Should you always trust “You have a private key that corresponds to this certificate”?

Our team regularly handles incidents dealing with SSL certificates. During the verification process for client (or server) SSL certificates, we tend to rely on the certificate UI to check if a given certificate has a valid private key. While doing some recent testing with the findprivatekey utility (
), I realized that trusting the UI was in fact a bad idea. Let’s take a simple example of a client certificate used for SSL client authentication:

Given the certificate’s thumbprint above, the findprivatekey utility allows us to display the private key location:

findprivatekey My CurrentUser -t “e3 bd c8 d3 0c c0 63 c6 89 68 3f 84 d0 dc af 62 41 0c 8c 53”
Private key directory:
Private key file name:

As an “experiment”, let’s rename the private key file:

Cd C:\Users\emmanubo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-1721254763-462695806-1538882281-36999
C:\Users\emmanubo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-1721254763-462695806-1538882281-36999>attrib 7f00fa7302a 28c328d1c0e78d51b744d_73d0bc64-45a4-4161-9a00-d6ffb76163e3 –s
C:\Users\emmanubo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-1721254763-462695806-1538882281-36999>ren 7f00fa7302a 28c328d1c0e78d51b744d_73d0bc64-45a4-4161-9a00-d6ffb76163e3 *.sau

Surprisingly, the certificate’s UI still shows that “You have a private key that corresponds to this certificate”!

And if we try to use the above client certificate in Internet Explorer for SSL client authentication, we’ll just get a generic failure after selecting the client certificate:

A network trace shows that client resets the TCP connection during the SSL handshake (instead of passing the client certificate to the server).

If you open a support incident with Microsoft, the support team will likely ask you to gather an ETL trace for schannel:

logman -start schannel -p {37D2C3CD-C5D4-4587-8531-4696C44244C8} 255 3 –ets
<reproduce the problem>
logman -stop schannel -ets

And the etl produced will point that the private key is missing:

[abstract of parsed schannel.etl]

[4] 02BC.0308::06/14/2012-14:06:28.314 A fatal error occurred when attempting to access the SSL client credential private key. The error code returned from the cryptographic module is 0x8009030D. The internal error state is 10003.
[4] 02BC.0308::06/14/2012-14:06:28.314 [sslproto] Credential_cpp191 CSslCredential::CreateCredential() – GetPrivateFromCert() FAILED: 0x8009030d

Conclusion: for basic SSL troubleshooting, consider using findprivatekey or certutil to check that certificate’s private key exists:

findprivatekey My CurrentUser -t “e3 bd c8 d3 0c c0 63 c6 89 68 3f 84 d0 dc af 62 41 0c 8c 53”
FindPrivateKey failed for the following reason:
Unable to obtain private key file name

certutil -v -user -store My “e3 bd c8 d3 0c c0 63 c6 89 68 3f 84 d0 dc af 62 41 0c 8c 53”
================ Certificate 1 ================
X509 Certificate:
Version: 3
Serial Number: 61580f4d000000000006

Missing stored keyset

We hope the above tricks will save you precious time!


Comments (3)

  1. VILL says:

    Thank you very much!!!

  2. John says:

    Yup, missing key found. UI said it was good and all. Great info!

  3. Mark says:

    Great post. I just found the same thing after the private key was deleted manually (not via the API): the GUI says it's still there. But… (in Windows 10 – not sure abut earlier versions) if you right click on the cert, select All Tasks and Manage Private Keys…, it will error if there's no key. Saves having to drop to the command line for those that doesn't like such things.