无法将带有私钥的生成证书导出到.net 4.0/4.5中的字节数组

本文关键字:net 数组 字节数 字节 私钥 证书 | 更新日期: 2023-09-27 18:12:41

我需要导出和导入生成的证书与私钥和字节数组,我没有任何问题,除非我使用。net框架4.0和4.5。我用BouncyCastle库生成自签名证书,然后将它们转换为。net格式(X509Certificate2对象)。不幸的是,升级到最新的框架后,我无法导出私钥。下面是代码:

using System;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
namespace X509CertificateExport
{
    class Program
    {
        static void Main(string[] args)
        {
            var certificate = Generate();
            var exported = certificate.Export(X509ContentType.Pfx);
            var imported = new X509Certificate2(exported, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
            Console.WriteLine("Certificate has private key: " + imported.HasPrivateKey);
            Console.ReadKey();
        }
        public static X509Certificate2 Generate()
        {
            var keyPairGenerator = new RsaKeyPairGenerator();
            var secureRandom = new SecureRandom(new CryptoApiRandomGenerator());
            keyPairGenerator.Init(new KeyGenerationParameters(secureRandom, 1024));
            var keyPair = keyPairGenerator.GenerateKeyPair();
            var publicKey = keyPair.Public;
            var privateKey = (RsaPrivateCrtKeyParameters)keyPair.Private;
            var generator = new X509V3CertificateGenerator();
            generator.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));
            generator.SetSubjectDN(new X509Name("CN=Test"));
            generator.SetIssuerDN(new X509Name("CN=Test"));
            generator.SetNotAfter(DateTime.Now + new TimeSpan(10, 10, 10, 10));
            generator.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
            generator.SetSignatureAlgorithm("MD5WithRSA");
            generator.SetPublicKey(publicKey);
            var newCert = generator.Generate(privateKey);
            var dotNetPrivateKey = ToDotNetKey(privateKey);
            var dotNetCert = new X509Certificate2(DotNetUtilities.ToX509Certificate(newCert));
            dotNetCert.PrivateKey = dotNetPrivateKey;
            return dotNetCert;
        }
        public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
        {
            var rsaProvider = new RSACryptoServiceProvider();
            var parameters = new RSAParameters
            {
                Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
                P = privateKey.P.ToByteArrayUnsigned(),
                Q = privateKey.Q.ToByteArrayUnsigned(),
                DP = privateKey.DP.ToByteArrayUnsigned(),
                DQ = privateKey.DQ.ToByteArrayUnsigned(),
                InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
                D = privateKey.Exponent.ToByteArrayUnsigned(),
                Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
            };
            rsaProvider.ImportParameters(parameters);
            return rsaProvider;
        }
    }
}

仔细查看生成的证书后,我注意到PrivateKey.CspKeyContainerInfo.Exportable标志对于。net框架3.5是true,但对于以后的版本,它会抛出:

'Exportable' threw an exception of type
'System.Security.Cryptography.CryptographicException' / Key does not exist

我看到的唯一区别是在PrivateKey.CspKeyContainerInfo.m_parameters.Flags:.NET 3.5 - 'NoFlags';. net 4.5 - 'CreateEphemeralKey'文档说明'CreateEphemeralKey'创建一个临时密钥,该密钥在相关的RSA对象关闭时释放。它是在4.0框架中引入的,以前并不存在。我试图通过显式地创建CspParameters来摆脱这个标志:

public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
{
    var cspParams = new CspParameters
    {
        Flags = CspProviderFlags.UseMachineKeyStore
    };
    var rsaProvider = new RSACryptoServiceProvider(cspParams);
    // ...

但运气不好。'CreateEphemeralKey'无论如何都添加了,所以我得到的结果是UseMachineKeyStore | CreateEphemeralKey标志,我不知道如何删除它。是否有一种方法可以忽略此标志并正常导出带有私钥的证书?

无法将带有私钥的生成证书导出到.net 4.0/4.5中的字节数组

我没有注意到CspKeyContainerInfo.CspParameters.KeyContainerName在。net 4.0和。net 4.5中创建密钥后为空,但它在。net 3.5中自动生成。我已经为容器设置了唯一的名称,现在我可以导出私钥了。

public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
{
    var cspParams = new CspParameters
    {
          KeyContainerName = Guid.NewGuid().ToString(),
          KeyNumber = (int)KeyNumber.Exchange,
          Flags = CspProviderFlags.UseMachineKeyStore
    };
    var rsaProvider = new RSACryptoServiceProvider(cspParams);
    // ...