wbond | e91513e | 2015-06-03 14:52:18 -0400 | [diff] [blame] | 1 | # coding: utf-8 |
| 2 | from __future__ import unicode_literals |
| 3 | |
| 4 | import unittest |
| 5 | import sys |
| 6 | import os |
| 7 | from collections import OrderedDict |
| 8 | from datetime import datetime |
| 9 | |
| 10 | from asn1crypto import x509, core |
| 11 | |
| 12 | if sys.version_info < (3,): |
| 13 | byte_cls = str |
| 14 | else: |
| 15 | byte_cls = bytes |
| 16 | |
| 17 | |
| 18 | tests_root = os.path.dirname(__file__) |
| 19 | fixtures_dir = os.path.join(tests_root, 'fixtures') |
| 20 | |
| 21 | |
| 22 | |
| 23 | class 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( |
wbond | 680cba1 | 2015-07-01 23:53:54 -0400 | [diff] [blame^] | 374 | 'ec', |
wbond | e91513e | 2015-06-03 14:52:18 -0400 | [diff] [blame] | 375 | 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 | ) |