C# - 根据 byte[] 中给定的颁发者证书生成 X509 证书
C# - Generate X509 Certificate based on a given issuer certificate in byte[]
我想从 C# 代码创建 iothub 设备证书。根 CA 作为 .pfx 存储在 keyvault 中,作为字符串获取,然后从 base 64 转换以获得存储在 keyvault 中的证书所需的证书字节:
我想编写一个函数,它将获取这些字节以及主题名称(用于叶证书),并将创建一个 x509 证书(具有 public 和私钥)作为根的发行者。
这是我到目前为止的草图:
public static X509Certificate2 GenerateCertificateBasedOnIssuer(string subjectName, byte[] issuerByteCert)
{
var issuerCertificate = new X509Certificate2(issuerByteCert);
RSA keyProvider = issuerCertificate.GetRSAPrivateKey();
CertificateRequest certificateRequest = new CertificateRequest($"CN={subjectName}", keyProvider, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
var publicOnlyDeviceCertificate = certificateRequest.Create(issuerCertificate, issuerCertificate.NotBefore, issuerCertificate.NotAfter, serialNumber.ToByteArray());
return publicOnlyDeviceCertificate; // oh no ! :(
}
我在这个解决方案中遇到的问题是创建的证书只包含一个 public 密钥。
我找到了另一个解决方案,似乎可以使用 BouncyCastle
的 X509V3CertificateGenerator
解决我在另一个 Stack Overflow 问题上的问题:Generate a self-signed certificate on the fly
此解决方案的问题是我无法将 rootCA 证书的私钥转换为 AsymmetricKeyParameter
(X509V3CertificateGenerator.Generate
方法的第一个参数)。我尝试使用此解决方案将发行者的密钥转换为 AsymmetricKeyParameter
:,但我遇到了无效操作异常。
我想知道我是否在正确的道路上(就理解而言)以及是否有一种方法可以根据我目前的代码生成带有私钥(和 public 密钥)的证书到位了。
更新:我已经能够通过硬编码密钥将私钥转换为 AsymmetricKeyParameter,如下所示:
string testKey = @"-----BEGIN PRIVATE KEY-----
<THE KEY>
-----END PRIVATE KEY-----
";
var stringReader = new StringReader(testKey);
var pemReader = new PemReader(stringReader);
var pemObject = pemReader.ReadObject();
var keyParam = ((AsymmetricKeyParameter)pemObject);
Azure keyvault 以 pfx 格式存储证书。我正在考虑将私钥存储为秘密字符串。我现在将继续使用硬编码密钥进行测试,直到找到可行的解决方案。
我现在正在使用 BouncyCastle
进行测试,如果可行,我会回来提供可行的解决方案!
您传递给 CertificateRequest
的密钥用作证书中的 public 密钥...所以您要传递一个新密钥,而不是发行者的密钥。
然后,一旦您有了主题密钥,您就可以在最后使用 CopyWithPrivateKey 将它们粘合在一起。
public static X509Certificate2 GenerateCertificateBasedOnIssuer(string subjectName, byte[] issuerByteCert)
{
using (var issuerCertificate = new X509Certificate2(issuerByteCert))
using (RSA subjectKey = RSA.Create(2048))
{
CertificateRequest certificateRequest = new CertificateRequest($"CN={subjectName}", subjectKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
var publicOnlyDeviceCertificate = certificateRequest.Create(issuerCertificate, issuerCertificate.NotBefore, issuerCertificate.NotAfter, serialNumber.ToByteArray());
using (publicOnlyDeviceCertificate)
{
return publicOnlyDeviceCertificate.CopyWithPrivateKey(subjectKey);
}
}
我想从 C# 代码创建 iothub 设备证书。根 CA 作为 .pfx 存储在 keyvault 中,作为字符串获取,然后从 base 64 转换以获得存储在 keyvault 中的证书所需的证书字节:
我想编写一个函数,它将获取这些字节以及主题名称(用于叶证书),并将创建一个 x509 证书(具有 public 和私钥)作为根的发行者。
这是我到目前为止的草图:
public static X509Certificate2 GenerateCertificateBasedOnIssuer(string subjectName, byte[] issuerByteCert)
{
var issuerCertificate = new X509Certificate2(issuerByteCert);
RSA keyProvider = issuerCertificate.GetRSAPrivateKey();
CertificateRequest certificateRequest = new CertificateRequest($"CN={subjectName}", keyProvider, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
var publicOnlyDeviceCertificate = certificateRequest.Create(issuerCertificate, issuerCertificate.NotBefore, issuerCertificate.NotAfter, serialNumber.ToByteArray());
return publicOnlyDeviceCertificate; // oh no ! :(
}
我在这个解决方案中遇到的问题是创建的证书只包含一个 public 密钥。
我找到了另一个解决方案,似乎可以使用 BouncyCastle
的 X509V3CertificateGenerator
解决我在另一个 Stack Overflow 问题上的问题:Generate a self-signed certificate on the fly
此解决方案的问题是我无法将 rootCA 证书的私钥转换为 AsymmetricKeyParameter
(X509V3CertificateGenerator.Generate
方法的第一个参数)。我尝试使用此解决方案将发行者的密钥转换为 AsymmetricKeyParameter
:
我想知道我是否在正确的道路上(就理解而言)以及是否有一种方法可以根据我目前的代码生成带有私钥(和 public 密钥)的证书到位了。
更新:我已经能够通过硬编码密钥将私钥转换为 AsymmetricKeyParameter,如下所示:
string testKey = @"-----BEGIN PRIVATE KEY-----
<THE KEY>
-----END PRIVATE KEY-----
";
var stringReader = new StringReader(testKey);
var pemReader = new PemReader(stringReader);
var pemObject = pemReader.ReadObject();
var keyParam = ((AsymmetricKeyParameter)pemObject);
Azure keyvault 以 pfx 格式存储证书。我正在考虑将私钥存储为秘密字符串。我现在将继续使用硬编码密钥进行测试,直到找到可行的解决方案。
我现在正在使用 BouncyCastle
进行测试,如果可行,我会回来提供可行的解决方案!
您传递给 CertificateRequest
的密钥用作证书中的 public 密钥...所以您要传递一个新密钥,而不是发行者的密钥。
然后,一旦您有了主题密钥,您就可以在最后使用 CopyWithPrivateKey 将它们粘合在一起。
public static X509Certificate2 GenerateCertificateBasedOnIssuer(string subjectName, byte[] issuerByteCert)
{
using (var issuerCertificate = new X509Certificate2(issuerByteCert))
using (RSA subjectKey = RSA.Create(2048))
{
CertificateRequest certificateRequest = new CertificateRequest($"CN={subjectName}", subjectKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
var publicOnlyDeviceCertificate = certificateRequest.Create(issuerCertificate, issuerCertificate.NotBefore, issuerCertificate.NotAfter, serialNumber.ToByteArray());
using (publicOnlyDeviceCertificate)
{
return publicOnlyDeviceCertificate.CopyWithPrivateKey(subjectKey);
}
}