C# 无法将生成的带有私钥的证书导出到.NET 4.0/4.5中的字节数组
我需要将生成的带有私钥的证书导出到字节数组和从字节数组导入,并且我不会有任何问题,除非我使用.NET framework 4.0和4.5。我正在使用库生成自签名证书,然后将其转换为.NET格式(X509Certificate2对象)。不幸的是,升级到最新的框架后,我无法导出私钥。代码如下:C# 无法将生成的带有私钥的证书导出到.NET 4.0/4.5中的字节数组,c#,certificate,export,bouncycastle,C#,Certificate,Export,Bouncycastle,我需要将生成的带有私钥的证书导出到字节数组和从字节数组导入,并且我不会有任何问题,除非我使用.NET framework 4.0和4.5。我正在使用库生成自签名证书,然后将其转换为.NET格式(X509Certificate2对象)。不幸的是,升级到最新的框架后,我无法导出私钥。代码如下: using System; using System.Diagnostics; using System.Security.Cryptography; using System.Security.Crypto
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 framework 3.5是正确的,但对于更高版本,它抛出:
'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框架中引入的,以前不存在。我试图通过显式创建CSP参数来摆脱此标志:
public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
{
var cspParams = new CspParameters
{
Flags = CspProviderFlags.UseMachineKeyStore
};
var rsaProvider = new RSACryptoServiceProvider(cspParams);
// ...
但是没有运气。”“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);
// ...
此“修复程序”的可能副本还解决了以下错误:SSL证书添加失败,错误:1312指定的登录会话不存在。它可能已经被终止了。