I want to create a X509Certificate2 object based on a PEM file. The problem is setting the PrivateKey property of X509Certificate2. I read X509Certificate2.CreateFromCertFile() on .NET Core and then used
var rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(pvk);
Where pvk
is the byte array of the private key (read from GetBytesFromPEM as shown here how to get private key from PEM file?), to set the private key, but then I get an
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException with message Bad Version of provider.
How can I properly set the PrivateKey of the X509Certificate2 based on the private key in the PEM file?
If I look at Creating the X509Certificate2, they use
RSACryptoServiceProvider prov = Crypto.DecodeRsaPrivateKey(keyBuffer);
certificate.PrivateKey = prov;
which seems like a neat way to do this, but this does not work in .Net Core...
If you've just extracted the bytes from the Base64 encoding of the private key file you have a PKCS#1, PKCS#8, or encrypted PKCS#8 private key blob (depending on if it said "BEGIN RSA PRIVATE KEY", "BEGIN PRIVATE KEY" or "BEGIN ENCRYPTED PRIVATE KEY").
ImportCspBlob
wants a custom format for the data, and that's why it's complaining.Digital signature in c# without using BouncyCastle has an explanation of ways forward. The easiest / most formulaic is to just make a PFX with the cert and key, and let the
X509Certificate2
constructor do its thing.If you go the route of loading the key object directly then the way you would mate a private key with the certificate is to use one of the new
CopyWithPrivateKey
extension methods. This returns a new instance ofX509Certificate2
which knows about the private key.The
PrivateKey
setter was "removed" from .NET Core because it has a lot of side effects on Windows that are hard to replicate on Linux and macOS, particularly if you retrieved the certificate out of an instance of X509Store.This code is a combination of overly strict and overly accepting for real BER rules, but this should read validly encoded PKCS#8 files unless they included attributes.