Hello S-1-1-0,
Today I’m continuing my certutil tips and tricks post series. In this post, I will get an introduction into cryptographic service provider architecture and how certutil can list and query them.
Windows Cryptography relies on a cryptographic service provider (CSP) architecture when performing cryptographic operations. CSP is a program module that represents an abstraction between client application and functions that utilize private keys. Applications are not required to interact with private key material directly, implement cryptographic functions. They only interact with known CSPs that implement private key storage database and cryptographic functions and operations. Here is a simple diagram that shows the relationship between client application and CSP:
When certificate is installed into Windows Certificate Store, public certificate is installed in registry and private key is registered and installed in selected CSP. When necessary, application queries the CSP and asks CSP to do the job, say generate key, hash, encrypt or sign data and get results. Application has zero knowledge of what is happening behind.
Microsoft Windows can support multiple CSPs and allows developers to write their own CSPs. One common cases of custom providers are hardware key storages like smart cards and hardware security modules (HSM). Custom CSP implements cryptographic algorithms, operations and interaction with key storage on hardware devices. If application needs to access the certificate on a smart card, application just communicates with smart card CSP via unified interface and all the rest is done by CSP.
After releasing Windows Vista and Windows Server 2008, there is a brand new CSP subsystem called Cryptography Next Generation (CNG). CNG is was written from scratch and is not compatible with legacy CSP subsystem. CNG brings a lot of improvements to CryptoAPI, but the idea is still the same. Also, CNG ships a new class of CSPs called Key Storage Provider or KSP. In general, KSP and CSP are similar in terms of their purpose. CSP refers to legacy CryptoAPI 1.0 and KSP refers to CNG or CAPI2.
Microsoft ships a number of different providers with different capabilities. Custom providers may be installed. So, let’s start with basic operations.
we can use certutil -csplist
to enumerate all registered providers (both, CSP and KSP):
PS C:\> certutil -csplist Provider Name: Athena ASECard Crypto CSP Provider Type: 1 - PROV_RSA_FULL Provider Name: Microsoft Base Cryptographic Provider v1.0 Provider Type: 1 - PROV_RSA_FULL Provider Name: Microsoft Base DSS and Diffie-Hellman Cryptographic Provider Provider Type: 13 - PROV_DSS_DH Provider Name: Microsoft Base DSS Cryptographic Provider Provider Type: 3 - PROV_DSS Provider Name: Microsoft Base Smart Card Crypto Provider Provider Type: 1 - PROV_RSA_FULL Provider Name: Microsoft DH SChannel Cryptographic Provider Provider Type: 18 - PROV_DH_SCHANNEL Provider Name: Microsoft Enhanced Cryptographic Provider v1.0 Provider Type: 1 - PROV_RSA_FULL Provider Name: Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider Provider Type: 13 - PROV_DSS_DH Provider Name: Microsoft Enhanced RSA and AES Cryptographic Provider Provider Type: 24 - PROV_RSA_AES Provider Name: Microsoft RSA SChannel Cryptographic Provider Provider Type: 12 - PROV_RSA_SCHANNEL Provider Name: Microsoft Strong Cryptographic Provider Provider Type: 1 - PROV_RSA_FULL Provider Name: Microsoft Software Key Storage Provider Provider Name: Athena Key Storage Provider Provider Name: Microsoft Passport Key Storage Provider Provider Name: Microsoft Platform Crypto Provider Microsoft Platform Crypto Provider: The device that is required by this cryptographic provider is not ready for use. Provider Name: Microsoft Smart Card Key Storage Provider CertUtil: -csplist command FAILED: 0x80090030 (-2146893776 NTE_DEVICE_NOT_READY) CertUtil: The device that is required by this cryptographic provider is not ready for use. PS C:\>
There are two ways to quickly say which provider is legacy CSP and which is CNG:
My current system has two custom providers, legacy CSP called “Athena ASECard Crypto CSP” and modern KSP called “Athena Key Storage Provider” which are used to access my Athena smart card. Providers may expose some capabilities in their names. For example, “Microsoft Enhanced RSA and AES Cryptographic Provider” name suggests, that this particular CSP implements AES algorithm operations (in fact, this CSP is the only built-in legacy CSP that implements AES). “Microsoft Platform Crypto Provider” provider suggests that it is intended to interact with Trusted Platform Module (TPM).
We can use certutil -csptest
command to dump specific provider capabilities:
C:\> certutil -csp "Athena Key Storage Provider" -csptest Provider Name: Athena Key Storage Provider Name: Athena Key Storage Provider HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Impl Type: 11 (0xb) NCRYPT_IMPL_HARDWARE_FLAG -- 1 NCRYPT_IMPL_SOFTWARE_FLAG -- 2 NCRYPT_IMPL_REMOVABLE_FLAG -- 8 Version: 65536 (0x10000) Pass Provider Aliases: Athena ASECard Crypto CSP Provider Module: UM(1): aseKSP.dll 0(1): 10001, 1 0: KEY_STORAGE Asymmetric Encryption Algorithms: RSA BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3 NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4 NCRYPT_SIGNATURE_OPERATION -- 10 (16) Secret Agreement Algorithms: ECDH_P256 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDH_P384 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDH_P521 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) Signature Algorithms: RSA BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3 NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDSA_P256 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDSA_P384 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDSA_P521 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) Asymmetric Algorithms: RSA BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3 NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, RSA) Algorithm Group: RSA Algorithm Name: RSA Length: 2048 (0x800) Lengths: dwMinLength = 1024 (0x400) dwMaxLength = 4096 (0x1000) dwIncrement = 512 (0x200) dwDefaultLength = 2048 (0x800) Block Length: 256 (0x100) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass ECDH_P256 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, ECDH_P256) Algorithm Group: ECDH Algorithm Name: ECDH_P256 Length: 256 (0x100) Lengths: dwMinLength = 256 (0x100) dwMaxLength = 256 (0x100) dwIncrement = 0 (0x0) dwDefaultLength = 256 (0x100) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass ECDH_P384 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, ECDH_P384) Algorithm Group: ECDH Algorithm Name: ECDH_P384 Length: 384 (0x180) Lengths: dwMinLength = 384 (0x180) dwMaxLength = 384 (0x180) dwIncrement = 0 (0x0) dwDefaultLength = 384 (0x180) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass ECDH_P521 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, ECDH_P521) Algorithm Group: ECDH Algorithm Name: ECDH_P521 Length: 521 (0x209) Lengths: dwMinLength = 521 (0x209) dwMaxLength = 521 (0x209) dwIncrement = 0 (0x0) dwDefaultLength = 521 (0x209) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass ECDSA_P256 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, ECDSA_P256) Algorithm Group: ECDSA Algorithm Name: ECDSA_P256 Length: 256 (0x100) Lengths: dwMinLength = 256 (0x100) dwMaxLength = 256 (0x100) dwIncrement = 0 (0x0) dwDefaultLength = 256 (0x100) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass ECDSA_P384 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, ECDSA_P384) Algorithm Group: ECDSA Algorithm Name: ECDSA_P384 Length: 384 (0x180) Lengths: dwMinLength = 384 (0x180) dwMaxLength = 384 (0x180) dwIncrement = 0 (0x0) dwDefaultLength = 384 (0x180) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass ECDSA_P521 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) NCryptCreatePersistedKey(Athena Key Storage Provider, ECDSA_P521) Algorithm Group: ECDSA Algorithm Name: ECDSA_P521 Length: 521 (0x209) Lengths: dwMinLength = 521 (0x209) dwMaxLength = 521 (0x209) dwIncrement = 0 (0x0) dwDefaultLength = 521 (0x209) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) HWND Handle:Binary: 0000 00 00 00 00 00 00 00 00 ........ Key Usage: 0 (0x0) Pass All Algorithms: RSA BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3 NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDH_P256 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDH_P384 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDH_P521 BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4 NCRYPT_SECRET_AGREEMENT_OPERATION -- 8 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDSA_P256 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDSA_P384 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) ECDSA_P521 BCRYPT_SIGNATURE_INTERFACE -- 5 NCRYPT_SIGNATURE_OPERATION -- 10 (16) BCryptEnumAlgorithms: Hash Algorithms: SHA256 SHA384 SHA512 SHA1 MD5 MD4 MD2 AES-GMAC AES-CMAC Asymmetric Encryption Algorithms: RSA Secret Agreement Algorithms: DH ECDH_P256 ECDH_P384 ECDH_P521 ECDH Signature Algorithms: RSA_SIGN ECDSA_P256 ECDSA_P384 ECDSA_P521 ECDSA DSA Cipher Algorithms: AES dwMinLength=128 dwMaxLength=256 dwIncrement=64 3DES dwMinLength=192 dwMaxLength=192 dwIncrement=0 3DES_112 dwMinLength=128 dwMaxLength=128 dwIncrement=0 XTS-AES dwMinLength=256 dwMaxLength=512 dwIncrement=128 DESX dwMinLength=192 dwMaxLength=192 dwIncrement=0 DES dwMinLength=64 dwMaxLength=64 dwIncrement=0 RC2 dwMinLength=16 dwMaxLength=128 dwIncrement=8 RC4 dwMinLength=8 dwMaxLength=512 dwIncrement=8 RNG Algorithms: RNG FIPS186DSARNG DUALECRNG Asymmetric Algorithms: RSA DH ECDH_P256 ECDH_P384 ECDH_P521 ECDH RSA_SIGN ECDSA_P256 ECDSA_P384 ECDSA_P521 ECDSA DSA All Algorithms: AES dwMinLength=128 dwMaxLength=256 dwIncrement=64 3DES dwMinLength=192 dwMaxLength=192 dwIncrement=0 3DES_112 dwMinLength=128 dwMaxLength=128 dwIncrement=0 XTS-AES dwMinLength=256 dwMaxLength=512 dwIncrement=128 DESX dwMinLength=192 dwMaxLength=192 dwIncrement=0 DES dwMinLength=64 dwMaxLength=64 dwIncrement=0 RC2 dwMinLength=16 dwMaxLength=128 dwIncrement=8 RC4 dwMinLength=8 dwMaxLength=512 dwIncrement=8 SHA256 SHA384 SHA512 SHA1 MD5 MD4 MD2 AES-GMAC AES-CMAC RSA DH ECDH_P256 ECDH_P384 ECDH_P521 ECDH RSA_SIGN ECDSA_P256 ECDSA_P384 ECDSA_P521 ECDSA DSA RNG FIPS186DSARNG DUALECRNG SP800_108_CTR_HMAC SP800_56A_CONCAT PBKDF2 CAPI_KDF TLS1_1_KDF TLS1_2_KDF HKDF CertUtil: -csptest command completed successfully. C:\>
The output is quite verbose, but it exposes all supported symmetric and asymmetric algorithms, hash algorithms, key sizes, etc.. For example, this block shows RSA asymmetric key generation options:
Algorithm Name: RSA Length: 2048 (0x800) Lengths: dwMinLength = 1024 (0x400) dwMaxLength = 4096 (0x1000) dwIncrement = 512 (0x200) dwDefaultLength = 2048 (0x800)
Athena KSP supports RSA keys starting with 1024 bits and up to 4096 bits with 512 bit step and default key size is 2048.
Certutil can query provider database to list all keys stored within particular provider by running certutil -key
command and specifying desired provider name:
C:\> certutil -csp "Microsoft Software Key Storage Provider" -key Microsoft Software Key Storage Provider: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200 3b77025f895e02021ad09cc75d8b941d_c0f790f6-ac7a-4d83-add9-d6e26941ca7e ECDH_P384 ECDH tq-f81ae2fb-b235-4a44-bc3a-8698b3103549 610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e ECDH_P384 ECDH tq-04de85ef-2f1a-4396-9d70-a03fd8a48242 ca359a08fea20a03fdfd19f37c6027bf_c0f790f6-ac7a-4d83-add9-d6e26941ca7e ECDH_P384 ECDH CertUtil: -key command completed successfully. C:\>
The output shows three key containers (or keys) with the following information:
What is the difference between first two? Key container name is the name of key container which may contain one or more keys. Unique container name is key name within provider. Unique container name is used as a private key file name when software provider is used.
we can add -v
switch in order to get more detailed output:
C:\> certutil -v -csp "Microsoft Software Key Storage Provider" -key Microsoft Software Key Storage Provider: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200 3b77025f895e02021ad09cc75d8b941d_c0f790f6-ac7a-4d83-add9-d6e26941ca7e AD(AT_NONE): b7680f1e88de194625f0d64b4b6bde9bea062a4d AD(AT_KEYEXCHANGE): 1c68213f8ab0f04cef612ef48fe260ea669154f4 AD(AT_SIGNATURE): 40ffbfed123ac8deb0d6040b2e0c38cd8bbbea74 ECDH_P384 ECDH Key Id Hash(rfc-sha1): 7092789a284e2f6490e5beab217a7c063936dcdc Key Id Hash(sha1): a0e57d359dc667c2ec5705bcc9c22696267f16ef Key Id Hash(bcrypt-sha1): ae761ac98deb8121d9d87a727b43eb3a8c42d061 Key Id Hash(bcrypt-sha256): c23b22c807e7c3629768ea017451f7fa82a0821ab29988bb192d1fff6a40e1d0 Container Public Key: 0000 04 81 48 02 a6 c4 7e 6b ae 9d 93 13 0c b1 84 bb 0010 d5 ba f4 97 37 4d 85 bb c3 ab ae 16 e7 19 58 10 0020 70 9c e1 41 71 a6 aa 83 f7 22 57 16 57 17 05 52 0030 25 93 ba be 2a 84 cc 3d a3 8e 7d 19 8f b5 2f f2 0040 70 7d 7a f9 88 77 0d 38 e2 b8 cd 72 c6 7e 98 df 0050 8d b5 eb a6 14 d6 68 52 73 29 7c 47 bf b3 3d 0b 0060 17 Cached Key Identifier: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200: Found exact match NCRYPT_ALLOW_DECRYPT_FLAG -- 1 NCRYPT_ALLOW_SIGNING_FLAG -- 2 NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4 NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8 NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215) UI Policy = 0 (NCRYPT_UI_PROTECT_KEY_FLAG -- 1) (NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG -- 2) Version: 0 Export Policy = 0 (NCRYPT_ALLOW_EXPORT_FLAG -- 1) (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2) (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4) (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8) Name: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200 Algorithm Group: ECDH Algorithm Name: ECDH_P384 Length: 384 (0x180) Lengths: dwMinLength = 384 (0x180) dwMaxLength = 384 (0x180) dwIncrement = 0 (0x0) dwDefaultLength = 384 (0x180) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) (NCRYPT_ALLOW_EXPORT_FLAG -- 1) (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2) (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4) (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8) Key Usage: 16777215 (0xffffff) NCRYPT_ALLOW_DECRYPT_FLAG -- 1 NCRYPT_ALLOW_SIGNING_FLAG -- 2 NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4 NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8 NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215) Security Descr: D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY) Modified: 01.11.2016 15:51 Virtual Iso: 0 (0x0) Per Boot Key: 0 (0x0) Private key is NOT exportable D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY) Allow Write NT AUTHORITY\NETWORK SERVICE Allow Write BUILTIN\Administrators Allow Write NT AUTHORITY\SYSTEM tq-f81ae2fb-b235-4a44-bc3a-8698b3103549 610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e AD(AT_NONE): 75a883f9ace7bd02f9271e8efe3fd6b4548fe8e9 AD(AT_KEYEXCHANGE): 54ad855bc53968041a8433031362cfc88bc8cbe7 AD(AT_SIGNATURE): 89ad1b600b527adeccd2f2a27e1b565d054fdc90 ECDH_P384 ECDH Key Id Hash(rfc-sha1): a1cf4cf92f7f38366b781074675b6cafaccf9c10 Key Id Hash(sha1): 9ceec12e97cb8e2f56cff51aba7865406c7a2f4e Key Id Hash(bcrypt-sha1): ee79615101f64059e8b98d4ff6633b18b268bd08 Key Id Hash(bcrypt-sha256): fbea73a80c6941a87cbbf12bdd756c162e02efb1bbff0d2e64c6fe11e0c91f3d Container Public Key: 0000 04 bc a9 d1 d4 07 58 50 e5 f5 0a 20 9f a7 ed d1 0010 12 cb e3 39 b0 3e 98 c9 aa c3 c6 ce 76 7f 6b 4f 0020 e1 01 aa 4b 9d c1 84 3d 8a ea 4e b6 e0 f3 c1 be 0030 bf c8 4c 90 1a 48 99 40 3b b2 0a cc a7 cf f7 a0 0040 c3 dc 90 93 74 ad a1 c5 3a 6b 8d 03 f6 69 b3 dd 0050 c5 49 de 23 b7 e8 3c 15 3d aa 8d 0a 77 0c 6f 55 0060 42 Cached Key Identifier: tq-f81ae2fb-b235-4a44-bc3a-8698b3103549: Found exact match NCRYPT_ALLOW_DECRYPT_FLAG -- 1 NCRYPT_ALLOW_SIGNING_FLAG -- 2 NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4 NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8 NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215) UI Policy = 0 (NCRYPT_UI_PROTECT_KEY_FLAG -- 1) (NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG -- 2) Version: 0 Export Policy = 0 (NCRYPT_ALLOW_EXPORT_FLAG -- 1) (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2) (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4) (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8) Name: tq-f81ae2fb-b235-4a44-bc3a-8698b3103549 Algorithm Group: ECDH Algorithm Name: ECDH_P384 Length: 384 (0x180) Lengths: dwMinLength = 384 (0x180) dwMaxLength = 384 (0x180) dwIncrement = 0 (0x0) dwDefaultLength = 384 (0x180) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) (NCRYPT_ALLOW_EXPORT_FLAG -- 1) (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2) (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4) (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8) Key Usage: 16777215 (0xffffff) NCRYPT_ALLOW_DECRYPT_FLAG -- 1 NCRYPT_ALLOW_SIGNING_FLAG -- 2 NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4 NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8 NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215) Security Descr: D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY) Modified: 11.05.2018 20:09 Virtual Iso: 0 (0x0) Per Boot Key: 0 (0x0) Private key is NOT exportable D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY) Allow Write NT AUTHORITY\NETWORK SERVICE Allow Write BUILTIN\Administrators Allow Write NT AUTHORITY\SYSTEM tq-04de85ef-2f1a-4396-9d70-a03fd8a48242 ca359a08fea20a03fdfd19f37c6027bf_c0f790f6-ac7a-4d83-add9-d6e26941ca7e AD(AT_NONE): a9c052679273c3dba5f84327479d9c4d8a3403a5 AD(AT_KEYEXCHANGE): 928750413b6faf33c149ac49724d92d8f393c048 AD(AT_SIGNATURE): c3fbab9e2d67c92ff33dfba1e1e6e7bd5d69f010 ECDH_P384 ECDH Key Id Hash(rfc-sha1): ba7e4b3a0c2d5ab2a953d4af54291e454a3313c3 Key Id Hash(sha1): 7ecec7e7a25fd55c68f6695e36f1670f76a72f61 Key Id Hash(bcrypt-sha1): cdebfc063e315a269e90fc0f5bdb9445102170ac Key Id Hash(bcrypt-sha256): 89a52fb54b114af118f5294d61c068510de83671a251057524af5341eb602a2d Container Public Key: 0000 04 70 82 b2 25 a8 3d 88 3b 28 0b ad 14 1e c4 99 0010 cb 05 92 a5 88 2f 9b 47 2b a1 82 12 b2 de 15 83 0020 f8 8d 50 b4 34 0e 4b 2d 4b 82 b8 d9 ac 9f 0e 2d 0030 3f 20 a5 e4 6e b2 90 66 b2 4b 62 ab 03 6b c0 d2 0040 5b 75 9c 3e e2 74 20 91 03 2c 39 a3 35 59 83 b2 0050 72 18 79 d0 f5 b2 0e 93 3e 14 e9 bf dd 7e 57 8a 0060 36 Cached Key Identifier: tq-04de85ef-2f1a-4396-9d70-a03fd8a48242: Found exact match NCRYPT_ALLOW_DECRYPT_FLAG -- 1 NCRYPT_ALLOW_SIGNING_FLAG -- 2 NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4 NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8 NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215) UI Policy = 0 (NCRYPT_UI_PROTECT_KEY_FLAG -- 1) (NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG -- 2) Version: 0 Export Policy = 0 (NCRYPT_ALLOW_EXPORT_FLAG -- 1) (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2) (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4) (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8) Name: tq-04de85ef-2f1a-4396-9d70-a03fd8a48242 Algorithm Group: ECDH Algorithm Name: ECDH_P384 Length: 384 (0x180) Lengths: dwMinLength = 384 (0x180) dwMaxLength = 384 (0x180) dwIncrement = 0 (0x0) dwDefaultLength = 384 (0x180) UI Policy: dwVersion = 1 (0x1) dwFlags = 0 (0x0) pszCreationTitle = (null) pszFriendlyName = (null) pszDescription = (null) Export Policy: 0 (0x0) (NCRYPT_ALLOW_EXPORT_FLAG -- 1) (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2) (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4) (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8) Key Usage: 16777215 (0xffffff) NCRYPT_ALLOW_DECRYPT_FLAG -- 1 NCRYPT_ALLOW_SIGNING_FLAG -- 2 NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4 NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8 NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215) Security Descr: D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY) Modified: 01.11.2018 18:18 Virtual Iso: 0 (0x0) Per Boot Key: 0 (0x0) Private key is NOT exportable D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY) Allow Write NT AUTHORITY\NETWORK SERVICE Allow Write BUILTIN\Administrators Allow Write NT AUTHORITY\SYSTEM CertUtil: -key command completed successfully. C:\>
Once again, with the -v
switch we get very verbose output. This dump shows more details about each key. For example, it shows public key associated with the specified private key, file system permissions on the key and intended usages.
In previous section, we enumerated private keys within KSP, but what the certificate this key belongs to? We can query local certificate store and find matching certificate:
C:\> certutil -store my
my "Personal"
<...>
================ Certificate 3 ================
Serial Number: 1800000018899823eb0d33bb5e000000000018
Issuer: CN=*******
NotBefore: 05.11.2017 13:25
NotAfter: 05.11.2018 13:25
Subject: CN=*******
Non-root Certificate
Cert Hash(sha1): 697d819ccc5f3f00c2f12b89138c2c98f94837f7
Key Container = tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
Unique container name: 610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
Provider = Microsoft Software Key Storage Provider
Private key is NOT exportable
Encryption test passed
CertUtil: -store command completed successfully.
C:\>
And indeed, we saw selected (in bold) key container and unique container name in the certutil -key
command's output:
tq-f81ae2fb-b235-4a44-bc3a-8698b3103549 610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e ECDH_P384 ECDH
this way we can bind the public certificate (which is stored in registry) to a corresponding private key.
Private key deletion may be very tricky. For example, many users and IT administrators think that by deleting the certificate from certificate store, the key is deleted as well. It is incorrect and this case was explained in one of my blog posts: The case of accidentally deleted user certificates. This means that when you need to delete the certificate and corresponding private key, you have to delete the key first. Then you can delete the certificate from certificate store.
We can use certutil to delete the private key material from device (file system or hardware device) with certutil -delkey
command:
PS C:\> certutil -csp "Microsoft Software Key Storage Provider" -delkey tq-f81ae2fb-b235-4a44-bc3a-8698b3103549 tq-f81ae2fb-b235-4a44-bc3a-8698b3103549 CertUtil: -delkey command completed successfully. PS C:\>
I deleted the key container from previous example (the certificate is already expired, so it is not harmful in this case). The command doesn’t produce any useful output. However, if we query the certificate again, we will see the difference:
PS C:\> certutil -store my 1800000018899823eb0d33bb5e000000000018
my "Personal"
================ Certificate 3 ================
Serial Number: 1800000018899823eb0d33bb5e000000000018
Issuer: CN=********
NotBefore: 05.11.2017 13:25
NotAfter: 05.11.2018 13:25
Subject: CN=*********
Non-root Certificate
Cert Hash(sha1): 697d819ccc5f3f00c2f12b89138c2c98f94837f7
Key Container = tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
Provider = Microsoft Software Key Storage Provider
Missing stored keyset
CertUtil: -store command completed successfully.
PS C:\>
Instead of “Encryption test passed” line we see another line: Missing stored keyset. We deleted the private key and certutil (and other tools as well) is unable to find the key and use it for any operation. Even though, the key icon is still present on certificate in certificate store, it is misleading, because the key is gone.
Today we explored the power of certutil in managing cryptographic providers and private keys. I’m a big fan of PowerShell, but PowerShell is nearly nowhere when the talk comes to cryptography. I’m still putting a lot of efforts to make PowerShell a little closer to certutil in these questions, but the road is very long. That’s all for today. Stay tuned for other PowerShell certutil stuff!
Thank you very much, for that material.
Thanks for the helpfull article.
Is there any possibility to import a public certificate (e.g. trusted third party, without having a private key) and store it's public key to a provider's container (e.g. based on a HSM)? So that the public key is not stored only within the certificate (at registery), but also at the provider's container (on HSM)?
You have written, that certificates are always stored at registery no matter what the provider is. And of course, public keys are stored within certificates. But public keys are also stored in CSP/KSP providers - as you shown with certutil and -key and -v flags.
So is the linkage from certificates to a public-key-only-container possible or is that something what windows doesn't support at all?
The goal would be a higher confidence when checking the PKI chain when e.g. connecting to the third party or verifying a signature (provided that windows look at the certificate's public key and checks it with the one stored on provider's container while doing PKI chain check)
Thank you
For public certificate import onto hardware devices (HSM, smart cards), you have to use software provided by HSM. I don't know ways to do this programmatically.
Thank you!
Fantastic explanation.!
User personal store. User certificate. Yet I cannot delete private key of expired certificate:
Administrator permissions are needed to use the selected options. Use an administrator command prompt to complete these tasks.
CertUtil: The requested operation requires elevation.
But ofcourse with evelvate cmd I get an error:
CertUtil: -delkey command FAILED: 0x80090016 (-2146893802 NTE_BAD_KEYSET)
CertUtil: Keyset does not exist
The key is listed correctly by
certutil -user -csp "Microsoft Software Key Storage Provider" -key
This is such a pain. It started in Windows 7 for me couple of weeks ago:
certutil Failed extract of third-party root list from auto update cab at: <http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab> with error: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. .
First I followed this tutorial, then tried to clean out the reg keys restart CryptSvc.
https://www.sysadmins.lv/blog-en/the-case-of-third-party-root-list-update-error.aspx
Still the error kept coming back. Then I downloaded that cab file extracted the STL from it and imported it following this guide:
https://knowledge.digicert.com/solution/SO13755.html
and finally worked. Keep deleting the stupid certificates will do NOTHING since it tries to redownload it and fail over and over again.
I couldn't even care less about using any certificate thingies it was just messing up my windows and needed to be fixed.
I know that Windows7 is out of date now but people will be using it for a good +20 years, I don't recall issues like this with Windows XP.
quick query how the certificate relates to the CSP function exposed? For example if my certificate has SHA256 hashing algorithm but the private key is stored in "Microsoft RSA SChannel Cryptographic Provider" which does not support SHA256 for hashing. How it will work?
FWIW, you can conveniently delete a certificate together with its private key in one go with PowerShell, using the "Cert:" drive, which exposes user and machine certificate stores as a pseudo-filesystem (stores are "directories" and certificates are "files" named after their thumbprints):
cd Cert:\CurrentUser\My
del .\<thumbprint> -DeleteKey
(Due to the way the Certificate namespace provider is implemented in PowerShell, the -DeleteKey parameter only works when the current location is inside the Cert: drive.)
@sebus The access rights (ACL) on the private key file may not grant Administrators the right to delete (happened for me today with a cert injected into an Azure virtual machine). You need to inspect and possibly change the permissions on the appropriate file.
For machine-level keys, the CNG Microsoft Software Key Storage Provider stores private keys as files in C:\ProgramData\Microsoft\Crypto\Keys. The CryptoAPI software CSPs do the same but in C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys. In both cases file names match the "Unique container name" certificate property. For user-level keys, replace C:\ProgramData with %USERPROFILE%\AppData\Roaming.
Reference: https://docs.microsoft.com/en-us/windows/win32/seccng/key-storage-and-retrieval#key-directories-and-files
What I noticed is that the powershell cert: drive has CSP details but not for KSP keys. Do you think that will improve, it somewhat feeld KSP support is still laggard in many tools.
(ls Cert:\LocalMAchine\my).PrivateKEy.CspKeyContainerInfo
> drive has CSP details but not for KSP keys
it is known issue, PrivateKey property does not support KSP and this will never be fixed. Instead, you should use extension methods for X509Certificate2 class.
Hi, could you explain the difference between the KSP and the CertStore?
There are a lot of certificates stored in KSP, that I cannot see in the CertStore. But when I import a key-pair into the CertStore it seems that I can also see it in the KSP.
Is there a GUI that I can use to browse the KSP?
KSP and CSP are different key storage models. The fact that you can see keys in KSP that aren't visible in CSP means that these keys are stored in KSP. However, KSP has a bridge API NCryptTranslateHandle which allows to convert CSP handle into KSP handle. That is, KSP can access keys in both, KSP and CSP, while CSP can access keys only in CSP.
Hi,
i cannot delete key
PS C:\Users\Administrator> certutil.exe -v -csp "Microsoft Software Key Storage Provider" -delkey PFXEncryptionKeyImported
CertUtil: -delkey command FAILED: 0x80070005 (WIN32: 5 ERROR_ACCESS_DENIED)
CertUtil: Access is denied.
> CertUtil: Access is denied.
make sure if your PS console is running in elevated mode.
Hello,
is there a way to select or specify particular CSP (e.g. Microsoft Enhanced RSA and AES Cryptographic Provider) when creating pfx file?
or is it somehow associated how CSR is generated (e.g. openssl, mmc console or browser api?
Post your comment:
Comments: