2016-03-29 49 views
3

以下函數使用證書進行簽名和驗證。如何使用c#密碼檢索簽名散列算法友好名稱?

private static bool Sign_Verify(X509Certificate2 x509, byte[] random_data) 
     { 
      // 
      // Local variable definitions 
      // 
      bool isVerified = false; 
      byte[] buffer = Encoding.Default.GetBytes("Hello World ... !"); 
      byte[] signature_Data = null; 
      byte[] signature_Hash = null; 
      // 
      // Retrieve the private key of the certificate selected. 
      // 
      RSACryptoServiceProvider privateKey 

            = x509.PrivateKey as RSACryptoServiceProvider; 

     if (null == privateKey) 
     { 
      Console.WriteLine("Invalid Private Key"); 
     } // if 
     else 
     { 
      Console.WriteLine("Certificate has private key."); 
     } // else 

     HashAlgorithm hashAlgo = HashAlgorithm.Create("SHA256"); 

     byte[] hash = hashAlgo.ComputeHash(random_data); 

     // 
     // Perform signing using the private key 
     try 
     { 
      signature_Hash = privateKey.SignHash(
                hash, 
                CryptoConfig.MapNameToOID("SHA256")); 
      if (null == signature_Hash) 
      { 
       Console.WriteLine("Error: SignHash\n\n"); 
      } // if 
      else 
      { 
       Console.WriteLine("Signature_Hash generated......\n\n"); 
      } // else 
     } // try 
     catch (CryptographicException) 
     { 
      //e.StackTrace(); 
     } // catch 

     // 
     // Retrieve the public key of the certificate selected. 
     // 
     RSACryptoServiceProvider publicKey 

            = x509.PublicKey.Key as RSACryptoServiceProvider; 
     if (null == publicKey) 
     { 
      Console.WriteLine("Invalid Public Key"); 
     } // if 
     else 
     { 
      Console.WriteLine("Certificate has public key."); 
     } // else 


     isVerified = publicKey.VerifyHash(
               hash, 
               CryptoConfig.MapNameToOID("SHA256"), 
               signature_Hash); 
     if (false == isVerified) 
     { 
      Console.WriteLine("Signature of Hash verification failed."); 
     } // if 
     else 
     { 
      Console.WriteLine("Signature of Hash verified successfully."); 
     } // else 

     return isVerified; 
    } // Sign_Verify 

在HashAlgorithm.Create(「SHA256」); ,我們對簽名散列算法的名稱進行了硬編碼。如何獲得證書的簽名散列算法的名稱而不是硬編碼呢?

回答

1

似乎沒有簡單的方法從.NET中的證書獲取簽名散列算法。你可以做的是先拿到簽名算法OID

cert.SignatureAlgorithm.Value; 

然後,你需要以某種方式映射此OID(這可能是與RSA加密例如SHA256)到OID或只是散列算法的名稱,沒有加密(只是SHA256 )。你可以自己建立這樣的地圖,或者使用現有的地圖,例如Bouncy Castle圖書館有一個。不幸的是它包含在內部類中,所以你將不得不使用一些反射來實現它。所以,在此提及充氣城堡第一(通過的NuGet),則:

var mapField = typeof(Org.BouncyCastle.Cms.CmsSignedData).Assembly.GetType("Org.BouncyCastle.Cms.CmsSignedHelper").GetField("digestAlgs", BindingFlags.Static | BindingFlags.NonPublic); 
var map = (System.Collections.IDictionary) mapField.GetValue(null); 

這會搶內部CmsSignedHelper類,其中包含你需要的地圖的私人digestAlgs領域的價值。

然後你做:

var hashAlgName = (string)map[cert.SignatureAlgorithm.Value];// returns "SHA256" for OID of sha256 with RSA. 
var hashAlg = HashAlgorithm.Create(hashAlgName); // your SHA256 
+0

CmsSignedData和IDictionary的是有缺失的命名空間,我已經添加了命名空間System.Security.Cryptography.Pkcs;仍然是給出相同的缺少命名空間錯誤 – user5271376

+0

你能否告訴如果.Net Framework 4 0r 4.5支持Bouncy Castle庫,並且我從未使用過Boucny Castle庫 – user5271376

+0

當然可以。如果您使用nuget軟件包管理器 - 搜索「Bouncy Castle」並安裝該軟件包。如果你不使用nuget - 這是圖書館開發者網站上的直接鏈接 - http://www.bouncycastle.org/csharp/download/bccrypto-csharp-1.8.1-bin.zip。解壓縮並將引用添加到您的項目的dll。 – Evk