blob: ab6c55ea93abf1de47120d01003f4ba266851ae9 [file] [log] [blame]
wbonde91513e2015-06-03 14:52:18 -04001# coding: utf-8
2from __future__ import unicode_literals
3
4import unittest
5import sys
6import os
7from collections import OrderedDict
8from datetime import datetime
9
10from asn1crypto import x509, core
11
12if sys.version_info < (3,):
13 byte_cls = str
14else:
15 byte_cls = bytes
16
17
18tests_root = os.path.dirname(__file__)
19fixtures_dir = os.path.join(tests_root, 'fixtures')
20
21
22
23class X509Tests(unittest.TestCase):
24
25 def test_parse_certificate(self):
26 with open(os.path.join(fixtures_dir, 'keys/test-der.crt'), 'rb') as f:
27 cert = x509.Certificate.load(f.read())
28
29 tbs_certificate = cert['tbs_certificate']
30 signature = tbs_certificate['signature']
31 issuer = tbs_certificate['issuer']
32 validity = tbs_certificate['validity']
33 subject = tbs_certificate['subject']
34 subject_public_key_info = tbs_certificate['subject_public_key_info']
35 subject_public_key_algorithm = subject_public_key_info['algorithm']
36 subject_public_key = subject_public_key_info['public_key'].parsed
37 extensions = tbs_certificate['extensions']
38
39 self.assertEqual(
40 'v3',
41 tbs_certificate['version'].native
42 )
43 self.assertEqual(
44 13683582341504654466,
45 tbs_certificate['serial_number'].native
46 )
47 self.assertEqual(
48 'sha256_rsa',
49 signature['algorithm'].native
50 )
51 self.assertEqual(
52 None,
53 signature['parameters'].native
54 )
55 self.assertEqual(
56 OrderedDict([
57 ('country_name', 'US'),
58 ('state_or_province_name', 'Massachusetts'),
59 ('locality_name', 'Newbury'),
60 ('organization_name', 'Codex Non Sufficit LC'),
61 ('organizational_unit_name', 'Testing'),
62 ('common_name', 'Will Bond'),
63 ('email_address', 'will@codexns.io'),
64 ]),
65 issuer.native
66 )
67 self.assertEqual(
68 datetime(2015, 5, 6, 14, 37, 16, tzinfo=core.timezone.utc),
69 validity['not_before'].native
70 )
71 self.assertEqual(
72 datetime(2025, 5, 3, 14, 37, 16, tzinfo=core.timezone.utc),
73 validity['not_after'].native
74 )
75 self.assertEqual(
76 OrderedDict([
77 ('country_name', 'US'),
78 ('state_or_province_name', 'Massachusetts'),
79 ('locality_name', 'Newbury'),
80 ('organization_name', 'Codex Non Sufficit LC'),
81 ('organizational_unit_name', 'Testing'),
82 ('common_name', 'Will Bond'),
83 ('email_address', 'will@codexns.io'),
84 ]),
85 subject.native
86 )
87 self.assertEqual(
88 'rsa',
89 subject_public_key_algorithm['algorithm'].native
90 )
91 self.assertEqual(
92 None,
93 subject_public_key_algorithm['parameters'].native
94 )
95 self.assertEqual(
96 23903990516906431865559598284199534387004799030432486061102966678620221767754702651554142956492614440585611990224871381291841413369032752409360196079700921141819811294444393525264295297988924243231844876926173670633422654261873814968313363171188082579071492839040415373948505938897419917635370450127498164824808630475648771544810334682447182123219422360569466851807131368135806769502898151721274383486320505905826683946456552230958810028663378886363555981449715929872558073101554364803925363048965464124465016494920967179276744892632783712377912841537032383450409486298694116013299423220523450956288827030007092359007,
97 subject_public_key['modulus'].native
98 )
99 self.assertEqual(
100 65537,
101 subject_public_key['public_exponent'].native
102 )
103 self.assertEqual(
104 None,
105 tbs_certificate['issuer_unique_id'].native
106 )
107 self.assertIsInstance(
108 tbs_certificate['issuer_unique_id'],
109 core.NoValue
110 )
111 self.assertEqual(
112 None,
113 tbs_certificate['subject_unique_id'].native
114 )
115 self.assertIsInstance(
116 tbs_certificate['subject_unique_id'],
117 core.NoValue
118 )
119
120 self.maxDiff = None
121 for extension in extensions:
122 self.assertIsInstance(
123 extension,
124 x509.Extension
125 )
126 self.assertEqual(
127 [
128 OrderedDict([
129 ('extn_id', 'key_identifier'),
130 ('critical', False),
131 ('extn_value', b'\xBE\x42\x85\x3D\xCC\xFF\xE3\xF9\x28\x02\x8F\x7E\x58\x56\xB4\xFD\x03\x5C\xEA\x4B'),
132 ]),
133 OrderedDict([
134 ('extn_id', 'authority_key_identifier'),
135 ('critical', False),
136 (
137 'extn_value',
138 OrderedDict([
139 ('key_identifier', b'\xBE\x42\x85\x3D\xCC\xFF\xE3\xF9\x28\x02\x8F\x7E\x58\x56\xB4\xFD\x03\x5C\xEA\x4B'),
140 (
141 'authority_cert_issuer',
142 [
143 OrderedDict([
144 ('country_name', 'US'),
145 ('state_or_province_name', 'Massachusetts'),
146 ('locality_name', 'Newbury'),
147 ('organization_name', 'Codex Non Sufficit LC'),
148 ('organizational_unit_name', 'Testing'),
149 ('common_name', 'Will Bond'),
150 ('email_address', 'will@codexns.io'),
151 ])
152 ]
153 ),
154 ('authority_cert_serial_number', 13683582341504654466),
155 ])
156 ),
157 ]),
158 OrderedDict([
159 ('extn_id', 'basic_constraints'),
160 ('critical', False),
161 (
162 'extn_value',
163 OrderedDict([
164 ('ca', True),
165 ('path_len_constraint', None)
166 ])
167 ),
168 ]),
169 ],
170 extensions.native
171 )
172
173 def test_parse_dsa_certificate(self):
174 with open(os.path.join(fixtures_dir, 'keys/test-dsa-der.crt'), 'rb') as f:
175 cert = x509.Certificate.load(f.read())
176
177 tbs_certificate = cert['tbs_certificate']
178 signature = tbs_certificate['signature']
179 issuer = tbs_certificate['issuer']
180 validity = tbs_certificate['validity']
181 subject = tbs_certificate['subject']
182 subject_public_key_info = tbs_certificate['subject_public_key_info']
183 subject_public_key_algorithm = subject_public_key_info['algorithm']
184 subject_public_key = subject_public_key_info['public_key'].parsed
185 extensions = tbs_certificate['extensions']
186
187 self.assertEqual(
188 'v3',
189 tbs_certificate['version'].native
190 )
191 self.assertEqual(
192 14308214745771946523,
193 tbs_certificate['serial_number'].native
194 )
195 self.assertEqual(
196 'sha256_dsa',
197 signature['algorithm'].native
198 )
199 self.assertEqual(
200 None,
201 signature['parameters'].native
202 )
203 self.assertEqual(
204 OrderedDict([
205 ('country_name', 'US'),
206 ('state_or_province_name', 'Massachusetts'),
207 ('locality_name', 'Newbury'),
208 ('organization_name', 'Codex Non Sufficit LC'),
209 ('organizational_unit_name', 'Testing'),
210 ('common_name', 'Will Bond'),
211 ('email_address', 'will@codexns.io'),
212 ]),
213 issuer.native
214 )
215 self.assertEqual(
216 datetime(2015, 5, 20, 13, 9, 2, tzinfo=core.timezone.utc),
217 validity['not_before'].native
218 )
219 self.assertEqual(
220 datetime(2025, 5, 17, 13, 9, 2, tzinfo=core.timezone.utc),
221 validity['not_after'].native
222 )
223 self.assertEqual(
224 OrderedDict([
225 ('country_name', 'US'),
226 ('state_or_province_name', 'Massachusetts'),
227 ('locality_name', 'Newbury'),
228 ('organization_name', 'Codex Non Sufficit LC'),
229 ('organizational_unit_name', 'Testing'),
230 ('common_name', 'Will Bond'),
231 ('email_address', 'will@codexns.io'),
232 ]),
233 subject.native
234 )
235 self.assertEqual(
236 'dsa',
237 subject_public_key_algorithm['algorithm'].native
238 )
239 self.assertEqual(
240 OrderedDict([
241 ('p', 4511743893397705393934377497936985478231822206263141826261443300639402520800626925517264115785551703273809312112372693877437137848393530691841757974971843334497076835630893064661599193178307024379015589119302113551197423138934242435710226975119594589912289060014025377813473273600967729027125618396732574594753039493158066887433778053086408525146692226448554390096911703556213619406958876388642882534250747780313634767409586007581976273681005928967585750017105562145167146445061803488570714706090280814293902464230717946651489964409785146803791743658888866280873858000476717727810363942159874283767926511678640730707887895260274767195555813448140889391762755466967436731106514029224490921857229134393798015954890071206959203407845438863870686180087606429828973298318856683615900474921310376145478859687052812749087809700610549251964102790514588562086548577933609968589710807989944739877028770343142449461177732058649962678857),
242 ('q', 71587850165936478337655415373676526523562874562337607790945426056266440596923),
243 ('g', 761437146067908309288345767887973163494473925243194806582679580640442238588269326525839153095505341738937595419375068472941615006110237832663093084973431440436421580371384720052414080562019831325744042316268714195397974084616335082272743706567701546951285088540646372701485690904535540223121118329044403681933304838754517522024738251994717369464179515923093116622352823578284891812676662979104509631349201801577889230316128523885862472086364717411346341249139971907827526291913249445756671582283459372536334490171231311487207683108274785825764378203622999309355578169139646003751751448501475767709869676880946562283552431757983801739671783678927397420797147373441051876558068212062253171347849380506793433921881336652424898488378657239798694995315456959568806256079056461448199493507273882763491729787817044805150879660784158902456811649964987582162907020243296662602990514615480712948126671999033658064244112238138589732202),
244 ]),
245 subject_public_key_algorithm['parameters'].native
246 )
247 self.assertEqual(
248 934231235067929794039535952071098031636053793876274937162425423023735221571983693370780054696865229184537343792766496068557051933738826401423094028670222490622041397241325320965905259541032379046252395145258594355589801644789631904099105867133976990593761395721476198083091062806327384261369876465927159169400428623265291958463077792777155465482611741502621885386691681062128487785344975981628995609792181581218570320181053055516069553767918513262908069925035292416868414952256645902605335068760774106734518308281769128146479819566784704033671969858507248124850451414380441279385481154336362988505436125981975735568289420374790767927084033441728922597082155884801013899630856890463962357814273014111039522903328923758417820349377075487103441305806369234738881875734407495707878637895190993370257589211331043479113328811265005530361001980539377903738453549980082795009589559114091215518866106998956304437954236070776810740036,
249 subject_public_key.native
250 )
251 self.assertEqual(
252 None,
253 tbs_certificate['issuer_unique_id'].native
254 )
255 self.assertIsInstance(
256 tbs_certificate['issuer_unique_id'],
257 core.NoValue
258 )
259 self.assertEqual(
260 None,
261 tbs_certificate['subject_unique_id'].native
262 )
263 self.assertIsInstance(
264 tbs_certificate['subject_unique_id'],
265 core.NoValue
266 )
267
268 self.maxDiff = None
269 for extension in extensions:
270 self.assertIsInstance(
271 extension,
272 x509.Extension
273 )
274 self.assertEqual(
275 [
276 OrderedDict([
277 ('extn_id', 'key_identifier'),
278 ('critical', False),
279 ('extn_value', b'\x81\xA3\x37\x86\xF9\x99\x28\xF2\x74\x70\x60\x87\xF2\xD3\x7E\x8D\x19\x61\xA8\xBE'),
280 ]),
281 OrderedDict([
282 ('extn_id', 'authority_key_identifier'),
283 ('critical', False),
284 (
285 'extn_value',
286 OrderedDict([
287 ('key_identifier', b'\x81\xA3\x37\x86\xF9\x99\x28\xF2\x74\x70\x60\x87\xF2\xD3\x7E\x8D\x19\x61\xA8\xBE'),
288 ('authority_cert_issuer', None),
289 ('authority_cert_serial_number', None),
290 ])
291 ),
292 ]),
293 OrderedDict([
294 ('extn_id', 'basic_constraints'),
295 ('critical', False),
296 (
297 'extn_value',
298 OrderedDict([
299 ('ca', True),
300 ('path_len_constraint', None)
301 ])
302 ),
303 ]),
304 ],
305 extensions.native
306 )
307
308 def test_parse_ec_certificate(self):
309 with open(os.path.join(fixtures_dir, 'keys/test-ec-der.crt'), 'rb') as f:
310 cert = x509.Certificate.load(f.read())
311
312 tbs_certificate = cert['tbs_certificate']
313 signature = tbs_certificate['signature']
314 issuer = tbs_certificate['issuer']
315 validity = tbs_certificate['validity']
316 subject = tbs_certificate['subject']
317 subject_public_key_info = tbs_certificate['subject_public_key_info']
318 subject_public_key_algorithm = subject_public_key_info['algorithm']
319 public_key_params = subject_public_key_info['algorithm']['parameters'].chosen
320 field_id = public_key_params['field_id']
321 curve = public_key_params['curve']
322 subject_public_key = subject_public_key_info['public_key'].parsed
323 extensions = tbs_certificate['extensions']
324
325 self.assertEqual(
326 'v3',
327 tbs_certificate['version'].native
328 )
329 self.assertEqual(
330 15854128451240978884,
331 tbs_certificate['serial_number'].native
332 )
333 self.assertEqual(
334 'sha256_ecdsa',
335 signature['algorithm'].native
336 )
337 self.assertEqual(
338 None,
339 signature['parameters'].native
340 )
341 self.assertEqual(
342 OrderedDict([
343 ('country_name', 'US'),
344 ('state_or_province_name', 'Massachusetts'),
345 ('locality_name', 'Newbury'),
346 ('organization_name', 'Codex Non Sufficit LC'),
347 ('organizational_unit_name', 'Testing'),
348 ('common_name', 'Will Bond'),
349 ('email_address', 'will@codexns.io'),
350 ]),
351 issuer.native
352 )
353 self.assertEqual(
354 datetime(2015, 5, 20, 12, 56, 46, tzinfo=core.timezone.utc),
355 validity['not_before'].native
356 )
357 self.assertEqual(
358 datetime(2025, 5, 17, 12, 56, 46, tzinfo=core.timezone.utc),
359 validity['not_after'].native
360 )
361 self.assertEqual(
362 OrderedDict([
363 ('country_name', 'US'),
364 ('state_or_province_name', 'Massachusetts'),
365 ('locality_name', 'Newbury'),
366 ('organization_name', 'Codex Non Sufficit LC'),
367 ('organizational_unit_name', 'Testing'),
368 ('common_name', 'Will Bond'),
369 ('email_address', 'will@codexns.io'),
370 ]),
371 subject.native
372 )
373 self.assertEqual(
wbond680cba12015-07-01 23:53:54 -0400374 'ec',
wbonde91513e2015-06-03 14:52:18 -0400375 subject_public_key_algorithm['algorithm'].native
376 )
377 self.assertEqual(
378 'ecdpVer1',
379 public_key_params['version'].native
380 )
381 self.assertEqual(
382 'prime_field',
383 field_id['field_type'].native
384 )
385 self.assertEqual(
386 115792089210356248762697446949407573530086143415290314195533631308867097853951,
387 field_id['parameters'].native
388 )
389 self.assertEqual(
390 b'\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC',
391 curve['a'].native
392 )
393 self.assertEqual(
394 b'\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B',
395 curve['b'].native
396 )
397 self.assertEqual(
398 b'\xC4\x9D\x36\x08\x86\xE7\x04\x93\x6A\x66\x78\xE1\x13\x9D\x26\xB7\x81\x9F\x7E\x90',
399 curve['seed'].native
400 )
401 self.assertEqual(
402 b'\x04\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5',
403 public_key_params['base'].native
404 )
405 self.assertEqual(
406 115792089210356248762697446949407573529996955224135760342422259061068512044369,
407 public_key_params['order'].native
408 )
409 self.assertEqual(
410 1,
411 public_key_params['cofactor'].native
412 )
413 self.assertEqual(
414 None,
415 public_key_params['hash'].native
416 )
417 self.assertEqual(
418 b'G\x9f\xcbs$\x1d\xc9\xdd\xd1-\xf1:\x9f\xb7\x04\xde \xd0X\x00\x93T\xf6\x89\xc7/\x87+\xf7\xf9=;4\xed\x9e{\x0e=WB\xdfx\x03\x0b\xcc1\xc6\x03\xd7\x9f`\x01',
419 subject_public_key.native
420 )
421 self.assertEqual(
422 None,
423 tbs_certificate['issuer_unique_id'].native
424 )
425 self.assertIsInstance(
426 tbs_certificate['issuer_unique_id'],
427 core.NoValue
428 )
429 self.assertEqual(
430 None,
431 tbs_certificate['subject_unique_id'].native
432 )
433 self.assertIsInstance(
434 tbs_certificate['subject_unique_id'],
435 core.NoValue
436 )
437
438 self.maxDiff = None
439 for extension in extensions:
440 self.assertIsInstance(
441 extension,
442 x509.Extension
443 )
444 self.assertEqual(
445 [
446 OrderedDict([
447 ('extn_id', 'key_identifier'),
448 ('critical', False),
449 ('extn_value', b'\x54\xAA\x54\x70\x6C\x34\x1A\x6D\xEB\x5D\x97\xD7\x1E\xFC\xD5\x24\x3C\x8A\x0E\xD7'),
450 ]),
451 OrderedDict([
452 ('extn_id', 'authority_key_identifier'),
453 ('critical', False),
454 (
455 'extn_value',
456 OrderedDict([
457 ('key_identifier', b'\x54\xAA\x54\x70\x6C\x34\x1A\x6D\xEB\x5D\x97\xD7\x1E\xFC\xD5\x24\x3C\x8A\x0E\xD7'),
458 ('authority_cert_issuer', None),
459 ('authority_cert_serial_number', None),
460 ])
461 ),
462 ]),
463 OrderedDict([
464 ('extn_id', 'basic_constraints'),
465 ('critical', False),
466 (
467 'extn_value',
468 OrderedDict([
469 ('ca', True),
470 ('path_len_constraint', None)
471 ])
472 ),
473 ]),
474 ],
475 extensions.native
476 )