Reputation: 657
I am trying to learn about certificates, the need for that is from an idea I had a few days ago to simplify the ordering and delivery of SSL certificates to my collegues. So I startet to investigate "how hard can it be"?
And to large entusiasm, the entire process was "not so hard", but then I came to "generating pfx certificates", with private key...
The code is from a console test app:
Creating keys and storing it.
int keysize = 2048;
CngKeyCreationParameters ckcParams = new CngKeyCreationParameters()
{
ExportPolicy = CngExportPolicies.AllowPlaintextExport,
KeyCreationOptions = CngKeyCreationOptions.None,
KeyUsage = CngKeyUsages.AllUsages,
};
ckcParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(KeySize), CngPropertyOptions.None));
CngKey myCngKey = CngKey.Create(CngAlgorithm.Rsa, KeyName, ckcParams);
byte[] privatePlainTextBlob = myCngKey.Export(CngKeyBlobFormat.Pkcs8PrivateBlob);
string privateblob_string = Convert.ToBase64String(privatePlainTextBlob);
// Now I can save the Pkcs8PrivateBlob "somewhere"
Later I can pick up this up and create a Certificate Request and send it to a certificate service by API.
byte[] cngbytes = Convert.FromBase64String( privateblob_string );
CngKey importedkey = CngKey.Import(cngbytes, CngKeyBlobFormat.Pkcs8PrivateBlob, CngProvider.MicrosoftSoftwareKeyStorageProvider);
RSACng rsa = new RSACng(importedkey);
request = new CertificateRequest(
new X500DistinguishedName(order.CertName),
rsa,
HashAlgorithmName.SHA512,
RSASignaturePadding.Pkcs1);
etc....
Now I can download the issued certificate in various formats from the API.
So far so good. Now I want to create PFX file and KEY file.
Creating PFX:
// My issued certificate from provider
byte[] PublicKeyStr = System.Text.Encoding.ASCII.GetBytes(CER_STRING);
// pfx
var certificate = new X509Certificate2(PublicKeyStr, string.Empty, X509KeyStorageFlags.Exportable);
byte[] certificateData = certificate.Export(X509ContentType.Pfx, "password");
// Now I have the pfx, but no private key
I am obviously is not capable of solving this. I have been on a journey into Bouncy Castle, with no luck (btw: where is their documentation?).
I have noticed that .net5 has a metode that I thought (again) might solve this.
X509Certificate2.CreateFromPem(ReadOnlySpan certpem, ReadOnlySpan keypem)
But then I need to get the keypem "private key pem".
My question is simple: Have I totally misunderstod or is the any way to add the needed private key to the pfx file with the information I have stored from the CngKey?
ANY suggestions, ideas, help, tips will be very welcomed. It is simply so frustrating to be so close and just fail miserably.
Upvotes: 0
Views: 205
Reputation: 33238
You need to associate the public certificate with the private key before exporting it as a PFX.
// Key
byte[] cngbytes = Convert.FromBase64String( privateblob_string );
CngKey importedkey = CngKey.Import(cngbytes, CngKeyBlobFormat.Pkcs8PrivateBlob, CngProvider.MicrosoftSoftwareKeyStorageProvider);
RSACng rsa = new RSACng(importedkey);
// Cert
byte[] PublicKeyStr = System.Text.Encoding.ASCII.GetBytes(CER_STRING);
var certificate = new X509Certificate2(PublicKeyStr);
// Together:
X509Certificate2 certWithKey = certificate.CopyWithPrivateKey(rsa);
// PFX:
byte[] pfx = certWithKey.Export(X509ContentType.Pfx, pwd);
Upvotes: 1