2011-05-26 60 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