Reading private key from PFX file

I know there are many posts about this, but still I cannot find a solution to make it work. I created a PFX file with openssl on my machine as follows:

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 # application, I access the private key as follows:

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

This works fine (on my machine), but when I run the same code on another computer, it throws: "Keyset not found" , although it HasPrivateKeyreturns true! Should the private key be included in the * .pfx file? Can you tell me:

  • Was the certificate / private key file somehow automatically installed on my computer using openssl when I created it?

  • How can I read the private key from a * .PFX file (or, alternatively, from a * .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 found out that the following works:

// 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, for me this is just a workaround, I would like to make it a more ordinary / standard way!

+4
source share
4 answers

There seems to be no direct way to do this in .NET. Therefore, I decided now to download the certificate directly from the certificate store:

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, CERTIFICATE_THUMB_PRINT, false);
if (certificates.Count == 0)
{
    // "Certificate not installed."
}
else
{
    certificate = certificates[0];
}
store.Close();

For this, of course, if necessary, install on a machine.

, , ( , , , , ).

+2

, , . , , , , .

(, ), !. . (, , ). , MSIL. (, Reflector), , , .

, - , , . , , , ( ..).

+3

( ), , , asp.net(.. ). X509KeyStorageFlags.MachineKeySet X509Certificate2, .

The reason this only happens when accessing the property PrivateKeyis because this is the first place where the actual CSP object is created to use the key.

+1
source

You need to download the certificate as follows:

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

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

+1
source

All Articles