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:
Was the certificate/private key somehow automatically installed on my machine by openssl when I created it?
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!