I want to create iothub device certificates from C# code. The root CA is stored in keyvault as a .pfx, fetched as a string, and then converted from base 64 in order to obtain the certificate bytes as it is required for a certificate stored in keyvault: Azure Key Vault Certificates does not have the Private Key when retrieved via IKeyVaultClient.GetCertificateAsync
I want to write a function that will take these bytes, along with a subject name (for the leaf certificate) and will create a x509 certificate (with both public and private keys) that would have the issuer as the root.
Here is what I have sketched so far:
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 ! :(
}
The issue I am having with this solution is that the created certificate only contains a public key.
I found another solution that appears to solve my problem on another Stack Overflow question using BouncyCastle
's X509V3CertificateGenerator
: Generate a self-signed certificate on the fly
The issue I have with this solution is that I cannot convert my rootCA certificate's private key to an AsymmetricKeyParameter
(first parameter of the X509V3CertificateGenerator.Generate
method). I tried converting the issuer's key to AsymmetricKeyParameter
using this solution: convert PEM encoded RSA public key to AsymmetricKeyParameter, but I got an invalid operation exception.
I was wondering if I was on the right path (as far as understanding goes) and if there is a way to generate a certificate with a private (and public key) based on the code I currently have in place.
UPDATE: I have been able to convert a private key to an AsymmetricKeyParameter by hardcoding the key as follows:
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 stores certificate in a pfx format. I am thinking of storing the private key as a secret string. I will keep testing with an hardcoded key for now until I get to a working solution.
I am now testing with BouncyCastle
and will come back with a working solution if it works!