2011-05-26 75 views
3

我有一個X509Certificate2實例,並獲取其PrivateKey屬性,該屬性爲RsaCryptoServiceProvider。 MSDN文檔RsaCryptoServiceProvider類是而不是線程安全。因此,如果給定一些X.509證書,我需要在多個線程上執行不對稱加密(通常在Web服務器上),那麼創建RsaCryptoServiceProvider的多個實例的最佳方法是什麼?緩解Web服務器上的RsaCryptoServiceProvider線程安全問題

X509Certificate2上的私鑰未標記爲可導出,因此我無法簡單地將原始RsaCryptoServiceProvider上的參數導出並將其重新導入到另一個實例中,以便解決線程安全問題。

我通過X509Store獲得的原始,但似乎是X509Certificate2實例的集合,例如,如果我想的RsaCryptoServiceProvider一個新的實例我有實例化一個X509Store找到X509Certificate2,以獲得RsaCryptoServiceProvider。它似乎非常重量級,只是讓.NET克隆RsaCryptoServiceProvider實例。

有沒有更好的方法?

回答

1

看起來RsaCryptoServiceProvider儘管其MSDN文檔聲明它不是線程安全的,但線程安全性足以在一次對多個線程進行加密/解密。我寫了下面的應用程序中使用這個類來測試高併發,到現在也沒有損毀或失效加密/解密正確可言:

using System; 
using System.Diagnostics; 
using System.Linq; 
using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates; 
using System.Threading; 

namespace ConsoleApplication1 { 
    class Program { 
     static bool exit; 

     static void Main(string[] args) { 
      var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
      try { 
       store.Open(OpenFlags.OpenExistingOnly); 

       Func<RSACryptoServiceProvider> rsaFactory = null; 
       X509Certificate2 winningCert = null; 
       exit = true; 
       foreach (X509Certificate2 cert in store.Certificates) { 
        try { 
         var result = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false).Cast<X509Certificate2>().FirstOrDefault(); 
         rsaFactory =() => (RSACryptoServiceProvider)result.PrivateKey; 
         UseRsa(rsaFactory()); 
         winningCert = cert; 
         break; 
        } catch (CryptographicException) { 
         Console.WriteLine("Cert {0} failed", cert.Thumbprint); 
        } 
       } 

       exit = false; 
       Console.WriteLine("Winning cert: {0}", winningCert.Thumbprint); 
       RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)winningCert.PrivateKey; 
       rsaFactory =() => rsa; 
       Thread[] threads = new Thread[16]; 
       for (int i = 0; i < threads.Length; i++) { 
        threads[i] = new Thread(state => UseRsa(rsaFactory())); 
        threads[i].Start(); 
       } 

       Thread.Sleep(10000); 

       exit = true; 
       for (int i = 0; i < threads.Length; i++) { 
        threads[i].Join(); 
       } 

       Console.WriteLine("Success."); 
      } finally { 
       store.Close(); 
      } 
     } 

     static void UseRsa(RSACryptoServiceProvider rsa) { 
      var rng = RandomNumberGenerator.Create(); 
      var buffer = new byte[64]; 

      do { 
       rng.GetBytes(buffer); 
       var cipher = rsa.Encrypt(buffer, true); 

       var plaintext = rsa.Decrypt(cipher, true); 
       for (int i = 0; i < buffer.Length; i++) { 
        if (buffer[i] != plaintext[i]) { 
         Debugger.Break(); 
        } 
       } 
      } while (!exit); 
     } 
    } 
} 
+1

我認爲這是工作的原因是,無論X509Certificate2.PrivateKey和X509Certificate2 .PublicKey.Key在每個調用中創建新的RSACryptoServiceProvider實例。 – liwp 2012-11-29 13:53:50