29

I have an X509Certificate2 certificate in my store that I would like to export to a byte array with the private key. The certificate byte array has to be so that when I then later would import the certificate from the byte array the private key would have the private key with it.

I have tried many wayes but has not succeded to export the certificate with the private key.

X509Store store = new X509Store(StoreLocation.CurrentUser);      

store.Open(OpenFlags.ReadOnly);

X509Certificate2 cert = store.Certificates[1];

byte[] certBytes = cert.GetRawCertData(); // Obviously does not work!

Is it possible to successfully export the certificate with private key to a byte array?

Help is very appreciated.

Erik Larsson
  • 2,339
  • 4
  • 14
  • 14

2 Answers2

34

The Export function of the X509Certificate2 class allows you to export a certificate with the private key to a byte array.

The following code demonstrates exporting a certificate with the private key:

X509Store store = new X509Store(StoreLocation.CurrentUser);

store.Open(OpenFlags.ReadOnly);

X509Certificate2 cert = store.Certificates[1];

// Export the certificate including the private key.
byte[] certBytes = cert.Export(X509ContentType.Pkcs12);

To secure your exported certificate use the following overload of the Export function:

byte[] certBytes = cert.Export(X509ContentType.Pkcs12, "SecurePassword");

BEGIN EDIT

To import the certificate use the following code:

X509Certificate2 certToImport = new X509Certificate2(arr, "SecurePassword");

// To mark it as exportable use the following constructor:
X509Certificate2 certToImport = new X509Certificate2(arr, "SecurePassword", X509KeyStorageFlags.Exportable);
// certToImport.HasPrivateKey must be true here!!

X509Store store2 = new X509Store(StoreName.TrustedPublisher,
                                 StoreLocation.CurrentUser);
store2.Open(OpenFlags.MaxAllowed);

store2.Add(certToImport);
store2.Close();

END EDIT

Hans
  • 12,314
  • 2
  • 51
  • 57
  • Thanks for your answers, but I still have a problem, when I run your code and import it again I get HasPrivateKey = false. What could be the problem? – Erik Larsson Mar 21 '12 at 20:01
  • 1
    @ErikLarsson: I've updated my answer. Hope, this helps. The property HasPrivateKey is true on my machine. If I open MMC to export the imported certificate I am able to exort the private key, too. – Hans Mar 21 '12 at 20:47
  • For anyone finding this thread, note that if you want to export it again you need to set it while importing to be `Exportable`, see the next answer and also http://stackoverflow.com/questions/9358129/cryptographicexception-key-not-valid-for-use-in-specified-state-while-trying/9373407#9373407 – yoel halb May 02 '17 at 20:14
  • 4
    This will throw ```System.Security.Cryptography.CryptographicException: 'Key not valid for use in specified state.'``` for a .NET 4.6.2 console app. – Eivind Gussiås Løkseth Sep 20 '17 at 13:36
  • @EivindGussiåsLøkseth: Where exactly do you get the exception? – Hans Sep 21 '17 at 04:31
  • @Hans, the issue I had was not related to a specific .NET version. I had a pfx file with a private key that was not exportable, and that's why the code failed. Unfortunately I couldn't find my comment and delete it after discovering this. – Eivind Gussiås Løkseth Sep 21 '17 at 07:41
4

One reason for not getting the private key, could be that it has been marked as "Not Exportable" when it was originally added to CAPI. In that case, I don't believe that is any real way of getting it out.

Søren Mors
  • 906
  • 6
  • 4
  • 2
    No, that only means you need stronger techniques. If it can be used it can be exported. – Joshua Mar 27 '12 at 19:14
  • @Joshua No, when a certificate is marked as "Not Exportable" it can only be used to sign/decrypt your input through the operating system and the operating system returns the result. Therefore the private key can be used but is protected and cannot be exported. – fjch1997 Aug 26 '17 at 19:48
  • @fjch1997: Attach a debugger to lsass sometime. – Joshua Aug 26 '17 at 21:50
  • @Joshua It's not managed code that handles the private key when you get your certificate from the certificate storage – fjch1997 Aug 26 '17 at 22:15
  • @fjch1997: Meh. When you use a kernel debugger you prefer native code anyway. – Joshua Aug 27 '17 at 00:56
  • @Joshua Did a quick google search and there are indeed tools to peek into the memory and retrieve the private key. Thumb down to Microsoft for this... – fjch1997 Aug 27 '17 at 01:26