Honey, I lost the (private) keys -- EFS keys missing?



Interesting EFS issue the other day..

Customer was rolling out EFS so they set up DRA's and this worked great. When they encrypted files the DRA's showed up just fine in the file information. However, when they went to decrypt a file via the assigned DRA account – it failed to recover the file.

Efsinfo.exe showed:

Users who can decrypt: 

      CUST\bob (bob(bob@CUST.com)

      Certificate thumbprint: A453 6DE7 2AB7 93EA DF34 D30E F542 FEF5 960E 56EF

Recovery Agents: 

  Unknown (DataRecoveryAgent1(JOE1@CUST.com)

    Certificate thumbprint: F456 453E F3E2 876A A435 5633 BF5A F45E F5DF 6C0B  

    Unknown (DataRecoveryAgent2(JOE2@CUST.com)

    Certificate thumbprint: FE23 4553 367E B94F 6F42 ED8F E3FB FEC5 C27D B32A


The user had the certificate imported to the user’s store:

Note the thumbprint ( hash ) shows on the file and is the same cert in our store.


certutil -store -v -user MY "F456 453E F3E2 876A A435 5633 BF5A F45E F5DF 6C0B"



    Key Container = {A1D09078-2F06-48B3-94EC-6DD4589068BC}


    Provider = Microsoft Enhanced Cryptographic Provider v1.0

    ProviderType = 1 

    Flags = 0

    KeySpec = 1 



Private key is NOT exportable

Encryption test passed



When you see “Encryption test passed” displayed by certutil.exe, this means that it successfully encrypted data via the public key and decrypted the data via the private key .


This is typically a good test to determine if you have access to the private key and you can use it. But, in this case the decryption\recovery was still failing.


Unfortunately, there is no logging in the security subsystem to determine why it was failing the recovery. After a debug we could see that it was failing in CryptAcquireContext with error 0x80090016 NTE_BAD_KEYSET


MSDN documentation states:

NTE_BAD_KEYSET( 0x80090016L )

The key container could not be opened. A common cause of this error is that the key container does not exist. To create a key container, call CryptAcquireContext using the CRYPT_NEWKEYSET flag. This error code can also indicate that access to an existing key container is denied. Access rights to the container can be granted by the key set creator by using CryptSetProvParam.

So why was certutil.exe able to encrypt and decrypt using this key?


Turns out that certutil.exe uses CryptAcquireCertificatePrivateKey whereas other code ( the EFS code ) goes to the certificate property, get the keyprovinfo, calls CryptAcquireContext with the CSP name and key container name.


typedef struct _CRYPT_KEY_PROV_INFO { LPWSTR pwszContainerName; LPWSTR pwszProvName; DWORD dwProvType; DWORD dwFlags; DWORD cProvParam; PCRYPT_KEY_PROV_PARAM rgProvParam; DWORD dwKeySpec;



Now, if the CRYPT_KEY_PROV_INFO is incorrect, or the container is incorrect this will fail.


In order to correct this information we ran:

                certutil -repairstore -user MY "F456 453E F3E2 876A A435 5633 BF5A F45E F5DF 6C0B"


The –repairstore fixed the problem of an incorrect container and we then can decrypt the files correctly.


Unfortunately, I never did get more information as to why or how we got into this state.. too bad. If someone runs into this and feels like helping me out – shoot me mail BEFORE you try and fix it like this J