对密码学知之甚少我对看似简单的任务有很大的疑问。
我有.pem证书,数据字节和该数据的签名。 我想检查是否有人通过将数据与签名进行匹配来更改数据。
我的尝试:
private bool VerifySignature(byte[] data, byte[] signature)
{
try
{
X509Certificate certificate = new X509Certificate("cert_filename.pem");
if (certificate == null)
return false;
DSACryptoServiceProvider dsa = (DSACryptoServiceProvider)certificate.PublicKey.Key;
return dsa.VerifyData(data, signatureData);
}
catch
{
return false;
}
}
但它给了我一个错误
'不支持'证书密钥算法' (System.NotSupportedException)。
查看加载的证书,它表示签名算法是'sha1ecdsa'。
我正在尝试仅针对签名验证数据。我在这里错过了什么? 我想在没有任何外部解决方案的情况下这样做,因为它似乎是非常简单的任务。
更新:我正在尝试实现与以下Java代码相同的功能:
private boolean verify(byte[] data, byte[] signature)
{
boolean isLicenseCorrect = false;
Signature sig = Signature.getInstance("SHA1WithECDSA");
sig.initVerify(certificate.getPublicKey());
sig.update(data);
return sig.verify(signature);
}
答案 0 :(得分:6)
虽然DSA和ECDSA是相关的,但它们并不相同。为什么不试试ECDsaCryptoServiceProvider
?请注意,ECDSA对椭圆曲线的支持仅包括NIST命名曲线。
答案 1 :(得分:0)
.NET 4.6.1增加了对ECDSA的改进支持。虽然我不喜欢你的捕获 - 一切都是假的,我会把它留在这里进行比较:
private bool VerifySignature(byte[] data, byte[] signature)
{
try
{
// new cannot return null, so no point in a null check. It would have thrown.
using (X509Certificate certificate = new X509Certificate("cert_filename.pem"))
using (ECDsa ecdsa = certificate.GetECDsaPublicKey())
using (RSA rsa = certificate.GetRSAPublicKey())
// Improved DSA is 4.6.2
{
// You said the cert was ECDSA-SHA1, but that doesn't mean the original data was.
// I assumed it was.
if (ecdsa != null)
return ecdsa.VerifyData(data, signature, HashAlgorithmName.SHA1);
if (rsa != null)
return rsa.VerifyData(data, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
return false;
}
}
catch
{
return false;
}
}
请注意,在.NET 4.6中,RSA基类定义了Sign / Verify方法,而在4.6.1中,ECDsa基类也得到了类似的处理。除非加载预先存在的命名密钥,否则新代码不应该讨论* CryptoServiceProvider类型。
值得注意的是,当公钥不属于该算法类型时,Get [Algorithm] PublicKey方法返回null
,因此需要进行空检查。