C# 如何验证签名,从CRT文件加载公钥?

C# 如何验证签名,从CRT文件加载公钥?,c#,cryptography,digital-signature,public-key-encryption,x509,C#,Cryptography,Digital Signature,Public Key Encryption,X509,我回顾了许多论坛和例子,但没有一个对我有帮助。我需要验证来自任何Web服务的签名。我有一个带有公钥的test.crt文件用于验证 static bool Verify(string text, string signature) { X509Certificate2 cert = new X509Certificate2( HttpContext.Current.Server.MapPath("test-server.cert")); RSACryptoServiceProv

我回顾了许多论坛和例子,但没有一个对我有帮助。我需要验证来自任何Web服务的签名。我有一个带有公钥的test.crt文件用于验证

static bool Verify(string text, string signature)
{
  X509Certificate2 cert = new X509Certificate2(
      HttpContext.Current.Server.MapPath("test-server.cert"));
  RSACryptoServiceProvider csp = (RSACryptoServiceProvider) cert.PublicKey.Key;

  // Hash the data
  SHA1Managed sha1 = new SHA1Managed();
  UnicodeEncoding encoding = new UnicodeEncoding();
  byte[] data = encoding.GetBytes(text);
  byte[] sign = Convert.FromBase64String(signature);
  byte[] hash = sha1.ComputeHash(data);

  return csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), sign);
}
但结果总是错误的:(

我有一个OpenSSL示例:

openssl base64 -d -in signature -out signature.bin
openssl dgst -sha1 -verify test-server.pub -signature signature.bin from_gateway

我怀疑使用Unicode编码可能是失败的原因。如下所示,由于ASCII是8位编码,而在Windows中Unicode编码是16位宽的,所以使用Unicode编码和Unicode编码的字节不同。在您的另一个问题中,您使用了Asciencoding。因此假设签名是在Asciencoding上计算的文本/字符串的字节数和使用Unicode编码验证的字节数显然不匹配

string text = "Hello";
Console.WriteLine("ASCIIEncoding bytes length: {0}", new ASCIIEncoding().GetBytes(text).Length);
Console.WriteLine("UnicodeEncoding bytes length: {0}", new UnicodeEncoding().GetBytes(text).Length);
输出

ASCIIEncoding bytes length: 5
UnicodeEncoding bytes length: 10

我创建了一个简单的应用程序,可以为文本生成签名并立即进行验证。您可以在此处进行检查:因此,上面的方法很好。您确定您使用了正确的证书进行签名和验证吗?我对web应用程序也这样做,因此它不是web内容。如何将签名从web服务传递到您的应用程序?@drup是吗确定签名是正确的吗?因为这里你说你不能得到签名:我看不出代码有任何错误,所以检查你的输入。例如,我可以看到你似乎在你的C#代码中使用了openssl的二进制签名和base64编码的签名。任何错误的字符编码也会起作用,你似乎认为openssl采用ASCII假设采用16位Unicode(让微软称编码为“Unicode”,有时他们可能是如此愚蠢)。