RSACryptoServiceProvider

RSACryptoServiceProvider

我有一个 X509Certificate2 实例,并获取它的 PrivateKey 属性,它是一个 RsaCryptoServiceProvider 。 MSDN 文档说明此 RsaCryptoServiceProvider 类不是线程安全的。因此,如果给定一些 X.509 证书,我需要在多个线程上执行非对称加密(通常在 Web 服务器上),那么创建 RsaCryptoServiceProvider 的多个实例的最佳方法是什么?
X509Certificate2 上的私钥未标记为可导出,因此我不能简单地导出原始 RsaCryptoServiceProvider 上的参数并将它们重新导入另一个实例以解决线程安全问题。

我通过 X509Store 获得了原始代码,但这似乎是 X509Certificate2 实例的集合,因此如果我想要一个新的 RsaCryptoServiceProvider 实例,我必须实例化一个新的 X509Store 以找到一个新的 X509Certificate2 ,以获得一个新的 RsaCryptoServiceProvider 。仅仅让 .NET 克隆 RsaCryptoServiceProvider 实例似乎非常重量级。

有没有更好的方法?

最佳答案

尽管 RsaCryptoServiceProvider 的 MSDN 文档说明它不是线程安全的,但似乎 ojit_code 的线程安全性足以同时在多个线程上加密/解密。我编写了以下应用程序来使用此类测试高并发性,并且它根本没有崩溃或无法正确加密/解密:

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);
        }
    }
}

关于asp.net - 缓解 Web 服务器上的 RsaCryptoServiceProvider 线程安全问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6140764/

10-08 21:51