Skip to content

Commit 5452a9a

Browse files
committed
[feat] initial commmit
1 parent cd2e504 commit 5452a9a

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

xca_template_parser.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/python3
2+
""" script to parse an xca certificate template """
3+
import sys
4+
from pprint import pprint
5+
6+
def _asn1_stream_parse(asn1_stream=None):
7+
""" parse asn_string """
8+
9+
oid_dic = {
10+
"2.5.4.3": "commonName",
11+
"2.5.4.4": "surname",
12+
"2.5.4.5": "serialNumber",
13+
"2.5.4.6": "countryName",
14+
"2.5.4.7": "localityName",
15+
"2.5.4.8": "stateOrProvinceName",
16+
"2.5.4.9": "streetAddress",
17+
"2.5.4.10": "organizationName",
18+
"2.5.4.11": "organizationalUnitName",
19+
"2.5.4.12": "title",
20+
"2.5.4.13": "description",
21+
"2.5.4.42": "givenName",
22+
}
23+
24+
# cut first 8 bytes which are bogus
25+
# asn1_stream = asn1_stream[8:]
26+
27+
# print(asn1_stream)
28+
stream_list = asn1_stream.split(b'\x06\x03\x55')
29+
30+
# we have to remove the first element from list as it contains junk
31+
stream_list.pop(0)
32+
33+
dn_dic = {}
34+
for ele in stream_list:
35+
oid = '2.5.{0}.{1}'.format(ele[0], ele[1])
36+
if oid in oid_dic:
37+
value_len = ele[3]
38+
value = ele[4:4+value_len]
39+
dn_dic[oid_dic[oid]] = value.decode('utf-8')
40+
return dn_dic
41+
42+
43+
def _utf_stream_parse(utf_stream=None):
44+
""" parse template information from utf_stream into dictitionary """
45+
46+
template_dic = {}
47+
48+
if utf_stream:
49+
stream_list = utf_stream.split(b'\x00\x00\x00')
50+
51+
# iterate list and clean up parameter
52+
parameter_list = []
53+
for idx, ele in enumerate(stream_list):
54+
ele = ele.replace(b'\x00', b'')
55+
if idx > 0:
56+
# strip the first character
57+
ele = ele[1:]
58+
parameter_list.append(ele.decode('utf-8'))
59+
60+
if parameter_list:
61+
# convert list into a directory
62+
template_dic = {item : parameter_list[index+1] for index, item in enumerate(parameter_list) if index % 2 == 0}
63+
64+
return template_dic
65+
66+
def _stream_split(byte_stream):
67+
""" split template in asn1 structure and utf_stream """
68+
asn1_stream = None
69+
utf_stream = None
70+
71+
if byte_stream:
72+
# search pattern
73+
pos = byte_stream.find(b'\x00\x00\x00\x0c') + 4
74+
75+
# read file again and seek content till position
76+
asn1_stream = byte_stream[:pos]
77+
utf_stream = byte_stream[pos:]
78+
79+
return(asn1_stream, utf_stream)
80+
81+
def template_process(byte_string=None):
82+
""" process template """
83+
(asn1_stream, utf_stream) = _stream_split(byte_string)
84+
85+
if asn1_stream:
86+
dn_dic = _asn1_stream_parse(asn1_stream)
87+
88+
template_dic = {}
89+
if utf_stream:
90+
template_dic = _utf_stream_parse(utf_stream)
91+
if template_dic:
92+
# replace '' with None
93+
template_dic = {k: None if not v else v for k, v in template_dic.items()}
94+
95+
return (dn_dic, template_dic)
96+
97+
if __name__ == '__main__':
98+
99+
if len(sys.argv) > 1:
100+
IN_FILE = sys.argv[1]
101+
with open(IN_FILE, 'rb') as in_file:
102+
BYTE_STREAM = in_file.read()
103+
(DN_DIC, TEMPLATE_DIC) = template_process(BYTE_STREAM)
104+
print('\n# DN attributes')
105+
pprint(DN_DIC)
106+
print('\n# certificate extensions and attributes')
107+
pprint(TEMPLATE_DIC)
108+
else:
109+
print('you need to specify a template file as argument...')

0 commit comments

Comments
 (0)