![](/img/trans.png)
[英]BouncyCastle PrivateKey To X509Certificate2 PrivateKey
[英]How to create X509Certificate2 with PrivateKey in .NET Standard 2.0/Core 2.1?
我们正在生成一些自签名证书以使用 BouncyCastle 进行测试,但是当我们尝试向证书添加私钥时,代码会引发异常。 这是有问题的代码:
private static X509Certificate2 CreateCertificate(string subject, DateTimeOffset notBefore, DataTimeOffset notAfter, string issuer, AsymmetricKeyParamter issuerPrivateKey)
{
// Setup
X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
SecureRandom random = new SecureRandom(new CryptoApiRandomGenerator());
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(new KeyGenerationParameters(random, KeyStrength));
// Randomly generate a serial number
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
certGenerator.SetSerialNumber(serialNumber);
// Set the issuer and subject names
X509Name issuerName = new X509Name(issuer);
X509Name subjectName = new X509Name(subject);
certGenerator.SetIssuerDN(issuerName);
certGenerator.SetSubjectDN(subjectName);
// Set the validity period
certGenerator.SetNotBefore(notBefore.UtcDateTime);
certGenerator.SetNotAfter(notAfter.UtcDateTime);
// Randomly generate the public key
AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
certGenerator.SetPublicKey(subjectKeyPair.Public);
// Generate the signed certificate
ISignatureFactory signatureFactory = new Asn1SignatureFactory(SHA256RSASignatureAlgorithm, issuerPrivateKey ?? subjectKeyPair.Private, random);
X509Certificate2 certificate = new X509Certificate2(certGenerator.Generate(signatureFactory).GetEncoded());
// Include the private key with the response
// ERROR HERE!
certificate.PrivateKey = DotNetUtilities.ToRSA(subjectKeyPair.Private as RsaPrivateCrtKeyParameters);
return certificate;
}
此代码位于面向 .NET Standard 2.0 的库中,该库是两个不同应用程序的依赖项:一个面向 .NET Core 2.1,另一个面向 .NET Framework 4.7.2。 我相信这在 .NET Framework 应用程序中工作正常,但在 .NET Core 应用程序中,我在上面指示的行中收到此消息的异常:
此平台不支持操作。
显然, 这是 .NET Core 中的预期行为。 我知道这个问题中提到的CopyWithPrivateKey
方法,理论上我应该使用它。 但是, .NET Standard 2.0 不支持此方法(请注意页面顶部指示重定向的错误)。 此外,由于 .NET Framework 的其他一些依赖项,.NET Framework 应用程序目前无法转换为 .NET Core。 根据此矩阵,.NET Framework 根本不支持 .NET Standard 2.1,这意味着我无法升级到 .NET Standard 2.1并使用CopyWithPrivateKey
!
如何以与 .NET Core 兼容的方式在 .NET Standard 2.0 中创建带有私钥的X509Certificate2
?
经过大量挖掘,我找到的唯一解决方案是将证书转换为 PKCS12 格式的字节数组,附加私钥,然后将其读回X509Certificate2
对象。 这很糟糕,但据我所知,在 .NET Core 中,您可以使用私钥获取私钥的唯一方法是调用CopyWithPrivateKey
(如问题中所述,在 .NET Standard 2.0 中不可用)或加载包含私钥。 下面的代码可以做到这一点:
private static X509Certificate2 AddPrivateKeyPlatformIndependent(Org.BouncyCastle.X509.X509Certificate bouncyCastleCert, AsymmetricKeyParameter privateKey)
{
string alias = bouncyCastleCert.SubjectDN.ToString();
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
X509CertificateEntry certEntry = new X509CertificateEntry(bouncyCastleCert);
store.SetCertificateEntry(alias, certEntry);
// TODO: This needs extra logic to support a certificate chain
AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(privateKey);
store.SetKeyEntry(alias, keyEntry, new X509CertificateEntry[] { certEntry });
byte[] certificateData;
string password = GenerateRandomString();
using (MemoryStream memoryStream = new MemoryStream())
{
store.Save(memoryStream, password.ToCharArray(), new SecureRandom());
memoryStream.Flush();
certificateData = memoryStream.ToArray();
}
return new X509Certificate2(certificateData, password, X509KeyStorageFlags.Exportable);
}
使用它代替问题代码中的最后两行,而不是使用certGenerator
创建X509Certificate2
, certGenerator
使用它来创建等效的 Bouncy Castle Type 以传递给它: Org.BouncyCastle.X509.X509Certificate bouncyCastleCert = certGenerator.Generate(signatureFactory);
由于有关 Bouncy Castle 和 .NET 证书的文档充其量很少,因此我在此过程中发现了一些怪癖:
PKCS12 容器中证书条目和密钥条目的别名必须相同。 否则,您将在尝试使用私钥时收到“密钥集不存在”异常。
加载字节数组时必须使用X509KeyStorageFlags.Exportable
,否则根据您使用证书的方式,您可能会收到“密钥在指定状态下无效”异常。 这也意味着您必须提供密码,因为没有它就不会过载,但您可以使用任何旧字符串,因为它是临时密码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.