.NET Standard - Merge a certificate and a private

2019-01-28 01:44发布

问题:

Is there any way to combine a certificate and a key (both received separately as Base64 strings from a service) into a .pfx file using C#/.NET Standard programmatically? Using a tool is not an option, since I need to automate it.

The context: I need to load a certificate and a private key (separate Base64 strings without headers and footers) to a X509Certificate2 object to pass it on to the app from a .NET Standard 1.6 library. The problem is, there is no PrivateKey property in the X509Certificate2 class in .NET Standard! So the only way for me to actually load the private key in a X509Certificate2 object is to combine it with the certificate itself in a .pfx file and load it like that in a constructor.

回答1:

There's not a way to do this with framework types. It may be possible with BouncyCastle, or other libraries.

.NET Core 2.0 has added the ability to merge a certificate and a key object together (into a new X509Certificate2 object) via extension methods:

X509Certificate2 mergedCert = cert.CopyWithPrivateKey(rsaPrivateKey);
X509Certificate2 mergedCert = cert.CopyWithPrivateKey(dsaPrivateKey);
X509Certificate2 mergedCert = cert.CopyWithPrivateKey(ecdsaPrivateKey);

But that requires compiling specifically for netcoreapp20 (not netstandard20).

The framework types also don't have a way of loading key objects from binary representations (with the exception of CngKey.Import, but that only works on Windows), only from the pre-parsed structures (RSAParameters, DSAParameters, ECParameters).

The easiest way to accomplish this goal on Linux (if BouncyCastle can't help you out) is to use System.Process to spawn a call similar to openssl pkcs12 -export -out tmp.pfx -in tmp.cer -inkey tmp.key -password pass:"".

On Windows you could maybe use CngKey.Import and P/Invoke CertSetCertificateContextProperty (for CERT_NCRYPT_KEY_HANDLE_PROP_ID (78)) to then call cert.Export on the mutated certificate.