wly*_*les 4 c# .net-core .net-standard-2.0
我们正在生成一些自签名证书以使用 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;
}
Run Code Online (Sandbox Code Playgroud)
此代码位于面向 .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
如何X509Certificate2以与 .NET Core 兼容的方式在 .NET Standard 2.0 中使用私钥创建一个?
经过大量挖掘,我找到的唯一解决方案是将证书转换为 PKCS12 格式的字节数组,附加私钥,然后将其读回X509Certificate2对象。这很糟糕,但据我所知,在 .NET Core 中,获得私钥的唯一方法是调用CopyWithPrivateKey(在问题中提到的 .NET Standard 2.0 中不可用)或加载包含私有密钥的PKCS12 数据钥匙。下面的代码可以做到这一点:
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);
}
Run Code Online (Sandbox Code Playgroud)
使用它代替问题代码中的最后两行,而不是创建X509Certificate2with certGenerator,使用它来创建等效的 Bouncy Castle Type 以传递给它:Org.BouncyCastle.X509.X509Certificate bouncyCastleCert = certGenerator.Generate(signatureFactory);
由于有关 Bouncy Castle 和 .NET 证书的文档充其量很少,因此我在此过程中发现了一些怪癖:
PKCS12 容器中证书条目和密钥条目的别名必须相同。否则,您将在尝试使用私钥时收到“密钥集不存在”异常。
X509KeyStorageFlags.Exportable加载字节数组时必须使用,否则根据您使用证书的方式,您可能会收到“密钥在指定状态下无效”异常。这也意味着您必须提供密码,因为没有它就不会过载,但您可以使用任何旧字符串,因为它是临时密码。
| 归档时间: |
|
| 查看次数: |
1200 次 |
| 最近记录: |