What is a strong key protection in Windows?
Strong key protection is one of the most misunderstood features in Windows security. In this post I will attempt to demystify it. I will also try to address some of the misconceptions about this feature that I’ve come across on the security discussion lists and while assisting our support folks.
It all starts with Crypto… API Framework
Windows has two crypto API frameworks for persisting public/private key pairs. First one called Cryptographic API or CAPI and the second one called Cryptography Next Generation or CNG. Both define a set of flags for their APIs that can set extra levels of protection. Let’s call them Medium and High for the sake of this discussion.
The flags are CRYPT_USER_PROTECTED (Medium) and CRYPT_FORCE_KEY_PROTECTION_HIGH (High) passed to the CryptGenKey function in CAPI. In CNG, the flags are NCRYPT_UI_PROTECT_KEY_FLAG (Medium) and NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG (High) actually set on the NCRYPT_UI_POLICY structure that is used during a call to the NCryptSetProperty function. The same flags can be used during import of the key with CAPI and CNG.
It all starts with Crypto… Providers
It is important to understand that the API model itself doesn’t define what those flags actually mean or what it means when they are not used. A developer that implements a provider for these APIs makes that decision. For example, a particular provider can require whoever is trying to use a key to solve a Sudoku puzzle where difficulty goes up as the Medium and High protection is used.
Providers are modules that plug-in into the API framework and are actually responsible for key material storage and protection. In CAPI world providers were called Cryptographic Service Providers (CSPs) and in CNG they are called Key Storage Providers (KSPs). A provider could be purely software-based (for example Microsoft Windows in-box providers) or a hybrid of software and hardware (for example Smart Card or Hardware Security Module (HSM) provider).
Microsoft Provider Implementation
From Windows Vista/Windows Server 2008 on, Windows ships with a handful of CAPI and CNG software-based providers while earlier Windows versions are only supporting CAPI. Those providers implement key protection in a very similar way in respect to the strong key protection.
By default all private keys stored by Windows providers are protected by using DPAPI. See this MSDN article Windows Data Protection or this Microsoft Knowledge Base article How to troubleshoot the Data Protection API (DPAPI) on more details about DPAPI. The two higher levels of protection Windows providers use are “consent” and “password”; however, they don’t simply map to the flags we talked about earlier.
First let me describe what these two options mean and then I’ll explain how they map to the flags. A consent option simply prompts a user asking her to allow access to the private key by an application that is running on behalf of that user. This helps to prevent some rogue application quietly using somebody’s key.
The password protection actually asks a user for password that is used as additional entropy passed to the DPAPI. User selects the password when a key is created (by the way password complexity policy on the machine applies to this password) and has to provide it before a key can be used. Not only this setting provides the same protection as the consent setting, it also helps against attacks when a user logon credentials have been compromised.
Now back to the Medium and High… With medium protection a user is presented with a UI choice between consent and password when a key is created. User has to select either one of them before the key is created and will be required to either consent or provide the password, depending on user’s choice at the create step. With high protection a user is presented with UI where the only choice is to create a password for the key.
A picture worth a thousand words so let’s take a look at the UI involved. This is what you see for a CAPI key with Microsoft software providers when CRYPT_USER_PROTECTED flag is passed (this is by the way is part of the DPAPI and is also documented in the MSDN article referenced earlier):
This is the first dialog that user sees. By clicking on the “Set Security Level…” a user can select the desired level from the following dialog.
When an application tries to use the key, the following dialog is presented.
Now let’s take a look at how things change when CRYPT_FORCE_KEY_PROTECTION_HIGH is used.
First noticeable different is that the default level is set to high already. Also, the OK button is disabled because no password has been entered. When a user clicks on the “Set Security Level…” they see the following UI.
This time user gets no option between Medium and High and is taken straight to the password selection page. When an application tries to use a key protected by a password the following UI is presented:
I will not go into the “Remember password” option in this post because it is better to discuss it together with the caching that Microsoft providers support and that is enough for a post on its own.
Now let’s see what CNG UI looks like. When you create a key pair and set its UI policy with the NCRYPT_UI_PROTECT_KEY_FLAG flag, you will see this UI:
Conceptually it is very similar to UI CAPI providers show. It is still allows a user to select between consent and password. One difference I’d like to point out is that default is actually password.
When an application tries to use a key that was created to require consent, they see this dialog.
With the NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG flag the creation dialog only allows password to be used.
When a key is being used, users will see this dialog (note the text box to enter password):
Security policy for strong key protection
Now that we identified what each flag does with respect to Windows in-box crypto providers, lets break down what affects “System Cryptography: Force strong key protection for user keys stored on the computer” policy has. The policy I’m talking about can be found in Group Policy under Local Policies\Security Options node and it affects different components of windows differently. The policy has these options (I will give them short names to use later in the text):
1. NoImput – User input is not required when new keys are stored and used.
2. Prompt – User is prompted when the key is first used.
3. Password – User must enter a password each time they use a key.
Note none of these simply map to flags discussed above.
Provider Behavior
Windows in-box providers only react to the “Password” setting of this policy by behaving as if High protection was requested when application requests Medium. For example, if an application passed NCRYPT_UI_PROTECT_KEY_FLAG and the policy is configured to “Password”, Windows CNG provider will behave as if NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG was used instead (same apples to CAPI Windows providers). The “Prompt” setting has no effect.
Certificate Enrollment Behavior
When enrolling for certificates from a Windows Enterprise CA using certificate templates (https://go.microsoft.com/fwlink/?LinkID=92522), administrators can select an option “Prompt the user during enrollment and require user input when the private key is used” on the Request tab. If this option is not selected, the strong key group policy doesn’t affect how keys are created during certificate enrollment. However, if this option is selected, the certificate enrollment wizard (one that can be launched from Certificate Manager snap-in certmgr.msc) will automatically check the “Strong private key protection” option which in turn will result in CRYPT_USER_PROTECTED or NCRYPT_UI_PROTECT_KEY_FLAG flag used during key generation. So if the Group Policy was set to “Password” the user will be presented with a dialog box requiring her to enter the password (remember Provider Behavior), otherwise she will get a choice between consent and password options.
Certificate Import Wizard Behavior
When you import a certificate, the certificate template setting “Prompt the user during enrollment and require user input when the private key is used” is not considered even if that certificate is based on some template. On one of the pages of the wizard, user has an ability to check if strong key protection should be used. If Group Policy was set to “Prompt” option, the wizard will check that option by default. If the Group Policy was set to “Password” option, the wizard will check the option and disable the checkbox control preventing user from unchecking it.
Certutil.exe –importPFX Command Behavior
Until Windows 7 and Windows Server 2008 R2 there was no way to force strong key protection while importing a certificate from a PFX file using Certutil.exe -importPFX command. Now you can supply ‘-protect’ option with the command that in turn will pass CRYPT_USER_PROTECTED or NCRYPT_UI_PROTECT_KEY_FLAG flags to the provider being used to import the key. After that, the Group Policy setting will have the same effect as I described in “Provider Behavior” section above.
More About That Certificate Template Setting
I have briefly mentioned the certificate template setting “Prompt the user during enrollment and require user input when the private key is used”. I want to discuss the level of security of this setting. The fact is that there is none. The CA has no way to enforce that the client did anything in response to this setting on the certificate template. Windows tools that do certificate enrollment such as Certificate Manager snapin, certreq.exe, and our APIs will honor it, but there is no real security protection against some other tool ignoring it. This holds true with all other certificate template settings that have to do with private key properties except the key size which can be verified based on the certificate request and public key that is part of it, but this topic is good for another post. One thing you can take away from this is that if you want high level of security, use hardware key storage (smart card or HSM) and enroll on machine you control with some Enrollment Agent (EA) present during enrollment. Otherwise this setting is just to keep honest people honest.
How can you find out what protection is set on the key
So how can you find out if a key associated with some certificate has strong key protection enabled? One way would be to use certutil.exe -store command that performs a key operation on each certificate it enumerates. If the key has high protection set, the UI will be displayed.
Comments
Anonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
After looking at the MSDN, the CAPI import function CryptImportKey() doesn’t document that it supports CRYPT_FORCE_KEY_PROTECTION_HIGH, but it does. For CNG, you first need to call NCryptImportKey() function with NCRYPT_DO_NOT_FINALIZE_FLAG and then call NCryptSetProperty() function to set the NCRYPT_UI_POLICY_PROPERTY using the NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG flag before you call NCryptFinalizeKey().Anonymous
January 01, 2003
"(by the way password complexity policy on the machine applies to this password)" -> I can not verify this feature : forced to choose a strong Windows password, I can choose "a" for protecting the key.... Are You sure of this bracket ? DavidAnonymous
January 01, 2003
David, could you tell me what operating system and service packs are you using?Anonymous
January 01, 2003
You should use the following command certutil -importpfx -csp “yourCSP” {yourCertificateWithKey} The list of CSPs on a system can be found out with certutil -csplistAnonymous
January 01, 2003
to phish: I just check and support for password complexity was introduced in Windows Vista and Server 2008.Anonymous
January 01, 2003
Thanks much for this article. I still have a question though: What actually happens with the private key if you use strong key protection? Is the protection password actually used to encrypt the key (e.g. using the DPAPI?) In other words is there a guarantee that the private key cannot be recovered without the password, say by an administrator. Or can this protection be bypassed in a similar way as the key export restriction can be bypassed? regards, PhilippeAnonymous
January 01, 2003
Good to know that CryptImportKey() supports CRYPT_FORCE_KEY_PROTECTION_HIGH. Are there any specific input conditions required to use it? On a Windows 7 machine when I try to import an unencrypted PRIVATEKEYBLOB with (CRYPT_USER_PROTECTED | CRYPT_FORCE_KEY_PROTECTION_HIGH) CryptImportKey() fails with NTE_BAD_FLAGS. The import works as expected if I remove CRYPT_FORCE_KEY_PROTECTION_HIGH.Anonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
Hello, While trying to verify the presence of a root certificate on a machine using the 'certutil -store root <FINGERPRINT>' command, I ran into the issue discussed above but with a twist that I am unable to understand. I configured 2 root CAs in the exact same way(as far as I can tell), both server 2008 machines, both using the same CSP, algorithm and key lenght. While one of them brings up the pop up, the other does not. The only difference that I observed when I had a look at the details of the certificates was that the certificate bringing up the dialog is a CA type certificate template and this is not visible on the other certificate. I would appreciate any help in figuring this out.Anonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
Thanks for beautiful article! Is there a way to set or modify the "strong protection" password for private key already placed in the Windows store? Currently the only way I know is to re-export / re-import the certificate, which isn't so convenient.Anonymous
January 01, 2003
A password is used as an additional entropy to the DPAPI so if you don’t have it; you can’t decrypt the protected data, private key in this case, even if you’re an admin.Anonymous
January 01, 2003
Certificate properties have no influence on private key protection. If during a key access UI is displayed, it means that the provider has that key protected with some higher level of protection. In order to understand how that setting was enabled, you need to track back to how you got that key on the machine in the first place. Usually it is either through import wizard, certificate enrollment, or in the case of a CA during CA setup. During CA setup, there is an option on the Cryptography page that says: “Use strong private key protection…”. If you have checked that, it would explain why you’re seeing this now.Anonymous
March 28, 2011
Was there ever an answer to the question that David ("Tordji") asked? I'm seeing the same problem: even though gpedit, security analysis, and gpresult all show reasonable password requirements (e.g., >=8 characters and password complexity enabled) I can "protect" a certificate with a one-letter password. System is XP (Pro) SP3, domain joined, fully-patched, with no third-party add-ons that i would expect to have played with the way that security settings are imposed. I've verified that the length and complexity requirements are being imposed on passwords for local accounts for the login password. Windows 7 Enterprise systems, built with a roughly similar set of security specs, behave as expected.Anonymous
April 07, 2011
Until you publish the post on (undesired) private key password caching, perhaps this will help, Anyone plagued by outlook abruptly no longer requesting a password to access protected content, set the following registry entries: [HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftCryptography] "PrivKeyCacheMaxItems"=dword:00000000 "PrivKeyCachePurgeIntervalSeconds"=dword:00000000 [HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftCryptographyProtect] "AllowCachePW"=dword:00000000 This is re the following statement in this article: "I will not go into the “Remember password” option in this post because it is better to discuss it together with the caching that Microsoft providers support and that is enough for a post on its own. "Anonymous
January 23, 2013
Is it possible to set this NCRYPT_UI_PROTECT_KEY_FLAG before ADCS installation, CA private key will respect this attribute. Thanks.Anonymous
March 28, 2014
The comment has been removedAnonymous
May 28, 2014
Hi , great post,
i have doubt, i am using HSM device to store the keys.i can create the keys from the UI provided by the device vendors. Now i need to access that keys (RSA) in my c# application.How can i do that. i have installed CNG in my system. But i got the codes to create/delete/import/export rsa keys. But i don't know how to set the provider as my HSM device. please help me.Anonymous
June 01, 2015
Hi, is there any way to change the password once it has been set? The original password is known, but we'd like to change it...Anonymous
August 06, 2015
we need to run one certificate for some users in our network in order to access one website for finance dept, how can we disable the option for a specific domain computers without affecting other users. as we don't want to set the private key protection for those usersAnonymous
October 11, 2015
Alex,
(if still monitoring this post)
Will strong key protection (in Windows 7 and later), apart from honoring the configured password policy, also honor the password expiration settings (configured at domain level via a GPO) - or is there a way to configure/affect this, either by GPO or programmatically?
I have it requesting a password when configured by group policy to strongly protect, and it does require a complex password so all good there - but I haven't tested if at user password expiry this will also force key protection passwords to change (and believe it won't from previously seen behavior (in WinXP)).
It might sound like overkill, but for completeness of design/decision making process it would be better if this were available... (Or has that changed/been implemented differently in Win8 or 10?)
Thanks, best regards,
PetarAnonymous
May 21, 2017
The comment has been removed