簡體   English   中英

無法使用私鑰將生成的證書導出到.NET 4.0 / 4.5中的字節數組

[英]Cannot export generated certificate with a private key to byte array in .NET 4.0/4.5

我需要使用私鑰導出和導入生成的證書到字節數組和從字節數組導入,除非我使用.NET framework 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;
        }
    }
}

仔細查看生成的證書后,我注意到對於.NET Framework 3.5,PrivateKey.CspKeyContainerInfo.Exportable標志是正確的,但對於以后的版本,它會拋出:

'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 UseMachineKeyStore | CreateEphemeralKey標志,我不知道如何刪除它。 有沒有辦法我可以忽略這個標志並通常用私鑰導出證書?

我沒有注意到在.NET 4.0和.NET 4.5中創建密鑰后CspKeyContainerInfo.CspParameters.KeyContainerName為空,但它是在.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);
    // ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM