2011-12-13 95 views
3

我需要申请和使用我公司的数字证书验证的字符串。 VerifyHash(散列,CryptoConfig.MapNameToOID(“SHA1”),签名);部分返回false,所以我得到“签名无效”错误。我究竟做错了什么?这个错误最可能的原因是什么?验证签名 - 是什么导致了“签名无效”错误?

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static byte[] Sign(string text, string certSubject) 
     { 
      X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); 
      X509Certificate2 myCert = null; 
      RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); 
      store.Open(OpenFlags.ReadOnly); 
      foreach (X509Certificate2 cert in store.Certificates.Find(X509FindType.FindBySubjectName, certSubject, false)) 
      { 
       myCert = cert; 
       break; 
      } 
      store.Close(); 
      if (myCert == null) 
      { 
       throw new Exception("Certificate not found: " + certSubject, null); 
      } 
      // Hash the data 
      SHA1Managed sha1 = new SHA1Managed(); 
      UnicodeEncoding encoding = new UnicodeEncoding(); 
      byte[] data = encoding.GetBytes(text); 
      byte[] hash = sha1.ComputeHash(data); 

      // Sign the hash 
      return provider.SignHash(hash, CryptoConfig.MapNameToOID("SHA1")); 
     } 

     static bool Verify(string text, byte[] signature, string certPath) 
     { 
      // Load the certificate we'll use to verify the signature from a file 
      X509Certificate2 cert = new X509Certificate2(certPath); 
      // Note: 
      // If we want to use the client cert in an ASP.NET app, we may use something like this instead: 
      // X509Certificate2 cert = new X509Certificate2(Request.ClientCertificate.Certificate); 

      // Get its associated CSP and public key 
      RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key; 

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

      // Verify the signature with the hash 
      return csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature); 
     } 

     static void Main(string[] args) 
     { 
      // Usage sample 
      try 
      { 
       // Sign text 
       byte[] signature = Sign("Test 123", "Ross cert"); 

       // Verify signature. 
       if (Verify("Test 123", signature, @"C:\...RossTest.cer")) 
       { 
        Console.WriteLine("SUCCESS! Signature verified"); 
       } 
       else 
       { 
        Console.WriteLine("ERROR: Signature not valid!"); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("EXCEPTION: " + ex.Message); 
      } 
      Console.ReadKey(); 
     } 
    } 
} 

回答

1

我会想象,问题是,在你的标志方法中,你会付出很多努力去获得myCert,但是从不使用它。您只需使用新创建的未初始化的RSACryptoServiceProvider进行签名。

我想像的store.Close()行后你想要的东西类似如下:

RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey; 
+0

谢谢克里斯。这是问题。顺便说一下我做的RSACryptoServiceProvider提供商=(的RSACryptoServiceProvider)myCert.PrivateKey; (而不是... PrivateKey.Key)。 – user1095808

+0

很酷。我根据你在你的验证方法与公钥东西有什么只是猜测的语法 - 我认为他们会返回同样的事情。我会更新我的答案以反映正确的用法。 – Chris

1
RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); 

这就是provider,当你签署的数据被分配的唯一地方。该代码意味着您只创建了一个全新的密钥对,即它不与您寻找的证书相关联。

当您确认您使用的证书(不是一个从你生成密钥对)的公钥对签名。由于它们不匹配,你永远不会得到有效的签名验证。

督察您需要与证书,不是任何密钥对相关联的私钥签名。

+0

感谢poupou。接得好。 – user1095808