Skip to content

Instantly share code, notes, and snippets.

@iamahuman
Created March 8, 2021 15:01
Show Gist options
  • Save iamahuman/e7d3881c892c940ab52c0a5397698195 to your computer and use it in GitHub Desktop.
Save iamahuman/e7d3881c892c940ab52c0a5397698195 to your computer and use it in GitHub Desktop.
Parse Crypto API certificate blobs in Windows Registry
#!/usr/bin/env python3
import sys
import os
import struct
PROP_STRUCT = struct.Struct("<3I")
# {{{ constants
PROP_IDS = {
1: "KEY_PROV_HANDLE",
2: "KEY_PROV_INFO",
3: "SHA1_HASH",
4: "MD5_HASH",
5: "KEY_CONTEXT",
6: "KEY_SPEC",
7: "IE30_RESERVED",
8: "PUBKEY_HASH_RESERVED",
9: "ENHKEY_USAGE",
10: "NEXT_UPDATE_LOCATION",
11: "FRIENDLY_NAME",
12: "PVK_FILE",
13: "DESCRIPTION",
14: "ACCESS_STATE",
15: "SIGNATURE_HASH",
16: "SMART_CARD_DATA",
17: "EFS",
18: "FORTEZZA_DATA",
19: "ARCHIVED",
20: "KEY_IDENTIFIER",
21: "AUTO_ENROLL",
22: "PUBKEY_ALG_PARA",
23: "CROSS_CERT_DIST_POINTS",
24: "ISSUER_PUBLIC_KEY_MD5_HASH",
25: "SUBJECT_PUBLIC_KEY_MD5_HASH",
26: "ENROLLMENT",
27: "DATE_STAMP",
28: "ISSUER_SERIAL_NUMBER_MD5_HASH",
29: "SUBJECT_NAME_MD5_HASH",
30: "EXTENDED_ERROR_INFO",
64: "RENEWAL",
65: "ARCHIVED_KEY_HASH",
66: "AUTO_ENROLL_RETRY",
67: "AIA_URL_RETRIEVED",
68: "AUTHORITY_INFO_ACCESS",
69: "BACKED_UP",
70: "OCSP_RESPONSE",
71: "REQUEST_ORIGINATOR",
72: "SOURCE_LOCATION",
73: "SOURCE_URL",
74: "NEW_KEY",
75: "OCSP_CACHE_PREFIX",
76: "SMART_CARD_ROOT_INFO",
77: "NO_AUTO_EXPIRE_CHECK",
78: "NCRYPT_KEY_HANDLE",
79: "HCRYPTPROV_OR_NCRYPT_KEY_HANDLE",
80: "SUBJECT_INFO_ACCESS",
81: "CA_OCSP_AUTHORITY_INFO_ACCESS",
82: "CA_DISABLE_CRL",
83: "ROOT_PROGRAM_CERT_POLICIES",
84: "ROOT_PROGRAM_NAME_CONSTRAINTS",
85: "SUBJECT_OCSP_AUTHORITY_INFO_ACCESS",
86: "SUBJECT_DISABLE_CRL",
87: "CEP",
89: "SIGN_HASH_CNG_ALG",
90: "SCARD_PIN_ID",
91: "SCARD_PIN_INFO",
92: "SUBJECT_PUB_KEY_BIT_LENGTH",
93: "PUB_KEY_CNG_ALG_BIT_LENGTH",
94: "ISSUER_PUB_KEY_BIT_LENGTH",
95: "ISSUER_CHAIN_SIGN_HASH_CNG_ALG",
96: "ISSUER_CHAIN_PUB_KEY_CNG_ALG_BIT_LENGTH",
97: "NO_EXPIRE_NOTIFICATION",
98: "AUTH_ROOT_SHA256_HASH",
99: "NCRYPT_KEY_HANDLE_TRANSFER",
100: "HCRYPTPROV_TRANSFER",
101: "SMART_CARD_READER",
102: "SEND_AS_TRUSTED_ISSUER",
103: "KEY_REPAIR_ATTEMPTED",
104: "DISALLOWED_FILETIME",
105: "ROOT_PROGRAM_CHAIN_POLICIES",
106: "SMART_CARD_READER_NON_REMOVABLE",
107: "SHA256_HASH",
108: "SCEP_SERVER_CERTS",
109: "SCEP_RA_SIGNATURE_CERT",
110: "SCEP_RA_ENCRYPTION_CERT",
111: "SCEP_CA_CERT",
112: "SCEP_SIGNER_CERT",
113: "SCEP_NONCE",
114: "SCEP_ENCRYPT_HASH_CNG_ALG",
115: "SCEP_FLAGS",
116: "SCEP_GUID",
117: "SERIALIZABLE_KEY_CONTEXT",
118: "ISOLATED_KEY",
119: "SERIAL_CHAIN",
120: "KEY_CLASSIFICATION",
121: "OCSP_MUST_STAPLE",
122: "DISALLOWED_ENHKEY_USAGE",
123: "NONCOMPLIANT_ROOT_URL",
124: "PIN_SHA256_HASH",
125: "CLR_DELETE_KEY",
126: "NOT_BEFORE_FILETIME",
127: "NOT_BEFORE_ENHKEY_USAGE",
128: "FIRST_RESERVED",
0x00007FFF: "LAST_RESERVED",
0x00008000: "FIRST_USER",
0x0000FFFF: "LAST_USER",
0x1000: "STORE_LOCALIZED_NAME",
}
# }}}
PROP_IDS[32] = 'CERT'
def get_props(inpf):
while True:
hdr = inpf.read(12)
if not hdr:
break
try:
propid, reserved, size = PROP_STRUCT.unpack(hdr)
except struct.error:
raise IOError('short read')
if reserved != 1:
raise ValueError('reserved is not 1')
data = inpf.read(size)
if len(data) != size:
raise IOError('data short read')
yield propid, data
def main(args):
fil = sys.stdin
try:
fil = fil.buffer
except AttributeError:
pass
if args[0] == 'list':
for propid, _ in get_props(fil):
print(PROP_IDS.get(propid, propid))
elif args[0] == 'get':
prop_str = args[1]
try:
dest_propid = int(prop_str)
except ValueError:
try:
dest_propid = next(
x for x, n in PROP_IDS.items() if n == prop_str)
except StopIteration:
raise ValueError('unrecognized property ID') from None
out = sys.stdout
pretty = os.isatty(out.fileno())
if not pretty:
try:
out = out.buffer
except AttributeError:
pass
for propid, data in get_props(fil):
if propid == dest_propid:
if pretty:
print(repr(data)[1:-1])
else:
out.write(data)
if __name__ == '__main__':
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment