![](/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.