14
14
# you may not use this file except in compliance with the License.
15
15
# You may obtain a copy of the License at
16
16
#
17
- # http:# www.apache.org/licenses/LICENSE-2.0
17
+ # http:// www.apache.org/licenses/LICENSE-2.0
18
18
#
19
19
# Unless required by applicable law or agreed to in writing, software
20
20
# distributed under the License is distributed on an "AS IS" BASIS,
37
37
from cryptography .hazmat .backends import default_backend
38
38
from cryptography .hazmat .primitives import serialization
39
39
except ImportError :
40
- print ('The cryptography package is not installed.'
41
- 'Please refer to the Get Started section of the ESP-IDF Programming Guide for '
42
- 'setting up the required packages.' )
40
+ print (
41
+ "The cryptography package is not installed."
42
+ "Please refer to the Get Started section of the ESP-IDF Programming Guide for "
43
+ "setting up the required packages."
44
+ )
43
45
raise
44
46
45
- ca_bundle_bin_file = ' x509_crt_bundle'
47
+ ca_bundle_bin_file = " x509_crt_bundle"
46
48
47
49
quiet = False
48
50
49
51
50
52
def status (msg ):
51
- """ Print status message to stderr """
53
+ """Print status message to stderr"""
52
54
if not quiet :
53
55
critical (msg )
54
56
55
57
56
58
def critical (msg ):
57
- """ Print critical message to stderr """
58
- sys .stderr .write (' gen_crt_bundle.py: ' )
59
+ """Print critical message to stderr"""
60
+ sys .stderr .write (" gen_crt_bundle.py: " )
59
61
sys .stderr .write (msg )
60
- sys .stderr .write (' \n ' )
62
+ sys .stderr .write (" \n " )
61
63
62
64
63
65
class CertificateBundle :
@@ -75,75 +77,81 @@ def add_from_path(self, crts_path):
75
77
found |= self .add_from_file (os .path .join (crts_path , file_path ))
76
78
77
79
if found is False :
78
- raise InputError (' No valid x509 certificates found in %s' % crts_path )
80
+ raise InputError (" No valid x509 certificates found in %s" % crts_path )
79
81
80
82
def add_from_file (self , file_path ):
81
83
try :
82
- if file_path .endswith (' .pem' ):
83
- status (' Parsing certificates from %s' % file_path )
84
- with open (file_path , 'r' , encoding = ' utf-8' ) as f :
84
+ if file_path .endswith (" .pem" ):
85
+ status (" Parsing certificates from %s" % file_path )
86
+ with open (file_path , "r" , encoding = " utf-8" ) as f :
85
87
crt_str = f .read ()
86
88
self .add_from_pem (crt_str )
87
89
return True
88
90
89
- elif file_path .endswith (' .der' ):
90
- status (' Parsing certificates from %s' % file_path )
91
- with open (file_path , 'rb' ) as f :
91
+ elif file_path .endswith (" .der" ):
92
+ status (" Parsing certificates from %s" % file_path )
93
+ with open (file_path , "rb" ) as f :
92
94
crt_str = f .read ()
93
95
self .add_from_der (crt_str )
94
96
return True
95
97
96
98
except ValueError :
97
- critical (' Invalid certificate in %s' % file_path )
98
- raise InputError (' Invalid certificate' )
99
+ critical (" Invalid certificate in %s" % file_path )
100
+ raise InputError (" Invalid certificate" )
99
101
100
102
return False
101
103
102
104
def add_from_pem (self , crt_str ):
103
- """ A single PEM file may have multiple certificates """
105
+ """A single PEM file may have multiple certificates"""
104
106
105
- crt = ''
107
+ crt = ""
106
108
count = 0
107
109
start = False
108
110
109
111
for strg in crt_str .splitlines (True ):
110
- if strg == ' -----BEGIN CERTIFICATE-----\n ' and start is False :
111
- crt = ''
112
+ if strg == " -----BEGIN CERTIFICATE-----\n " and start is False :
113
+ crt = ""
112
114
start = True
113
- elif strg == ' -----END CERTIFICATE-----\n ' and start is True :
114
- crt += strg + ' \n '
115
+ elif strg == " -----END CERTIFICATE-----\n " and start is True :
116
+ crt += strg + " \n "
115
117
start = False
116
- self .certificates .append (x509 .load_pem_x509_certificate (crt .encode (), default_backend ()))
118
+ self .certificates .append (
119
+ x509 .load_pem_x509_certificate (crt .encode (), default_backend ())
120
+ )
117
121
count += 1
118
122
if start is True :
119
123
crt += strg
120
124
121
- if ( count == 0 ) :
122
- raise InputError (' No certificate found' )
125
+ if count == 0 :
126
+ raise InputError (" No certificate found" )
123
127
124
- status (' Successfully added %d certificates' % count )
128
+ status (" Successfully added %d certificates" % count )
125
129
126
130
def add_from_der (self , crt_str ):
127
131
self .certificates .append (x509 .load_der_x509_certificate (crt_str , default_backend ()))
128
- status (' Successfully added 1 certificate' )
132
+ status (" Successfully added 1 certificate" )
129
133
130
134
def create_bundle (self ):
131
135
# Sort certificates in order to do binary search when looking up certificates
132
- self .certificates = sorted (self .certificates , key = lambda cert : cert .subject .public_bytes (default_backend ()))
136
+ self .certificates = sorted (
137
+ self .certificates , key = lambda cert : cert .subject .public_bytes (default_backend ())
138
+ )
133
139
134
- bundle = struct .pack ('>H' , len (self .certificates ))
140
+ bundle = struct .pack (">H" , len (self .certificates ))
135
141
136
142
for crt in self .certificates :
137
- """ Read the public key as DER format """
143
+ """Read the public key as DER format"""
138
144
pub_key = crt .public_key ()
139
- pub_key_der = pub_key .public_bytes (serialization .Encoding .DER , serialization .PublicFormat .SubjectPublicKeyInfo )
145
+ pub_key_der = pub_key .public_bytes (
146
+ serialization .Encoding .DER , serialization .PublicFormat .SubjectPublicKeyInfo
147
+ )
140
148
141
149
""" Read the subject name as DER format """
142
150
sub_name_der = crt .subject .public_bytes (default_backend ())
143
151
144
152
name_len = len (sub_name_der )
145
153
key_len = len (pub_key_der )
146
- len_data = struct .pack (' >HH' , name_len , key_len )
154
+ len_data = struct .pack (" >HH" , name_len , key_len )
147
155
148
156
bundle += len_data
149
157
bundle += sub_name_der
@@ -154,23 +162,25 @@ def create_bundle(self):
154
162
def add_with_filter (self , crts_path , filter_path ):
155
163
156
164
filter_set = set ()
157
- with open (filter_path , 'r' , encoding = ' utf-8' ) as f :
158
- csv_reader = csv .reader (f , delimiter = ',' )
165
+ with open (filter_path , "r" , encoding = " utf-8" ) as f :
166
+ csv_reader = csv .reader (f , delimiter = "," )
159
167
160
168
# Skip header
161
169
next (csv_reader )
162
170
for row in csv_reader :
163
171
filter_set .add (row [1 ])
164
172
165
- status (' Parsing certificates from %s' % crts_path )
173
+ status (" Parsing certificates from %s" % crts_path )
166
174
crt_str = []
167
- with open (crts_path , 'r' , encoding = ' utf-8' ) as f :
175
+ with open (crts_path , "r" , encoding = " utf-8" ) as f :
168
176
crt_str = f .read ()
169
177
170
178
# Split all certs into a list of (name, certificate string) tuples
171
- pem_crts = re .findall (r'(^.+?)\n(=+\n[\s\S]+?END CERTIFICATE-----\n)' , crt_str , re .MULTILINE )
179
+ pem_crts = re .findall (
180
+ r"(^.+?)\n(=+\n[\s\S]+?END CERTIFICATE-----\n)" , crt_str , re .MULTILINE
181
+ )
172
182
173
- filtered_crts = ''
183
+ filtered_crts = ""
174
184
for name , crt in pem_crts :
175
185
if name in filter_set :
176
186
filtered_crts += crt
@@ -186,13 +196,27 @@ def __init__(self, e):
186
196
def main ():
187
197
global quiet
188
198
189
- parser = argparse .ArgumentParser (description = 'ESP-IDF x509 certificate bundle utility' )
190
-
191
- parser .add_argument ('--quiet' , '-q' , help = "Don't print non-critical status messages to stderr" , action = 'store_true' )
192
- parser .add_argument ('--input' , '-i' , nargs = '+' , required = True ,
193
- help = 'Paths to the custom certificate folders or files to parse, parses all .pem or .der files' )
194
- parser .add_argument ('--filter' , '-f' , help = 'Path to CSV-file where the second columns contains the name of the certificates \
195
- that should be included from cacrt_all.pem' )
199
+ parser = argparse .ArgumentParser (description = "ESP-IDF x509 certificate bundle utility" )
200
+
201
+ parser .add_argument (
202
+ "--quiet" ,
203
+ "-q" ,
204
+ help = "Don't print non-critical status messages to stderr" ,
205
+ action = "store_true" ,
206
+ )
207
+ parser .add_argument (
208
+ "--input" ,
209
+ "-i" ,
210
+ nargs = "+" ,
211
+ required = True ,
212
+ help = "Paths to the custom certificate folders or files to parse, parses all .pem or .der files" ,
213
+ )
214
+ parser .add_argument (
215
+ "--filter" ,
216
+ "-f" ,
217
+ help = "Path to CSV-file where the second columns contains the name of the certificates \
218
+ that should be included from cacrt_all.pem" ,
219
+ )
196
220
197
221
args = parser .parse_args ()
198
222
@@ -202,24 +226,24 @@ def main():
202
226
203
227
for path in args .input :
204
228
if os .path .isfile (path ):
205
- if os .path .basename (path ) == ' cacrt_all.pem' and args .filter :
229
+ if os .path .basename (path ) == " cacrt_all.pem" and args .filter :
206
230
bundle .add_with_filter (path , args .filter )
207
231
else :
208
232
bundle .add_from_file (path )
209
233
elif os .path .isdir (path ):
210
234
bundle .add_from_path (path )
211
235
else :
212
- raise InputError (' Invalid --input=%s, is neither file nor folder' % args .input )
236
+ raise InputError (" Invalid --input=%s, is neither file nor folder" % args .input )
213
237
214
- status (' Successfully added %d certificates in total' % len (bundle .certificates ))
238
+ status (" Successfully added %d certificates in total" % len (bundle .certificates ))
215
239
216
240
crt_bundle = bundle .create_bundle ()
217
241
218
- with open (ca_bundle_bin_file , 'wb' ) as f :
242
+ with open (ca_bundle_bin_file , "wb" ) as f :
219
243
f .write (crt_bundle )
220
244
221
245
222
- if __name__ == ' __main__' :
246
+ if __name__ == " __main__" :
223
247
try :
224
248
main ()
225
249
except InputError as e :
0 commit comments