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 | |
wbond | 8bb77d0 | 2015-07-13 17:44:29 -0400 | [diff] [blame^] | 25 | def test_extensions(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 | self.assertEqual([], cert.critical_extensions) |
| 30 | self.assertEqual(b'\xbeB\x85=\xcc\xff\xe3\xf9(\x02\x8f~XV\xb4\xfd\x03\\\xeaK', cert.key_identifier_value.native) |
| 31 | self.assertEqual(None, cert.key_usage_value) |
| 32 | self.assertEqual(None, cert.subject_alt_name_value) |
| 33 | self.assertEqual(True, cert.basic_constraints_value['ca'].native) |
| 34 | self.assertEqual(None, cert.basic_constraints_value['path_len_constraint'].native) |
| 35 | self.assertEqual(None, cert.name_constraints_value) |
| 36 | self.assertEqual(None, cert.crl_distribution_points_value) |
| 37 | self.assertEqual(None, cert.certificate_policies_value) |
| 38 | self.assertEqual(None, cert.policy_mappings_value) |
| 39 | self.assertEqual(b'\xbeB\x85=\xcc\xff\xe3\xf9(\x02\x8f~XV\xb4\xfd\x03\\\xeaK', cert.authority_key_identifier_value['key_identifier'].native) |
| 40 | self.assertEqual(None, cert.policy_constraints_value) |
| 41 | self.assertEqual(None, cert.extended_key_usage_value) |
| 42 | self.assertEqual(None, cert.ocsp_no_check_value) |
| 43 | |
| 44 | def test_extensions2(self): |
| 45 | with open(os.path.join(fixtures_dir, 'keys/test-inter-der.crt'), 'rb') as f: |
| 46 | cert = x509.Certificate.load(f.read()) |
| 47 | |
| 48 | self.assertEqual([], cert.critical_extensions) |
| 49 | self.assertEqual(b'\xd2\n\xfd.%\xd1\xb7!\xd7P~\xbb\xa4}\xbf4\xefR^\x02', cert.key_identifier_value.native) |
| 50 | self.assertEqual(None, cert.key_usage_value) |
| 51 | self.assertEqual(None, cert.subject_alt_name_value) |
| 52 | self.assertEqual(True, cert.basic_constraints_value['ca'].native) |
| 53 | self.assertEqual(None, cert.basic_constraints_value['path_len_constraint'].native) |
| 54 | self.assertEqual(None, cert.name_constraints_value) |
| 55 | self.assertEqual(None, cert.crl_distribution_points_value) |
| 56 | self.assertEqual(None, cert.certificate_policies_value) |
| 57 | self.assertEqual(None, cert.policy_mappings_value) |
| 58 | self.assertEqual(b'\xbeB\x85=\xcc\xff\xe3\xf9(\x02\x8f~XV\xb4\xfd\x03\\\xeaK', cert.authority_key_identifier_value['key_identifier'].native) |
| 59 | self.assertEqual(None, cert.policy_constraints_value) |
| 60 | self.assertEqual(None, cert.extended_key_usage_value) |
| 61 | self.assertEqual(None, cert.ocsp_no_check_value) |
| 62 | |
| 63 | def test_extensions3(self): |
| 64 | with open(os.path.join(fixtures_dir, 'keys/test-third-der.crt'), 'rb') as f: |
| 65 | cert = x509.Certificate.load(f.read()) |
| 66 | |
| 67 | self.assertEqual([], cert.critical_extensions) |
| 68 | self.assertEqual(b'D8\xe0\xe0&\x85\xbf\x98\x86\xdc\x1b\xe1\x1d\xf520\xbe\xab\xac\r', cert.key_identifier_value.native) |
| 69 | self.assertEqual(None, cert.key_usage_value) |
| 70 | self.assertEqual(None, cert.subject_alt_name_value) |
| 71 | self.assertEqual(None, cert.basic_constraints_value) |
| 72 | self.assertEqual(None, cert.name_constraints_value) |
| 73 | self.assertEqual(None, cert.crl_distribution_points_value) |
| 74 | self.assertEqual(None, cert.certificate_policies_value) |
| 75 | self.assertEqual(None, cert.policy_mappings_value) |
| 76 | self.assertEqual(b'\xd2\n\xfd.%\xd1\xb7!\xd7P~\xbb\xa4}\xbf4\xefR^\x02', cert.authority_key_identifier_value['key_identifier'].native) |
| 77 | self.assertEqual(None, cert.policy_constraints_value) |
| 78 | self.assertEqual(None, cert.extended_key_usage_value) |
| 79 | self.assertEqual(None, cert.ocsp_no_check_value) |
| 80 | |
| 81 | def test_extensions4(self): |
| 82 | with open(os.path.join(fixtures_dir, 'geotrust_certs/GeoTrust_Universal_CA.crt'), 'rb') as f: |
| 83 | cert = x509.Certificate.load(f.read()) |
| 84 | |
| 85 | self.assertEqual(['basic_constraints', 'key_usage'], cert.critical_extensions) |
| 86 | self.assertEqual(b'\xda\xbb.\xaa\xb0\x0c\xb8\x88&Qt\\m\x03\xd3\xc0\xd8\x8fz\xd6', cert.key_identifier_value.native) |
| 87 | self.assertEqual( |
| 88 | OrderedDict([ |
| 89 | ('digital_signature', True), |
| 90 | ('non_repudiation', False), |
| 91 | ('key_encipherment', False), |
| 92 | ('data_encipherment', False), |
| 93 | ('key_agreement', False), |
| 94 | ('key_cert_sign', True), |
| 95 | ('crl_sign', True), |
| 96 | ('encipher_only', False), |
| 97 | ('decipher_only', False), |
| 98 | ]), |
| 99 | cert.key_usage_value.native |
| 100 | ) |
| 101 | self.assertEqual(None, cert.subject_alt_name_value) |
| 102 | self.assertEqual( |
| 103 | OrderedDict([ |
| 104 | ('ca', True), |
| 105 | ('path_len_constraint', None), |
| 106 | ]), |
| 107 | cert.basic_constraints_value.native |
| 108 | ) |
| 109 | self.assertEqual(None, cert.name_constraints_value) |
| 110 | self.assertEqual(None, cert.crl_distribution_points_value) |
| 111 | self.assertEqual(None, cert.certificate_policies_value) |
| 112 | self.assertEqual(None, cert.policy_mappings_value) |
| 113 | self.assertEqual(b'\xda\xbb.\xaa\xb0\x0c\xb8\x88&Qt\\m\x03\xd3\xc0\xd8\x8fz\xd6', cert.authority_key_identifier_value['key_identifier'].native) |
| 114 | self.assertEqual(None, cert.policy_constraints_value) |
| 115 | self.assertEqual(None, cert.extended_key_usage_value) |
| 116 | self.assertEqual(None, cert.ocsp_no_check_value) |
| 117 | |
| 118 | def test_extensions5(self): |
| 119 | with open(os.path.join(fixtures_dir, 'geotrust_certs/GeoTrust_Primary_CA.crt'), 'rb') as f: |
| 120 | cert = x509.Certificate.load(f.read()) |
| 121 | |
| 122 | self.assertEqual(['basic_constraints', 'key_usage'], cert.critical_extensions) |
| 123 | self.assertEqual(b',\xd5PA\x97\x15\x8b\xf0\x8f6a[J\xfbk\xd9\x99\xc93\x92', cert.key_identifier_value.native) |
| 124 | self.assertEqual( |
| 125 | OrderedDict([ |
| 126 | ('digital_signature', True), |
| 127 | ('non_repudiation', True), |
| 128 | ('key_encipherment', False), |
| 129 | ('data_encipherment', False), |
| 130 | ('key_agreement', False), |
| 131 | ('key_cert_sign', False), |
| 132 | ('crl_sign', False), |
| 133 | ('encipher_only', False), |
| 134 | ('decipher_only', False), |
| 135 | ]), |
| 136 | cert.key_usage_value.native |
| 137 | ) |
| 138 | self.assertEqual(None, cert.subject_alt_name_value) |
| 139 | self.assertEqual(True, cert.basic_constraints_value['ca'].native) |
| 140 | self.assertEqual(None, cert.basic_constraints_value['path_len_constraint'].native) |
| 141 | self.assertEqual(None, cert.name_constraints_value) |
| 142 | self.assertEqual(None, cert.crl_distribution_points_value) |
| 143 | self.assertEqual(None, cert.certificate_policies_value) |
| 144 | self.assertEqual(None, cert.policy_mappings_value) |
| 145 | self.assertEqual(None, cert.authority_key_identifier_value) |
| 146 | self.assertEqual(None, cert.policy_constraints_value) |
| 147 | self.assertEqual(None, cert.extended_key_usage_value) |
| 148 | self.assertEqual(None, cert.ocsp_no_check_value) |
| 149 | |
| 150 | def test_extensions6(self): |
| 151 | with open(os.path.join(fixtures_dir, 'geotrust_certs/GeoTrust_EV_SSL_CA_-_G4.crt'), 'rb') as f: |
| 152 | cert = x509.Certificate.load(f.read()) |
| 153 | |
| 154 | self.assertEqual(['basic_constraints', 'key_usage'], cert.critical_extensions) |
| 155 | self.assertEqual(b'\xde\xcf\\P\xb7\xae\x02\x1f\x15\x17\xaa\x16\xe8\r\xb5(\x9djZ\xf3', cert.key_identifier_value.native) |
| 156 | self.assertEqual( |
| 157 | OrderedDict([ |
| 158 | ('digital_signature', True), |
| 159 | ('non_repudiation', True), |
| 160 | ('key_encipherment', False), |
| 161 | ('data_encipherment', False), |
| 162 | ('key_agreement', False), |
| 163 | ('key_cert_sign', False), |
| 164 | ('crl_sign', False), |
| 165 | ('encipher_only', False), |
| 166 | ('decipher_only', False), |
| 167 | ]), |
| 168 | cert.key_usage_value.native |
| 169 | ) |
| 170 | self.assertEqual( |
| 171 | [ |
| 172 | OrderedDict([ |
| 173 | ('common_name', 'SymantecPKI-1-538') |
| 174 | ]) |
| 175 | ], |
| 176 | cert.subject_alt_name_value.native |
| 177 | ) |
| 178 | self.assertEqual(True, cert.basic_constraints_value['ca'].native) |
| 179 | self.assertEqual(0, cert.basic_constraints_value['path_len_constraint'].native) |
| 180 | self.assertEqual(None, cert.name_constraints_value) |
| 181 | self.assertEqual( |
| 182 | [ |
| 183 | OrderedDict([ |
| 184 | ('distribution_point', ['http://g1.symcb.com/GeoTrustPCA.crl']), |
| 185 | ('reasons', None), |
| 186 | ('crl_issuer', None) |
| 187 | ]) |
| 188 | ], |
| 189 | cert.crl_distribution_points_value.native |
| 190 | ) |
| 191 | self.assertEqual( |
| 192 | [ |
| 193 | OrderedDict([ |
| 194 | ('policy_identifier', 'any_policy'), |
| 195 | ( |
| 196 | 'policy_qualifiers', |
| 197 | [ |
| 198 | OrderedDict([ |
| 199 | ('policy_qualifier_id', 'certification_practice_statement'), |
| 200 | ('qualifier', 'https://www.geotrust.com/resources/cps') |
| 201 | ]) |
| 202 | ] |
| 203 | ) |
| 204 | ]) |
| 205 | ], |
| 206 | cert.certificate_policies_value.native |
| 207 | ) |
| 208 | self.assertEqual(None, cert.policy_mappings_value) |
| 209 | self.assertEqual(b',\xd5PA\x97\x15\x8b\xf0\x8f6a[J\xfbk\xd9\x99\xc93\x92', cert.authority_key_identifier_value['key_identifier'].native) |
| 210 | self.assertEqual(None, cert.policy_constraints_value) |
| 211 | self.assertEqual(None, cert.extended_key_usage_value) |
| 212 | self.assertEqual(None, cert.ocsp_no_check_value) |
| 213 | |
wbond | e91513e | 2015-06-03 14:52:18 -0400 | [diff] [blame] | 214 | def test_parse_certificate(self): |
| 215 | with open(os.path.join(fixtures_dir, 'keys/test-der.crt'), 'rb') as f: |
| 216 | cert = x509.Certificate.load(f.read()) |
| 217 | |
| 218 | tbs_certificate = cert['tbs_certificate'] |
| 219 | signature = tbs_certificate['signature'] |
| 220 | issuer = tbs_certificate['issuer'] |
| 221 | validity = tbs_certificate['validity'] |
| 222 | subject = tbs_certificate['subject'] |
| 223 | subject_public_key_info = tbs_certificate['subject_public_key_info'] |
| 224 | subject_public_key_algorithm = subject_public_key_info['algorithm'] |
| 225 | subject_public_key = subject_public_key_info['public_key'].parsed |
| 226 | extensions = tbs_certificate['extensions'] |
| 227 | |
| 228 | self.assertEqual( |
| 229 | 'v3', |
| 230 | tbs_certificate['version'].native |
| 231 | ) |
| 232 | self.assertEqual( |
| 233 | 13683582341504654466, |
| 234 | tbs_certificate['serial_number'].native |
| 235 | ) |
| 236 | self.assertEqual( |
| 237 | 'sha256_rsa', |
| 238 | signature['algorithm'].native |
| 239 | ) |
| 240 | self.assertEqual( |
| 241 | None, |
| 242 | signature['parameters'].native |
| 243 | ) |
| 244 | self.assertEqual( |
| 245 | OrderedDict([ |
| 246 | ('country_name', 'US'), |
| 247 | ('state_or_province_name', 'Massachusetts'), |
| 248 | ('locality_name', 'Newbury'), |
| 249 | ('organization_name', 'Codex Non Sufficit LC'), |
| 250 | ('organizational_unit_name', 'Testing'), |
| 251 | ('common_name', 'Will Bond'), |
| 252 | ('email_address', 'will@codexns.io'), |
| 253 | ]), |
| 254 | issuer.native |
| 255 | ) |
| 256 | self.assertEqual( |
| 257 | datetime(2015, 5, 6, 14, 37, 16, tzinfo=core.timezone.utc), |
| 258 | validity['not_before'].native |
| 259 | ) |
| 260 | self.assertEqual( |
| 261 | datetime(2025, 5, 3, 14, 37, 16, tzinfo=core.timezone.utc), |
| 262 | validity['not_after'].native |
| 263 | ) |
| 264 | self.assertEqual( |
| 265 | OrderedDict([ |
| 266 | ('country_name', 'US'), |
| 267 | ('state_or_province_name', 'Massachusetts'), |
| 268 | ('locality_name', 'Newbury'), |
| 269 | ('organization_name', 'Codex Non Sufficit LC'), |
| 270 | ('organizational_unit_name', 'Testing'), |
| 271 | ('common_name', 'Will Bond'), |
| 272 | ('email_address', 'will@codexns.io'), |
| 273 | ]), |
| 274 | subject.native |
| 275 | ) |
| 276 | self.assertEqual( |
| 277 | 'rsa', |
| 278 | subject_public_key_algorithm['algorithm'].native |
| 279 | ) |
| 280 | self.assertEqual( |
| 281 | None, |
| 282 | subject_public_key_algorithm['parameters'].native |
| 283 | ) |
| 284 | self.assertEqual( |
| 285 | 23903990516906431865559598284199534387004799030432486061102966678620221767754702651554142956492614440585611990224871381291841413369032752409360196079700921141819811294444393525264295297988924243231844876926173670633422654261873814968313363171188082579071492839040415373948505938897419917635370450127498164824808630475648771544810334682447182123219422360569466851807131368135806769502898151721274383486320505905826683946456552230958810028663378886363555981449715929872558073101554364803925363048965464124465016494920967179276744892632783712377912841537032383450409486298694116013299423220523450956288827030007092359007, |
| 286 | subject_public_key['modulus'].native |
| 287 | ) |
| 288 | self.assertEqual( |
| 289 | 65537, |
| 290 | subject_public_key['public_exponent'].native |
| 291 | ) |
| 292 | self.assertEqual( |
| 293 | None, |
| 294 | tbs_certificate['issuer_unique_id'].native |
| 295 | ) |
| 296 | self.assertIsInstance( |
| 297 | tbs_certificate['issuer_unique_id'], |
| 298 | core.NoValue |
| 299 | ) |
| 300 | self.assertEqual( |
| 301 | None, |
| 302 | tbs_certificate['subject_unique_id'].native |
| 303 | ) |
| 304 | self.assertIsInstance( |
| 305 | tbs_certificate['subject_unique_id'], |
| 306 | core.NoValue |
| 307 | ) |
| 308 | |
| 309 | self.maxDiff = None |
| 310 | for extension in extensions: |
| 311 | self.assertIsInstance( |
| 312 | extension, |
| 313 | x509.Extension |
| 314 | ) |
| 315 | self.assertEqual( |
| 316 | [ |
| 317 | OrderedDict([ |
| 318 | ('extn_id', 'key_identifier'), |
| 319 | ('critical', False), |
| 320 | ('extn_value', b'\xBE\x42\x85\x3D\xCC\xFF\xE3\xF9\x28\x02\x8F\x7E\x58\x56\xB4\xFD\x03\x5C\xEA\x4B'), |
| 321 | ]), |
| 322 | OrderedDict([ |
| 323 | ('extn_id', 'authority_key_identifier'), |
| 324 | ('critical', False), |
| 325 | ( |
| 326 | 'extn_value', |
| 327 | OrderedDict([ |
| 328 | ('key_identifier', b'\xBE\x42\x85\x3D\xCC\xFF\xE3\xF9\x28\x02\x8F\x7E\x58\x56\xB4\xFD\x03\x5C\xEA\x4B'), |
| 329 | ( |
| 330 | 'authority_cert_issuer', |
| 331 | [ |
| 332 | OrderedDict([ |
| 333 | ('country_name', 'US'), |
| 334 | ('state_or_province_name', 'Massachusetts'), |
| 335 | ('locality_name', 'Newbury'), |
| 336 | ('organization_name', 'Codex Non Sufficit LC'), |
| 337 | ('organizational_unit_name', 'Testing'), |
| 338 | ('common_name', 'Will Bond'), |
| 339 | ('email_address', 'will@codexns.io'), |
| 340 | ]) |
| 341 | ] |
| 342 | ), |
| 343 | ('authority_cert_serial_number', 13683582341504654466), |
| 344 | ]) |
| 345 | ), |
| 346 | ]), |
| 347 | OrderedDict([ |
| 348 | ('extn_id', 'basic_constraints'), |
| 349 | ('critical', False), |
| 350 | ( |
| 351 | 'extn_value', |
| 352 | OrderedDict([ |
| 353 | ('ca', True), |
| 354 | ('path_len_constraint', None) |
| 355 | ]) |
| 356 | ), |
| 357 | ]), |
| 358 | ], |
| 359 | extensions.native |
| 360 | ) |
| 361 | |
| 362 | def test_parse_dsa_certificate(self): |
| 363 | with open(os.path.join(fixtures_dir, 'keys/test-dsa-der.crt'), 'rb') as f: |
| 364 | cert = x509.Certificate.load(f.read()) |
| 365 | |
| 366 | tbs_certificate = cert['tbs_certificate'] |
| 367 | signature = tbs_certificate['signature'] |
| 368 | issuer = tbs_certificate['issuer'] |
| 369 | validity = tbs_certificate['validity'] |
| 370 | subject = tbs_certificate['subject'] |
| 371 | subject_public_key_info = tbs_certificate['subject_public_key_info'] |
| 372 | subject_public_key_algorithm = subject_public_key_info['algorithm'] |
| 373 | subject_public_key = subject_public_key_info['public_key'].parsed |
| 374 | extensions = tbs_certificate['extensions'] |
| 375 | |
| 376 | self.assertEqual( |
| 377 | 'v3', |
| 378 | tbs_certificate['version'].native |
| 379 | ) |
| 380 | self.assertEqual( |
| 381 | 14308214745771946523, |
| 382 | tbs_certificate['serial_number'].native |
| 383 | ) |
| 384 | self.assertEqual( |
| 385 | 'sha256_dsa', |
| 386 | signature['algorithm'].native |
| 387 | ) |
| 388 | self.assertEqual( |
| 389 | None, |
| 390 | signature['parameters'].native |
| 391 | ) |
| 392 | self.assertEqual( |
| 393 | OrderedDict([ |
| 394 | ('country_name', 'US'), |
| 395 | ('state_or_province_name', 'Massachusetts'), |
| 396 | ('locality_name', 'Newbury'), |
| 397 | ('organization_name', 'Codex Non Sufficit LC'), |
| 398 | ('organizational_unit_name', 'Testing'), |
| 399 | ('common_name', 'Will Bond'), |
| 400 | ('email_address', 'will@codexns.io'), |
| 401 | ]), |
| 402 | issuer.native |
| 403 | ) |
| 404 | self.assertEqual( |
| 405 | datetime(2015, 5, 20, 13, 9, 2, tzinfo=core.timezone.utc), |
| 406 | validity['not_before'].native |
| 407 | ) |
| 408 | self.assertEqual( |
| 409 | datetime(2025, 5, 17, 13, 9, 2, tzinfo=core.timezone.utc), |
| 410 | validity['not_after'].native |
| 411 | ) |
| 412 | self.assertEqual( |
| 413 | OrderedDict([ |
| 414 | ('country_name', 'US'), |
| 415 | ('state_or_province_name', 'Massachusetts'), |
| 416 | ('locality_name', 'Newbury'), |
| 417 | ('organization_name', 'Codex Non Sufficit LC'), |
| 418 | ('organizational_unit_name', 'Testing'), |
| 419 | ('common_name', 'Will Bond'), |
| 420 | ('email_address', 'will@codexns.io'), |
| 421 | ]), |
| 422 | subject.native |
| 423 | ) |
| 424 | self.assertEqual( |
| 425 | 'dsa', |
| 426 | subject_public_key_algorithm['algorithm'].native |
| 427 | ) |
| 428 | self.assertEqual( |
| 429 | OrderedDict([ |
| 430 | ('p', 4511743893397705393934377497936985478231822206263141826261443300639402520800626925517264115785551703273809312112372693877437137848393530691841757974971843334497076835630893064661599193178307024379015589119302113551197423138934242435710226975119594589912289060014025377813473273600967729027125618396732574594753039493158066887433778053086408525146692226448554390096911703556213619406958876388642882534250747780313634767409586007581976273681005928967585750017105562145167146445061803488570714706090280814293902464230717946651489964409785146803791743658888866280873858000476717727810363942159874283767926511678640730707887895260274767195555813448140889391762755466967436731106514029224490921857229134393798015954890071206959203407845438863870686180087606429828973298318856683615900474921310376145478859687052812749087809700610549251964102790514588562086548577933609968589710807989944739877028770343142449461177732058649962678857), |
| 431 | ('q', 71587850165936478337655415373676526523562874562337607790945426056266440596923), |
| 432 | ('g', 761437146067908309288345767887973163494473925243194806582679580640442238588269326525839153095505341738937595419375068472941615006110237832663093084973431440436421580371384720052414080562019831325744042316268714195397974084616335082272743706567701546951285088540646372701485690904535540223121118329044403681933304838754517522024738251994717369464179515923093116622352823578284891812676662979104509631349201801577889230316128523885862472086364717411346341249139971907827526291913249445756671582283459372536334490171231311487207683108274785825764378203622999309355578169139646003751751448501475767709869676880946562283552431757983801739671783678927397420797147373441051876558068212062253171347849380506793433921881336652424898488378657239798694995315456959568806256079056461448199493507273882763491729787817044805150879660784158902456811649964987582162907020243296662602990514615480712948126671999033658064244112238138589732202), |
| 433 | ]), |
| 434 | subject_public_key_algorithm['parameters'].native |
| 435 | ) |
| 436 | self.assertEqual( |
| 437 | 934231235067929794039535952071098031636053793876274937162425423023735221571983693370780054696865229184537343792766496068557051933738826401423094028670222490622041397241325320965905259541032379046252395145258594355589801644789631904099105867133976990593761395721476198083091062806327384261369876465927159169400428623265291958463077792777155465482611741502621885386691681062128487785344975981628995609792181581218570320181053055516069553767918513262908069925035292416868414952256645902605335068760774106734518308281769128146479819566784704033671969858507248124850451414380441279385481154336362988505436125981975735568289420374790767927084033441728922597082155884801013899630856890463962357814273014111039522903328923758417820349377075487103441305806369234738881875734407495707878637895190993370257589211331043479113328811265005530361001980539377903738453549980082795009589559114091215518866106998956304437954236070776810740036, |
| 438 | subject_public_key.native |
| 439 | ) |
| 440 | self.assertEqual( |
| 441 | None, |
| 442 | tbs_certificate['issuer_unique_id'].native |
| 443 | ) |
| 444 | self.assertIsInstance( |
| 445 | tbs_certificate['issuer_unique_id'], |
| 446 | core.NoValue |
| 447 | ) |
| 448 | self.assertEqual( |
| 449 | None, |
| 450 | tbs_certificate['subject_unique_id'].native |
| 451 | ) |
| 452 | self.assertIsInstance( |
| 453 | tbs_certificate['subject_unique_id'], |
| 454 | core.NoValue |
| 455 | ) |
| 456 | |
| 457 | self.maxDiff = None |
| 458 | for extension in extensions: |
| 459 | self.assertIsInstance( |
| 460 | extension, |
| 461 | x509.Extension |
| 462 | ) |
| 463 | self.assertEqual( |
| 464 | [ |
| 465 | OrderedDict([ |
| 466 | ('extn_id', 'key_identifier'), |
| 467 | ('critical', False), |
| 468 | ('extn_value', b'\x81\xA3\x37\x86\xF9\x99\x28\xF2\x74\x70\x60\x87\xF2\xD3\x7E\x8D\x19\x61\xA8\xBE'), |
| 469 | ]), |
| 470 | OrderedDict([ |
| 471 | ('extn_id', 'authority_key_identifier'), |
| 472 | ('critical', False), |
| 473 | ( |
| 474 | 'extn_value', |
| 475 | OrderedDict([ |
| 476 | ('key_identifier', b'\x81\xA3\x37\x86\xF9\x99\x28\xF2\x74\x70\x60\x87\xF2\xD3\x7E\x8D\x19\x61\xA8\xBE'), |
| 477 | ('authority_cert_issuer', None), |
| 478 | ('authority_cert_serial_number', None), |
| 479 | ]) |
| 480 | ), |
| 481 | ]), |
| 482 | OrderedDict([ |
| 483 | ('extn_id', 'basic_constraints'), |
| 484 | ('critical', False), |
| 485 | ( |
| 486 | 'extn_value', |
| 487 | OrderedDict([ |
| 488 | ('ca', True), |
| 489 | ('path_len_constraint', None) |
| 490 | ]) |
| 491 | ), |
| 492 | ]), |
| 493 | ], |
| 494 | extensions.native |
| 495 | ) |
| 496 | |
| 497 | def test_parse_ec_certificate(self): |
| 498 | with open(os.path.join(fixtures_dir, 'keys/test-ec-der.crt'), 'rb') as f: |
| 499 | cert = x509.Certificate.load(f.read()) |
| 500 | |
| 501 | tbs_certificate = cert['tbs_certificate'] |
| 502 | signature = tbs_certificate['signature'] |
| 503 | issuer = tbs_certificate['issuer'] |
| 504 | validity = tbs_certificate['validity'] |
| 505 | subject = tbs_certificate['subject'] |
| 506 | subject_public_key_info = tbs_certificate['subject_public_key_info'] |
| 507 | subject_public_key_algorithm = subject_public_key_info['algorithm'] |
| 508 | public_key_params = subject_public_key_info['algorithm']['parameters'].chosen |
| 509 | field_id = public_key_params['field_id'] |
| 510 | curve = public_key_params['curve'] |
| 511 | subject_public_key = subject_public_key_info['public_key'].parsed |
| 512 | extensions = tbs_certificate['extensions'] |
| 513 | |
| 514 | self.assertEqual( |
| 515 | 'v3', |
| 516 | tbs_certificate['version'].native |
| 517 | ) |
| 518 | self.assertEqual( |
| 519 | 15854128451240978884, |
| 520 | tbs_certificate['serial_number'].native |
| 521 | ) |
| 522 | self.assertEqual( |
| 523 | 'sha256_ecdsa', |
| 524 | signature['algorithm'].native |
| 525 | ) |
| 526 | self.assertEqual( |
| 527 | None, |
| 528 | signature['parameters'].native |
| 529 | ) |
| 530 | self.assertEqual( |
| 531 | OrderedDict([ |
| 532 | ('country_name', 'US'), |
| 533 | ('state_or_province_name', 'Massachusetts'), |
| 534 | ('locality_name', 'Newbury'), |
| 535 | ('organization_name', 'Codex Non Sufficit LC'), |
| 536 | ('organizational_unit_name', 'Testing'), |
| 537 | ('common_name', 'Will Bond'), |
| 538 | ('email_address', 'will@codexns.io'), |
| 539 | ]), |
| 540 | issuer.native |
| 541 | ) |
| 542 | self.assertEqual( |
| 543 | datetime(2015, 5, 20, 12, 56, 46, tzinfo=core.timezone.utc), |
| 544 | validity['not_before'].native |
| 545 | ) |
| 546 | self.assertEqual( |
| 547 | datetime(2025, 5, 17, 12, 56, 46, tzinfo=core.timezone.utc), |
| 548 | validity['not_after'].native |
| 549 | ) |
| 550 | self.assertEqual( |
| 551 | OrderedDict([ |
| 552 | ('country_name', 'US'), |
| 553 | ('state_or_province_name', 'Massachusetts'), |
| 554 | ('locality_name', 'Newbury'), |
| 555 | ('organization_name', 'Codex Non Sufficit LC'), |
| 556 | ('organizational_unit_name', 'Testing'), |
| 557 | ('common_name', 'Will Bond'), |
| 558 | ('email_address', 'will@codexns.io'), |
| 559 | ]), |
| 560 | subject.native |
| 561 | ) |
| 562 | self.assertEqual( |
wbond | 680cba1 | 2015-07-01 23:53:54 -0400 | [diff] [blame] | 563 | 'ec', |
wbond | e91513e | 2015-06-03 14:52:18 -0400 | [diff] [blame] | 564 | subject_public_key_algorithm['algorithm'].native |
| 565 | ) |
| 566 | self.assertEqual( |
| 567 | 'ecdpVer1', |
| 568 | public_key_params['version'].native |
| 569 | ) |
| 570 | self.assertEqual( |
| 571 | 'prime_field', |
| 572 | field_id['field_type'].native |
| 573 | ) |
| 574 | self.assertEqual( |
| 575 | 115792089210356248762697446949407573530086143415290314195533631308867097853951, |
| 576 | field_id['parameters'].native |
| 577 | ) |
| 578 | self.assertEqual( |
| 579 | 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', |
| 580 | curve['a'].native |
| 581 | ) |
| 582 | self.assertEqual( |
| 583 | 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', |
| 584 | curve['b'].native |
| 585 | ) |
| 586 | self.assertEqual( |
| 587 | b'\xC4\x9D\x36\x08\x86\xE7\x04\x93\x6A\x66\x78\xE1\x13\x9D\x26\xB7\x81\x9F\x7E\x90', |
| 588 | curve['seed'].native |
| 589 | ) |
| 590 | self.assertEqual( |
| 591 | 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', |
| 592 | public_key_params['base'].native |
| 593 | ) |
| 594 | self.assertEqual( |
| 595 | 115792089210356248762697446949407573529996955224135760342422259061068512044369, |
| 596 | public_key_params['order'].native |
| 597 | ) |
| 598 | self.assertEqual( |
| 599 | 1, |
| 600 | public_key_params['cofactor'].native |
| 601 | ) |
| 602 | self.assertEqual( |
| 603 | None, |
| 604 | public_key_params['hash'].native |
| 605 | ) |
| 606 | self.assertEqual( |
| 607 | 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', |
| 608 | subject_public_key.native |
| 609 | ) |
| 610 | self.assertEqual( |
| 611 | None, |
| 612 | tbs_certificate['issuer_unique_id'].native |
| 613 | ) |
| 614 | self.assertIsInstance( |
| 615 | tbs_certificate['issuer_unique_id'], |
| 616 | core.NoValue |
| 617 | ) |
| 618 | self.assertEqual( |
| 619 | None, |
| 620 | tbs_certificate['subject_unique_id'].native |
| 621 | ) |
| 622 | self.assertIsInstance( |
| 623 | tbs_certificate['subject_unique_id'], |
| 624 | core.NoValue |
| 625 | ) |
| 626 | |
| 627 | self.maxDiff = None |
| 628 | for extension in extensions: |
| 629 | self.assertIsInstance( |
| 630 | extension, |
| 631 | x509.Extension |
| 632 | ) |
| 633 | self.assertEqual( |
| 634 | [ |
| 635 | OrderedDict([ |
| 636 | ('extn_id', 'key_identifier'), |
| 637 | ('critical', False), |
| 638 | ('extn_value', b'\x54\xAA\x54\x70\x6C\x34\x1A\x6D\xEB\x5D\x97\xD7\x1E\xFC\xD5\x24\x3C\x8A\x0E\xD7'), |
| 639 | ]), |
| 640 | OrderedDict([ |
| 641 | ('extn_id', 'authority_key_identifier'), |
| 642 | ('critical', False), |
| 643 | ( |
| 644 | 'extn_value', |
| 645 | OrderedDict([ |
| 646 | ('key_identifier', b'\x54\xAA\x54\x70\x6C\x34\x1A\x6D\xEB\x5D\x97\xD7\x1E\xFC\xD5\x24\x3C\x8A\x0E\xD7'), |
| 647 | ('authority_cert_issuer', None), |
| 648 | ('authority_cert_serial_number', None), |
| 649 | ]) |
| 650 | ), |
| 651 | ]), |
| 652 | OrderedDict([ |
| 653 | ('extn_id', 'basic_constraints'), |
| 654 | ('critical', False), |
| 655 | ( |
| 656 | 'extn_value', |
| 657 | OrderedDict([ |
| 658 | ('ca', True), |
| 659 | ('path_len_constraint', None) |
| 660 | ]) |
| 661 | ), |
| 662 | ]), |
| 663 | ], |
| 664 | extensions.native |
| 665 | ) |