5

I'm developing in a Windows environment.

My company functions as it's own certificate authority for internal-use https applications, and I've been issued a certificate from our system (for an internal-use only web server I've built).

Using certificate manager I am able to export the certificate. But, when exporting the certificate from certificate manager, the 'export private key' radio button is greyed out. <-- I've tried to address this without success.

Does anyone have any suggestions?

I'm developing in Node JS (with express).

Without this I cannot configure the sslOptions object for https.createServer.

Thank you!

208_man
  • 1,440
  • 3
  • 28
  • 59
  • The answer from Ian Boyd to this question: https://stackoverflow.com/questions/3914882/how-to-export-non-exportable-private-key-from-store/ will solve your problem. – Daniel K Aug 19 '21 at 10:43

4 Answers4

9

Recovering a certificate where the private key is marked as non-exportable

We needed to export the private key of our IIS7 SSL certificate in order to import it in a node.js HTTPS project operating on a different port under the same domain.

We realized that the certificate had lost its ability to export the private key. The certificate had recently been re-issued using the old CSR but somehow the new certificate’s private key was marked as non-exportable, while past certificates had exportable private keys. Luckily we had a previous certificate available with exportable private key to work with. There are guides on the internet that the following process might work without the old certificate but in our case it did not, possibly because the certificate was re-issued.

DISCLAIMER: the following process is not intrusive on your computer and requires a VM to work with. If it succeeds then your will get your private key exported. If it fails, then your only option would be to create a CSR with exportable private key and re-issue your certificate and re-configure your domains.

Using mmc we imported both certificates in Local Computer\Personal.

NOTE: THE PLACE THAT YOU IMPORT CERTIFICATES IS IMPORTANT!

enter image description here

We located the Thumbprint of the certificate with the non-exportable private key:

enter image description here

In this sample the thumb is 693867F321B5764E324F3FB8C5CBCE03CDA3C2A3.

IMPORTANT: THUMB MUST BE UPPERCASE !!!

At this point, depending on the root cause of your problem, we suggest starting a command prompt and enter the following command, as it might cure your problem:

certutil -repairstore my 693867F321B5764E324F3FB8C5CBCE03CDA3C2A3

If the problem is not cured and the private key remains non-exportable, continue...

Using PowerShell we identified the private key store and copied to C:\

enter image description here

$a = get-item cert:\LocalMachine\My\693867F321B5764E324F3FB8C5CBCE03CDA3C2A3
$a.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName

This command revealed the private key store to be:

00998a33dbff25a91050b3b1bf9001ef_a5968f4a-5244-4993-830a-363efe3adaed

Then using NirSoft PsExec64 we started an Elevated Command Prompt on System account and copied / decrypted the keystore to C:\ using /G and /H.

PsExec64.exe -s -i cmd
xcopy /G /H "C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys\00998a33dbff25a91050b3b1bf9001ef_a5968f4a-5244-4993-830a-363efe3adaed" c:\

enter image description here

We create a VMware and copied both certificates and the private key store:

enter image description here

Using MMC we imported both certificates into Local Computer\Personal:

enter image description here

enter image description here

During import, we made sure that for the certificate with the private key, we marked the private key as exportable:

enter image description here

So, both certificates were imported but as expected only one had the lock icon indicating it had a private key:

enter image description here

Using Power Shell on the VM, we got the Machine’s GUID from Microsoft Cryptography and used this GUID in order to copy the private key store to the proper location.

Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\ -Name MachineGuid

This returned: a73d2e44-7a45-486a-97d3-b9d97bf556fa. In the following command you need to replace the old computer's GUID with the new, the GUID is after the first dash (-). The command syntax is this:

Move-Item "C:\<certificate-store>_<old-computer-guid>" "C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys\<certificate-store>_<vm-computer-guid>"

So, according to the identifiers derived in previous steps, it should look like this:

Move-Item "C:\00998a33dbff25a91050b3b1bf9001ef_a5968f4a-5244-4993-830a-363efe3adaed" "C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys\00998a33dbff25a91050b3b1bf9001ef_a73d2e44-7a45-486a-97d3-b9d97bf556fa"

Then we run certutil using the thumb of the problematic certificate to repair it!

certutil -repairstore my 693867F321B5764E324F3FB8C5CBCE03CDA3C2A3

You should see something like this:

enter image description here

After refreshing MMC you will that both certificates have a private key icon:

enter image description here

So, go ahead and export the certificate with the private key:

enter image description here

SOS: MAKE SURE YOU MARK THE PRIVATE KEY AS EXPORTABLE !!!

enter image description here

enter image description here

Next copy the PFX file back to your node.js server computer and import it ON-TOP of the existing problematic certificate.

Once you import the new certificate you can delete the old.

Next re-export the certificate from your server, just for sanity check. You should see the Export Private Key that is not grayed out any more!

enter image description here

SOS: MAKE SURE YOU MARK THE PRIVATE KEY AS EXPORTABLE !!!

enter image description here

To export the private key for node.js we used DigiCert Utility tool:

enter image description here

To convert the PFX to PEM for node.js we used OpenSSL:

openssl pkcs12 -in www_xxx_com.pfx -clcerts -nokeys -out www_xxx_com.pem

To use the certificate is node.js create an SLL folder in your node.exe path and copy the following items in it:

  1. Private Key file (.key)
  2. Certificate file (.pem)
  3. Authority Certificate file (.crt)

NOTE: the authority certificate file is provided along with your certificate from your certificate provider.

enter image description here

Finally you may load the certificate and private key using the following code:

  var https_options = {
    key: fs.readFileSync("C:\\nodejs\\ssl\\www_xxx_com.key"),
    cert: fs.readFileSync("C:\\nodejs\\ssl\\www_xxx_com.pem"),
    ca: [
      fs.readFileSync('C:\\nodejs\\ssl\\DigiCertCA.crt')      
    ]
  };
  require('https').createServer(https_options, app).listen(PORT);

Or depending on where node.js is installed, edit the paths accordingly.

Elias
  • 452
  • 5
  • 11
  • I do not believe this works in Windows 2016/2019. See solutions in https://stackoverflow.com/questions/3914882/how-to-export-non-exportable-private-key-from-store/ – Daniel K Aug 19 '21 at 10:43
  • Wow. Very useful. Also my takeaway from this is that if a key exists in the windows certificate store with a private key, and that machine is compromised, we can assume the key is as well. That is all the lengths Microsoft goes to in order to make you think your certs are safe in the store are nothing but obfuscation. Is that about right? – Emperor Eto Jan 31 '23 at 03:00
1

I had the same issue.

Ran the command using CMD

 certutil –repairstore my serialnumber

You can find the serialnumber from the certificate details tab. Remove all the spaces before running the command.

Example

certutil –repairstore my 25oA445521C8E9

For more details

Check the link

Shemeemsha R A
  • 1,416
  • 16
  • 22
0

Possible reasons are:

  1. If your CA isn't a Microsoft one (or even if it is, but you created the certificate on another box), you exported the certificate only, without exporting the private key. For Windows, this means you have to export/import a .pfx or .p12 file (combined certificate and private key) as opposed to a .cer or .crt file (certificate only).

  2. Assuming your CA is a Microsoft one, the Allow private key to be exported wasn't enabled on the template used to issue your certificate.

  3. Again, assuming your CA is Microsoft, if you used the Advanced Operations -> Custom Request... option from the Certificate Manager and selected to Proceed without enrollment policy, you didn't enable Make private key exportable under the Private Key tab on the Certificate Properties dialog.

garethTheRed
  • 1,997
  • 13
  • 20
  • Thanks so much @garethTheRed. My teammate converted the certificate and key to .pem, something I'd done incorrectly, and not it all works. – 208_man Aug 24 '18 at 15:31
0

There is the possibility of a lack of access, I mean your key file has been stored at "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" and it's possible that to test some approaches you removed machine keys and took them somewhere as a backup, after you scenarios have been tested you need to restore those file at that moment you have to provide access to each file users like "Everyone", "System", "Administrator", "IIS_IUSR", etc...

after this those certificates are accessible in your IIS to assign those to any hosted sites,

I faced the same problem, I deleted the machine keys and those are in effect once server got restarted, once server restarted you associated SSL certificate are automatically removed because those files are not accessible by system in this case we have to provide access manually