Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read Private Key from PFX-file

I know, there are many posts about this, but still I cannot find a solution to get this to work. I have generated a PFX-file with openssl on my machine like this:

openssl x509 -req -days 365 -in "myReqest.csr" -signkey "myPrivateKey.pem" -out "myCertificate.crt"
openssl pkcs12 -export -out "myCertificate.pfx" -inkey "myPrivateKey.pem" -in "myCertificate.crt" -certfile "myCertificate.crt"

In my C# app, I access the private key like this:

var cert = new X509Certificate2("myCertificate.pfx", "myPassword");
cert.HasPrivateKey; // This is always true!
cert.PrivateKey; // Works on my machine (only)

This works perfectly fine (on my machine), but when I run the same code on another machine, it throws: "Key set not found", even though HasPrivateKey returns true! Shouldn't the private key be included in the *.pfx-file? Can you tell me:

  1. Was the certificate/private key somehow automatically installed on my machine by openssl when I created it?

  2. How can I read the private key from the *.PFX-file (or alternatively from the *.PEM-file)?

StackTrace of Exception:

at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContaier)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContaier, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameter)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()

Update:

I've found out, that the following does work:

// on my machine
// read certificate from file (exportable!)
X509Certificate2 cert = new X509Certificate2("filename.pfx", "password", X509KeyStorageFlags.Exportable)
// sign data etc.
((RSACryptoServiceProvider)cert.PrivateKey).SignData(...
// export private key to XML-file
File.WriteAllText("filename.xml", cert.PrivateKey.ToXmlString(true));

// on the other machine
// create new RSA object
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
// import private key from xml
rsa.FromXmlString(File.ReadAllText("filename.xml"));
// verify data etc.
rsa.VerifyData(...

However, to me, this is only a workaround, I would like to do it an a more conventional/standard compliant way!

like image 403
marsze Avatar asked Nov 25 '13 16:11

marsze


People also ask

Does a PFX file contain the private key?

A PFX file indicates a certificate in PKCS#12 format; it contains the certificate, the intermediate authority certificate necessary for the trustworthiness of the certificate, and the private key to the certificate. Think of it as an archive that stores everything you need to deploy a certificate.

Can you extract private key from certificate?

Go to: Certificates > Personal > Certificates. Right-click on the certificate you wish to export and go to All Tasks and hit Export. Hit Next on the Certificate Export Wizard to begin the process. Select “Yes, export the private key” and hit next.

How extract private key from PFX without password?

If you have a PFX file that contains a private key with a password, you can use OpenSSL to extract the private key without a password into a separate file, or create a new PFX file without a password.


1 Answers

You have to load the certificate like this:

X509Certificate2 cert = new X509Certificate2("a.pfx", "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet)

This post explains why http://paulstovell.com/blog/x509certificate2

like image 136
Bogdan Avatar answered Sep 24 '22 08:09

Bogdan