blob: 49cc8493b917a13ec50fb15b99d713076c8f35c3 [file] [log] [blame]
Paul Kehrer016e08a2014-11-26 09:41:18 -10001# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
4
5from __future__ import absolute_import, division, print_function
6
Paul Kehrerb2de9482014-12-11 14:54:48 -06007import abc
Paul Kehrer31bdf792015-03-25 14:11:00 -05008import ipaddress
Paul Kehrer016e08a2014-11-26 09:41:18 -10009from enum import Enum
10
Paul Kehrerb2de9482014-12-11 14:54:48 -060011import six
12
Paul Kehrer912d3fb2015-01-29 11:19:22 -060013from cryptography import utils
Paul Kehrer8802a5b2015-02-13 12:06:57 -060014from cryptography.hazmat.primitives import hashes
Paul Kehrer912d3fb2015-01-29 11:19:22 -060015
Paul Kehrer016e08a2014-11-26 09:41:18 -100016
Paul Kehrer806bfb22015-02-02 17:05:24 -060017_OID_NAMES = {
18 "2.5.4.3": "commonName",
19 "2.5.4.6": "countryName",
20 "2.5.4.7": "localityName",
21 "2.5.4.8": "stateOrProvinceName",
22 "2.5.4.10": "organizationName",
23 "2.5.4.11": "organizationalUnitName",
24 "2.5.4.5": "serialNumber",
25 "2.5.4.4": "surname",
26 "2.5.4.42": "givenName",
27 "2.5.4.12": "title",
28 "2.5.4.44": "generationQualifier",
29 "2.5.4.46": "dnQualifier",
30 "2.5.4.65": "pseudonym",
31 "0.9.2342.19200300.100.1.25": "domainComponent",
32 "1.2.840.113549.1.9.1": "emailAddress",
Paul Kehrer71d40c62015-02-19 08:21:04 -060033 "1.2.840.113549.1.1.4": "md5WithRSAEncryption",
34 "1.2.840.113549.1.1.5": "sha1WithRSAEncryption",
Paul Kehrer56da2a52015-02-11 23:35:07 -060035 "1.2.840.113549.1.1.14": "sha224WithRSAEncryption",
36 "1.2.840.113549.1.1.11": "sha256WithRSAEncryption",
37 "1.2.840.113549.1.1.12": "sha384WithRSAEncryption",
38 "1.2.840.113549.1.1.13": "sha512WithRSAEncryption",
Paul Kehrer71d40c62015-02-19 08:21:04 -060039 "1.2.840.10045.4.3.1": "ecdsa-with-SHA224",
40 "1.2.840.10045.4.3.2": "ecdsa-with-SHA256",
41 "1.2.840.10045.4.3.3": "ecdsa-with-SHA384",
42 "1.2.840.10045.4.3.4": "ecdsa-with-SHA512",
43 "1.2.840.10040.4.3": "dsa-with-sha1",
44 "2.16.840.1.101.3.4.3.1": "dsa-with-sha224",
45 "2.16.840.1.101.3.4.3.2": "dsa-with-sha256",
Paul Kehrere1513fa2015-03-30 23:08:17 -050046 "1.3.6.1.5.5.7.3.1": "serverAuth",
47 "1.3.6.1.5.5.7.3.2": "clientAuth",
48 "1.3.6.1.5.5.7.3.3": "codeSigning",
49 "1.3.6.1.5.5.7.3.4": "emailProtection",
50 "1.3.6.1.5.5.7.3.8": "timeStamping",
51 "1.3.6.1.5.5.7.3.9": "OCSPSigning",
Paul Kehrerd08b5492015-04-04 15:19:16 -050052 "2.5.29.9": "subjectDirectoryAttributes",
53 "2.5.29.14": "subjectKeyIdentifier",
Paul Kehrerfbb7ac82015-03-16 19:26:29 -050054 "2.5.29.15": "keyUsage",
Paul Kehrerd08b5492015-04-04 15:19:16 -050055 "2.5.29.17": "subjectAltName",
56 "2.5.29.18": "issuerAltName",
57 "2.5.29.19": "basicConstraints",
58 "2.5.29.30": "nameConstraints",
59 "2.5.29.31": "cRLDistributionPoints",
60 "2.5.29.32": "certificatePolicies",
61 "2.5.29.33": "policyMappings",
62 "2.5.29.35": "authorityKeyIdentifier",
63 "2.5.29.36": "policyConstraints",
Paul Kehrere1513fa2015-03-30 23:08:17 -050064 "2.5.29.37": "extendedKeyUsage",
Paul Kehrerd08b5492015-04-04 15:19:16 -050065 "2.5.29.46": "freshestCRL",
66 "2.5.29.54": "inhibitAnyPolicy",
67 "1.3.6.1.5.5.7.1.1": "authorityInfoAccess",
68 "1.3.6.1.5.5.7.1.11": "subjectInfoAccess",
69 "1.3.6.1.5.5.7.48.1.5": "OCSPNoCheck",
Paul Kehrer3e6d5582015-05-02 21:57:56 -050070 "1.3.6.1.5.5.7.48.1": "OCSP",
Paul Kehrerf506bca2015-05-02 22:31:47 -050071 "1.3.6.1.5.5.7.48.2": "caIssuers",
Paul Kehrer2b622582015-04-15 11:04:29 -040072 "1.3.6.1.5.5.7.2.1": "id-qt-cps",
73 "1.3.6.1.5.5.7.2.2": "id-qt-unotice",
Paul Kehrer806bfb22015-02-02 17:05:24 -060074}
75
76
Paul Kehrer9089c912015-04-20 22:15:20 -050077_GENERAL_NAMES = {
78 0: "otherName",
79 1: "rfc822Name",
80 2: "dNSName",
81 3: "x400Address",
82 4: "directoryName",
83 5: "ediPartyName",
84 6: "uniformResourceIdentifier",
85 7: "iPAddress",
86 8: "registeredID",
87}
88
89
Paul Kehrere76cd272014-12-14 19:00:51 -060090class Version(Enum):
Paul Kehrer016e08a2014-11-26 09:41:18 -100091 v1 = 0
92 v3 = 2
93
94
Paul Kehrer016e08a2014-11-26 09:41:18 -100095def load_pem_x509_certificate(data, backend):
96 return backend.load_pem_x509_certificate(data)
97
98
Paul Kehrer016e08a2014-11-26 09:41:18 -100099def load_der_x509_certificate(data, backend):
100 return backend.load_der_x509_certificate(data)
Paul Kehrera68fd332014-11-27 07:08:40 -1000101
102
Paul Kehrer31e39882015-03-11 11:37:04 -0500103def load_pem_x509_csr(data, backend):
104 return backend.load_pem_x509_csr(data)
Paul Kehrerdc480ad2015-02-23 12:14:54 -0600105
106
Paul Kehrer1effb6e2015-03-30 15:05:59 -0500107def load_der_x509_csr(data, backend):
108 return backend.load_der_x509_csr(data)
109
110
Paul Kehrere76cd272014-12-14 19:00:51 -0600111class InvalidVersion(Exception):
Paul Kehrerd5cccf72014-12-15 17:20:33 -0600112 def __init__(self, msg, parsed_version):
113 super(InvalidVersion, self).__init__(msg)
114 self.parsed_version = parsed_version
Paul Kehrerb2de9482014-12-11 14:54:48 -0600115
116
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500117class DuplicateExtension(Exception):
118 def __init__(self, msg, oid):
119 super(DuplicateExtension, self).__init__(msg)
120 self.oid = oid
121
122
123class UnsupportedExtension(Exception):
124 def __init__(self, msg, oid):
125 super(UnsupportedExtension, self).__init__(msg)
126 self.oid = oid
127
128
Paul Kehrerfa56a232015-03-17 13:14:03 -0500129class ExtensionNotFound(Exception):
130 def __init__(self, msg, oid):
131 super(ExtensionNotFound, self).__init__(msg)
132 self.oid = oid
133
134
Paul Kehrer9089c912015-04-20 22:15:20 -0500135class UnsupportedGeneralNameType(Exception):
Paul Kehrerbed07352015-04-21 08:31:10 -0500136 def __init__(self, msg, type):
137 super(UnsupportedGeneralNameType, self).__init__(msg)
138 self.type = type
Paul Kehrer9089c912015-04-20 22:15:20 -0500139
140
Paul Kehrer806bfb22015-02-02 17:05:24 -0600141class NameAttribute(object):
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600142 def __init__(self, oid, value):
143 if not isinstance(oid, ObjectIdentifier):
Paul Kehrer858b9b72015-02-05 09:50:31 -0600144 raise TypeError(
145 "oid argument must be an ObjectIdentifier instance."
146 )
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600147
148 self._oid = oid
149 self._value = value
150
151 oid = utils.read_only_property("_oid")
152 value = utils.read_only_property("_value")
153
154 def __eq__(self, other):
Paul Kehrer806bfb22015-02-02 17:05:24 -0600155 if not isinstance(other, NameAttribute):
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600156 return NotImplemented
157
158 return (
159 self.oid == other.oid and
160 self.value == other.value
161 )
162
163 def __ne__(self, other):
164 return not self == other
165
Paul Kehrera498be82015-02-12 15:00:56 -0600166 def __repr__(self):
Alex Gaynord6b63da2015-03-23 00:25:44 -0400167 return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self)
Paul Kehrera498be82015-02-12 15:00:56 -0600168
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600169
170class ObjectIdentifier(object):
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600171 def __init__(self, dotted_string):
172 self._dotted_string = dotted_string
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600173
174 def __eq__(self, other):
175 if not isinstance(other, ObjectIdentifier):
176 return NotImplemented
177
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600178 return self._dotted_string == other._dotted_string
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600179
180 def __ne__(self, other):
181 return not self == other
182
183 def __repr__(self):
184 return "<ObjectIdentifier(oid={0}, name={1})>".format(
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600185 self._dotted_string,
186 _OID_NAMES.get(self._dotted_string, "Unknown OID")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600187 )
188
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500189 def __hash__(self):
190 return hash(self.dotted_string)
191
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600192 dotted_string = utils.read_only_property("_dotted_string")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600193
194
Paul Kehrer719d5362015-01-01 20:03:52 -0600195class Name(object):
196 def __init__(self, attributes):
197 self._attributes = attributes
198
Paul Kehrere901d642015-02-11 18:50:58 -0600199 def get_attributes_for_oid(self, oid):
Alex Gaynorf9574232015-02-19 13:56:50 -0800200 return [i for i in self if i.oid == oid]
Paul Kehrer719d5362015-01-01 20:03:52 -0600201
Paul Kehrer719d5362015-01-01 20:03:52 -0600202 def __eq__(self, other):
203 if not isinstance(other, Name):
204 return NotImplemented
205
Paul Kehrer53d8d492015-02-13 18:47:30 -0600206 return self._attributes == other._attributes
Paul Kehrer719d5362015-01-01 20:03:52 -0600207
208 def __ne__(self, other):
209 return not self == other
210
Paul Kehrer53d8d492015-02-13 18:47:30 -0600211 def __iter__(self):
Paul Kehrer8b21a4a2015-02-14 07:56:36 -0600212 return iter(self._attributes)
Paul Kehrer53d8d492015-02-13 18:47:30 -0600213
214 def __len__(self):
215 return len(self._attributes)
216
Paul Kehrer1fb35c92015-04-11 15:42:54 -0400217 def __repr__(self):
Paul Kehrerf4ed10a2015-04-11 15:53:12 -0400218 return "<Name({0!r})>".format(self._attributes)
Paul Kehrer1fb35c92015-04-11 15:42:54 -0400219
Paul Kehrer719d5362015-01-01 20:03:52 -0600220
Paul Kehrerd08b5492015-04-04 15:19:16 -0500221OID_SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9")
222OID_SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14")
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500223OID_KEY_USAGE = ObjectIdentifier("2.5.29.15")
Paul Kehrerd08b5492015-04-04 15:19:16 -0500224OID_SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17")
225OID_ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500226OID_BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19")
Paul Kehrerd08b5492015-04-04 15:19:16 -0500227OID_NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30")
228OID_CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31")
229OID_CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32")
230OID_POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33")
231OID_AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35")
232OID_POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36")
233OID_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37")
234OID_FRESHEST_CRL = ObjectIdentifier("2.5.29.46")
235OID_INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54")
236OID_AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1")
237OID_SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11")
238OID_OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500239
240
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500241class Extensions(object):
242 def __init__(self, extensions):
243 self._extensions = extensions
244
Paul Kehrerfa56a232015-03-17 13:14:03 -0500245 def get_extension_for_oid(self, oid):
246 for ext in self:
247 if ext.oid == oid:
248 return ext
249
250 raise ExtensionNotFound("No {0} extension was found".format(oid), oid)
251
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500252 def __iter__(self):
253 return iter(self._extensions)
254
255 def __len__(self):
256 return len(self._extensions)
257
258
Paul Kehrer8cf26422015-03-21 09:50:24 -0500259class Extension(object):
Paul Kehrer85894662015-03-22 13:19:31 -0500260 def __init__(self, oid, critical, value):
261 if not isinstance(oid, ObjectIdentifier):
262 raise TypeError(
263 "oid argument must be an ObjectIdentifier instance."
264 )
Paul Kehrer8cf26422015-03-21 09:50:24 -0500265
266 if not isinstance(critical, bool):
267 raise TypeError("critical must be a boolean value")
268
Paul Kehrer85894662015-03-22 13:19:31 -0500269 self._oid = oid
270 self._critical = critical
271 self._value = value
272
273 oid = utils.read_only_property("_oid")
274 critical = utils.read_only_property("_critical")
275 value = utils.read_only_property("_value")
276
277 def __repr__(self):
Paul Kehrer58b75692015-03-22 23:24:58 -0500278 return ("<Extension(oid={0.oid}, critical={0.critical}, "
279 "value={0.value})>").format(self)
Paul Kehrer85894662015-03-22 13:19:31 -0500280
Paul Kehrer58e870c2015-05-17 09:15:30 -0700281 def __eq__(self, other):
282 if not isinstance(other, Extension):
283 return NotImplemented
284
285 return (
286 self.oid == other.oid and
287 self.critical == other.critical and
288 self.value == other.value
289 )
290
291 def __ne__(self, other):
292 return not self == other
293
Paul Kehrer85894662015-03-22 13:19:31 -0500294
Paul Kehrerffa2a152015-03-31 08:18:25 -0500295class ExtendedKeyUsage(object):
296 def __init__(self, usages):
Paul Kehrerb0476172015-05-02 19:34:51 -0500297 if not all(isinstance(x, ObjectIdentifier) for x in usages):
298 raise TypeError(
299 "Every item in the usages list must be an ObjectIdentifier"
300 )
Paul Kehrerffa2a152015-03-31 08:18:25 -0500301
302 self._usages = usages
303
304 def __iter__(self):
305 return iter(self._usages)
306
307 def __len__(self):
308 return len(self._usages)
309
Paul Kehrer23d10c32015-04-02 23:12:32 -0500310 def __repr__(self):
311 return "<ExtendedKeyUsage({0})>".format(self._usages)
312
Paul Kehrerb0476172015-05-02 19:34:51 -0500313 def __eq__(self, other):
314 if not isinstance(other, ExtendedKeyUsage):
315 return NotImplemented
316
Paul Kehrerf24bad72015-05-02 19:36:20 -0500317 return self._usages == other._usages
Paul Kehrerb0476172015-05-02 19:34:51 -0500318
319 def __ne__(self, other):
320 return not self == other
321
Paul Kehrerffa2a152015-03-31 08:18:25 -0500322
Paul Kehrer85894662015-03-22 13:19:31 -0500323class BasicConstraints(object):
324 def __init__(self, ca, path_length):
325 if not isinstance(ca, bool):
326 raise TypeError("ca must be a boolean value")
327
Paul Kehrer611d3d32015-03-22 13:31:18 -0500328 if path_length is not None and not ca:
Paul Kehrer8cf26422015-03-21 09:50:24 -0500329 raise ValueError("path_length must be None when ca is False")
330
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500331 if (
Paul Kehrer5553d572015-03-23 21:08:01 -0500332 path_length is not None and
333 (not isinstance(path_length, six.integer_types) or path_length < 0)
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500334 ):
Paul Kehrer8cf26422015-03-21 09:50:24 -0500335 raise TypeError(
336 "path_length must be a non-negative integer or None"
337 )
338
339 self._ca = ca
340 self._path_length = path_length
Paul Kehrer8cf26422015-03-21 09:50:24 -0500341
342 ca = utils.read_only_property("_ca")
343 path_length = utils.read_only_property("_path_length")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500344
345 def __repr__(self):
Paul Kehrer58b75692015-03-22 23:24:58 -0500346 return ("<BasicConstraints(ca={0.ca}, "
347 "path_length={0.path_length})>").format(self)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500348
Paul Kehrer3a69b132015-05-13 10:03:46 -0500349 def __eq__(self, other):
350 if not isinstance(other, BasicConstraints):
351 return NotImplemented
352
353 return self.ca == other.ca and self.path_length == other.path_length
354
355 def __ne__(self, other):
356 return not self == other
357
Paul Kehrer8cf26422015-03-21 09:50:24 -0500358
Paul Kehrercecbbba2015-03-30 14:58:38 -0500359class KeyUsage(object):
360 def __init__(self, digital_signature, content_commitment, key_encipherment,
361 data_encipherment, key_agreement, key_cert_sign, crl_sign,
362 encipher_only, decipher_only):
363 if not key_agreement and (encipher_only or decipher_only):
364 raise ValueError(
365 "encipher_only and decipher_only can only be true when "
366 "key_agreement is true"
367 )
368
369 self._digital_signature = digital_signature
370 self._content_commitment = content_commitment
371 self._key_encipherment = key_encipherment
372 self._data_encipherment = data_encipherment
373 self._key_agreement = key_agreement
374 self._key_cert_sign = key_cert_sign
375 self._crl_sign = crl_sign
376 self._encipher_only = encipher_only
377 self._decipher_only = decipher_only
378
379 digital_signature = utils.read_only_property("_digital_signature")
380 content_commitment = utils.read_only_property("_content_commitment")
381 key_encipherment = utils.read_only_property("_key_encipherment")
382 data_encipherment = utils.read_only_property("_data_encipherment")
383 key_agreement = utils.read_only_property("_key_agreement")
384 key_cert_sign = utils.read_only_property("_key_cert_sign")
385 crl_sign = utils.read_only_property("_crl_sign")
386
387 @property
388 def encipher_only(self):
389 if not self.key_agreement:
390 raise ValueError(
391 "encipher_only is undefined unless key_agreement is true"
392 )
393 else:
394 return self._encipher_only
395
396 @property
397 def decipher_only(self):
398 if not self.key_agreement:
399 raise ValueError(
400 "decipher_only is undefined unless key_agreement is true"
401 )
402 else:
403 return self._decipher_only
404
Paul Kehrerac3e5bb2015-04-02 23:07:10 -0500405 def __repr__(self):
406 try:
407 encipher_only = self.encipher_only
408 decipher_only = self.decipher_only
409 except ValueError:
Paul Kehrerb372e672015-04-15 11:05:24 -0400410 encipher_only = None
411 decipher_only = None
Paul Kehrerac3e5bb2015-04-02 23:07:10 -0500412
413 return ("<KeyUsage(digital_signature={0.digital_signature}, "
414 "content_commitment={0.content_commitment}, "
415 "key_encipherment={0.key_encipherment}, "
416 "data_encipherment={0.data_encipherment}, "
417 "key_agreement={0.key_agreement}, "
418 "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
419 "encipher_only={1}, decipher_only={2})>").format(
420 self, encipher_only, decipher_only)
421
Paul Kehrer8565f5e2015-05-13 09:57:09 -0500422 def __eq__(self, other):
423 if not isinstance(other, KeyUsage):
424 return NotImplemented
425
426 return (
427 self.digital_signature == other.digital_signature and
428 self.content_commitment == other.content_commitment and
429 self.key_encipherment == other.key_encipherment and
430 self.data_encipherment == other.data_encipherment and
431 self.key_agreement == other.key_agreement and
432 self.key_cert_sign == other.key_cert_sign and
433 self.crl_sign == other.crl_sign and
434 self._encipher_only == other._encipher_only and
435 self._decipher_only == other._decipher_only
436 )
437
438 def __ne__(self, other):
439 return not self == other
440
Paul Kehrercecbbba2015-03-30 14:58:38 -0500441
Paul Kehrer3e6d5582015-05-02 21:57:56 -0500442class AuthorityInformationAccess(object):
443 def __init__(self, descriptions):
444 if not all(isinstance(x, AccessDescription) for x in descriptions):
445 raise TypeError(
446 "Every item in the descriptions list must be an "
447 "AccessDescription"
448 )
449
450 self._descriptions = descriptions
451
452 def __iter__(self):
453 return iter(self._descriptions)
454
455 def __len__(self):
456 return len(self._descriptions)
457
458 def __repr__(self):
459 return "<AuthorityInformationAccess({0})>".format(self._descriptions)
460
461 def __eq__(self, other):
462 if not isinstance(other, AuthorityInformationAccess):
463 return NotImplemented
464
465 return self._descriptions == other._descriptions
466
467 def __ne__(self, other):
468 return not self == other
469
470
471class AccessDescription(object):
472 def __init__(self, access_method, access_location):
473 if not (access_method == OID_OCSP or access_method == OID_CA_ISSUERS):
Paul Kehrerf506bca2015-05-02 22:31:47 -0500474 raise ValueError(
475 "access_method must be OID_OCSP or OID_CA_ISSUERS"
476 )
Paul Kehrer3e6d5582015-05-02 21:57:56 -0500477
478 if not isinstance(access_location, GeneralName):
479 raise TypeError("access_location must be a GeneralName")
480
481 self._access_method = access_method
482 self._access_location = access_location
483
484 def __repr__(self):
485 return (
486 "<AccessDescription(access_method={0.access_method}, access_locati"
487 "on={0.access_location})>".format(self)
488 )
489
490 def __eq__(self, other):
491 if not isinstance(other, AccessDescription):
492 return NotImplemented
493
494 return (
495 self.access_method == other.access_method and
496 self.access_location == other.access_location
497 )
498
499 def __ne__(self, other):
500 return not self == other
501
502 access_method = utils.read_only_property("_access_method")
503 access_location = utils.read_only_property("_access_location")
504
505
Paul Kehrer2b622582015-04-15 11:04:29 -0400506class CertificatePolicies(object):
507 def __init__(self, policies):
Paul Kehrerf61ec742015-04-18 20:42:39 -0500508 if not all(isinstance(x, PolicyInformation) for x in policies):
Paul Kehrer2b622582015-04-15 11:04:29 -0400509 raise TypeError(
510 "Every item in the policies list must be a "
511 "PolicyInformation"
512 )
513
514 self._policies = policies
515
516 def __iter__(self):
517 return iter(self._policies)
518
519 def __len__(self):
520 return len(self._policies)
521
522 def __repr__(self):
523 return "<CertificatePolicies({0})>".format(self._policies)
524
Paul Kehrerc56ab622015-05-03 09:56:31 -0500525 def __eq__(self, other):
526 if not isinstance(other, CertificatePolicies):
527 return NotImplemented
528
529 return self._policies == other._policies
530
531 def __ne__(self, other):
532 return not self == other
533
Paul Kehrer2b622582015-04-15 11:04:29 -0400534
535class PolicyInformation(object):
536 def __init__(self, policy_identifier, policy_qualifiers):
537 if not isinstance(policy_identifier, ObjectIdentifier):
538 raise TypeError("policy_identifier must be an ObjectIdentifier")
539
540 self._policy_identifier = policy_identifier
541 if policy_qualifiers and not all(
Paul Kehrerba35b3b2015-05-10 13:07:59 -0500542 isinstance(
543 x, (six.text_type, UserNotice)
544 ) for x in policy_qualifiers
Paul Kehrer2b622582015-04-15 11:04:29 -0400545 ):
546 raise TypeError(
Paul Kehrerba35b3b2015-05-10 13:07:59 -0500547 "policy_qualifiers must be a list of strings and/or UserNotice"
548 " objects or None"
Paul Kehrer2b622582015-04-15 11:04:29 -0400549 )
550
551 self._policy_qualifiers = policy_qualifiers
552
553 def __repr__(self):
554 return (
555 "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
556 "y_qualifiers={0.policy_qualifiers})>".format(self)
557 )
558
Paul Kehrerc56ab622015-05-03 09:56:31 -0500559 def __eq__(self, other):
560 if not isinstance(other, PolicyInformation):
561 return NotImplemented
562
563 return (
564 self.policy_identifier == other.policy_identifier and
565 self.policy_qualifiers == other.policy_qualifiers
566 )
567
568 def __ne__(self, other):
569 return not self == other
570
Paul Kehrer2b622582015-04-15 11:04:29 -0400571 policy_identifier = utils.read_only_property("_policy_identifier")
572 policy_qualifiers = utils.read_only_property("_policy_qualifiers")
573
574
Paul Kehrer2b622582015-04-15 11:04:29 -0400575class UserNotice(object):
576 def __init__(self, notice_reference, explicit_text):
577 if notice_reference and not isinstance(
578 notice_reference, NoticeReference
579 ):
580 raise TypeError(
581 "notice_reference must be None or a NoticeReference"
582 )
583
584 self._notice_reference = notice_reference
585 self._explicit_text = explicit_text
586
587 def __repr__(self):
588 return (
589 "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
Paul Kehrer9aaef9e2015-05-11 10:49:20 -0500590 "{0.explicit_text!r})>".format(self)
Paul Kehrer2b622582015-04-15 11:04:29 -0400591 )
592
Paul Kehrerc56ab622015-05-03 09:56:31 -0500593 def __eq__(self, other):
594 if not isinstance(other, UserNotice):
595 return NotImplemented
596
597 return (
598 self.notice_reference == other.notice_reference and
599 self.explicit_text == other.explicit_text
600 )
601
602 def __ne__(self, other):
603 return not self == other
604
Paul Kehrer2b622582015-04-15 11:04:29 -0400605 notice_reference = utils.read_only_property("_notice_reference")
606 explicit_text = utils.read_only_property("_explicit_text")
607
608
609class NoticeReference(object):
610 def __init__(self, organization, notice_numbers):
611 self._organization = organization
Paul Kehrer6e198b02015-05-12 15:53:38 -0500612 if not isinstance(notice_numbers, list) or not all(
Paul Kehrerf61ec742015-04-18 20:42:39 -0500613 isinstance(x, int) for x in notice_numbers
Paul Kehrer2b622582015-04-15 11:04:29 -0400614 ):
615 raise TypeError(
Paul Kehrer6e198b02015-05-12 15:53:38 -0500616 "notice_numbers must be a list of integers"
Paul Kehrer2b622582015-04-15 11:04:29 -0400617 )
618
619 self._notice_numbers = notice_numbers
620
621 def __repr__(self):
622 return (
Paul Kehrer73be2ca2015-05-11 21:22:38 -0500623 "<NoticeReference(organization={0.organization!r}, notice_numbers="
Paul Kehrer2b622582015-04-15 11:04:29 -0400624 "{0.notice_numbers})>".format(self)
625 )
626
Paul Kehrerc56ab622015-05-03 09:56:31 -0500627 def __eq__(self, other):
628 if not isinstance(other, NoticeReference):
629 return NotImplemented
630
631 return (
632 self.organization == other.organization and
633 self.notice_numbers == other.notice_numbers
634 )
635
636 def __ne__(self, other):
637 return not self == other
638
Paul Kehrer2b622582015-04-15 11:04:29 -0400639 organization = utils.read_only_property("_organization")
640 notice_numbers = utils.read_only_property("_notice_numbers")
641
642
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500643class SubjectKeyIdentifier(object):
644 def __init__(self, digest):
645 self._digest = digest
646
647 digest = utils.read_only_property("_digest")
648
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500649 def __repr__(self):
Paul Kehrercbfb1012015-04-10 20:57:20 -0400650 return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500651
652 def __eq__(self, other):
653 if not isinstance(other, SubjectKeyIdentifier):
654 return NotImplemented
655
656 return (
657 self.digest == other.digest
658 )
659
660 def __ne__(self, other):
661 return not self == other
662
663
Paul Kehrer5a485522015-05-06 00:29:12 -0500664class CRLDistributionPoints(object):
665 def __init__(self, distribution_points):
666 if not all(
667 isinstance(x, DistributionPoint) for x in distribution_points
668 ):
669 raise TypeError(
670 "distribution_points must be a list of DistributionPoint "
671 "objects"
672 )
673
674 self._distribution_points = distribution_points
675
676 def __iter__(self):
677 return iter(self._distribution_points)
678
679 def __len__(self):
680 return len(self._distribution_points)
681
682 def __repr__(self):
683 return "<CRLDistributionPoints({0})>".format(self._distribution_points)
684
685 def __eq__(self, other):
686 if not isinstance(other, CRLDistributionPoints):
687 return NotImplemented
688
689 return self._distribution_points == other._distribution_points
690
691 def __ne__(self, other):
692 return not self == other
693
694
695class DistributionPoint(object):
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500696 def __init__(self, full_name, relative_name, reasons, crl_issuer):
697 if full_name and relative_name:
698 raise ValueError(
699 "At least one of full_name and relative_name must be None"
700 )
701
702 if full_name and not all(
703 isinstance(x, GeneralName) for x in full_name
704 ):
705 raise TypeError(
706 "full_name must be a list of GeneralName objects"
707 )
708
709 if relative_name and not isinstance(relative_name, Name):
710 raise TypeError("relative_name must be a Name")
Paul Kehrer5a485522015-05-06 00:29:12 -0500711
712 if crl_issuer and not all(
713 isinstance(x, GeneralName) for x in crl_issuer
714 ):
715 raise TypeError(
716 "crl_issuer must be None or a list of general names"
717 )
718
Paul Kehrer3fd02602015-05-09 19:46:13 -0500719 if reasons and (not isinstance(reasons, frozenset) or not all(
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500720 isinstance(x, ReasonFlags) for x in reasons
Paul Kehrer3fd02602015-05-09 19:46:13 -0500721 )):
722 raise TypeError("reasons must be None or frozenset of ReasonFlags")
Paul Kehrer5a485522015-05-06 00:29:12 -0500723
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500724 if reasons and (
725 ReasonFlags.unspecified in reasons or
726 ReasonFlags.remove_from_crl in reasons
727 ):
Paul Kehrer5a485522015-05-06 00:29:12 -0500728 raise ValueError(
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500729 "unspecified and remove_from_crl are not valid reasons in a "
730 "DistributionPoint"
731 )
732
733 if reasons and not crl_issuer and not (full_name or relative_name):
734 raise ValueError(
735 "You must supply crl_issuer, full_name, or relative_name when "
Paul Kehrer5a485522015-05-06 00:29:12 -0500736 "reasons is not None"
737 )
738
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500739 self._full_name = full_name
740 self._relative_name = relative_name
Paul Kehrer5a485522015-05-06 00:29:12 -0500741 self._reasons = reasons
742 self._crl_issuer = crl_issuer
743
744 def __repr__(self):
745 return (
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500746 "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
747 "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_is"
748 "suer})>".format(self)
Paul Kehrer5a485522015-05-06 00:29:12 -0500749 )
750
751 def __eq__(self, other):
752 if not isinstance(other, DistributionPoint):
753 return NotImplemented
754
755 return (
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500756 self.full_name == other.full_name and
757 self.relative_name == other.relative_name and
Paul Kehrer5a485522015-05-06 00:29:12 -0500758 self.reasons == other.reasons and
759 self.crl_issuer == other.crl_issuer
760 )
761
762 def __ne__(self, other):
763 return not self == other
764
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500765 full_name = utils.read_only_property("_full_name")
766 relative_name = utils.read_only_property("_relative_name")
Paul Kehrer5a485522015-05-06 00:29:12 -0500767 reasons = utils.read_only_property("_reasons")
768 crl_issuer = utils.read_only_property("_crl_issuer")
769
770
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500771class ReasonFlags(Enum):
772 unspecified = "unspecified"
773 key_compromise = "keyCompromise"
774 ca_compromise = "cACompromise"
775 affiliation_changed = "affiliationChanged"
776 superseded = "superseded"
777 cessation_of_operation = "cessationOfOperation"
778 certificate_hold = "certificateHold"
779 privilege_withdrawn = "privilegeWithdrawn"
780 aa_compromise = "aACompromise"
781 remove_from_crl = "removeFromCRL"
Paul Kehrer5a485522015-05-06 00:29:12 -0500782
783
Paul Kehrer31bdf792015-03-25 14:11:00 -0500784@six.add_metaclass(abc.ABCMeta)
785class GeneralName(object):
786 @abc.abstractproperty
787 def value(self):
788 """
789 Return the value of the object
790 """
791
792
793@utils.register_interface(GeneralName)
794class RFC822Name(object):
795 def __init__(self, value):
796 if not isinstance(value, six.text_type):
797 raise TypeError("value must be a unicode string")
798
799 self._value = value
800
801 value = utils.read_only_property("_value")
802
803 def __repr__(self):
804 return "<RFC822Name(value={0})>".format(self.value)
805
806 def __eq__(self, other):
807 if not isinstance(other, RFC822Name):
808 return NotImplemented
809
810 return self.value == other.value
811
812 def __ne__(self, other):
813 return not self == other
814
815
816@utils.register_interface(GeneralName)
817class DNSName(object):
818 def __init__(self, value):
819 if not isinstance(value, six.text_type):
820 raise TypeError("value must be a unicode string")
821
822 self._value = value
823
824 value = utils.read_only_property("_value")
825
826 def __repr__(self):
827 return "<DNSName(value={0})>".format(self.value)
828
829 def __eq__(self, other):
830 if not isinstance(other, DNSName):
831 return NotImplemented
832
833 return self.value == other.value
834
835 def __ne__(self, other):
836 return not self == other
837
838
839@utils.register_interface(GeneralName)
840class UniformResourceIdentifier(object):
841 def __init__(self, value):
842 if not isinstance(value, six.text_type):
843 raise TypeError("value must be a unicode string")
844
845 self._value = value
846
847 value = utils.read_only_property("_value")
848
849 def __repr__(self):
850 return "<UniformResourceIdentifier(value={0})>".format(self.value)
851
852 def __eq__(self, other):
853 if not isinstance(other, UniformResourceIdentifier):
854 return NotImplemented
855
856 return self.value == other.value
857
858 def __ne__(self, other):
859 return not self == other
860
861
862@utils.register_interface(GeneralName)
863class DirectoryName(object):
864 def __init__(self, value):
865 if not isinstance(value, Name):
866 raise TypeError("value must be a Name")
867
868 self._value = value
869
870 value = utils.read_only_property("_value")
871
872 def __repr__(self):
873 return "<DirectoryName(value={0})>".format(self.value)
874
875 def __eq__(self, other):
876 if not isinstance(other, DirectoryName):
877 return NotImplemented
878
879 return self.value == other.value
880
881 def __ne__(self, other):
882 return not self == other
883
884
885@utils.register_interface(GeneralName)
886class RegisteredID(object):
887 def __init__(self, value):
888 if not isinstance(value, ObjectIdentifier):
889 raise TypeError("value must be an ObjectIdentifier")
890
891 self._value = value
892
893 value = utils.read_only_property("_value")
894
895 def __repr__(self):
896 return "<RegisteredID(value={0})>".format(self.value)
897
898 def __eq__(self, other):
899 if not isinstance(other, RegisteredID):
900 return NotImplemented
901
902 return self.value == other.value
903
904 def __ne__(self, other):
905 return not self == other
906
907
908@utils.register_interface(GeneralName)
909class IPAddress(object):
910 def __init__(self, value):
911 if not isinstance(
912 value, (ipaddress.IPv4Address, ipaddress.IPv6Address)
913 ):
914 raise TypeError(
915 "value must be an instance of ipaddress.IPv4Address or "
916 "ipaddress.IPv6Address"
917 )
918
919 self._value = value
920
921 value = utils.read_only_property("_value")
922
923 def __repr__(self):
924 return "<IPAddress(value={0})>".format(self.value)
925
926 def __eq__(self, other):
927 if not isinstance(other, IPAddress):
928 return NotImplemented
929
930 return self.value == other.value
931
932 def __ne__(self, other):
933 return not self == other
934
935
936class SubjectAlternativeName(object):
937 def __init__(self, general_names):
Paul Kehrerd04b39b2015-04-21 08:44:17 -0500938 if not all(isinstance(x, GeneralName) for x in general_names):
939 raise TypeError(
940 "Every item in the general_names list must be an "
941 "object conforming to the GeneralName interface"
942 )
943
Paul Kehrer31bdf792015-03-25 14:11:00 -0500944 self._general_names = general_names
945
946 def __iter__(self):
947 return iter(self._general_names)
948
949 def __len__(self):
950 return len(self._general_names)
951
952 def get_values_for_type(self, type):
953 return [i.value for i in self if isinstance(i, type)]
954
955 def __repr__(self):
956 return "<SubjectAlternativeName({0})>".format(self._general_names)
957
Paul Kehrer58cc3972015-05-13 10:00:41 -0500958 def __eq__(self, other):
959 if not isinstance(other, SubjectAlternativeName):
960 return NotImplemented
961
962 return self._general_names == other._general_names
963
964 def __ne__(self, other):
965 return not self == other
966
Paul Kehrer31bdf792015-03-25 14:11:00 -0500967
Paul Kehrer2eb4ed92015-04-11 15:33:45 -0400968class AuthorityKeyIdentifier(object):
969 def __init__(self, key_identifier, authority_cert_issuer,
970 authority_cert_serial_number):
971 if authority_cert_issuer or authority_cert_serial_number:
972 if not authority_cert_issuer or not authority_cert_serial_number:
973 raise ValueError(
974 "authority_cert_issuer and authority_cert_serial_number "
975 "must both be present or both None"
976 )
977
Paul Kehrerc6e0f062015-05-03 11:04:34 -0500978 if not all(
979 isinstance(x, GeneralName) for x in authority_cert_issuer
980 ):
981 raise TypeError(
982 "authority_cert_issuer must be a list of GeneralName "
983 "objects"
984 )
Paul Kehrer2eb4ed92015-04-11 15:33:45 -0400985
986 if not isinstance(authority_cert_serial_number, six.integer_types):
987 raise TypeError(
988 "authority_cert_serial_number must be an integer"
989 )
990
991 self._key_identifier = key_identifier
992 self._authority_cert_issuer = authority_cert_issuer
993 self._authority_cert_serial_number = authority_cert_serial_number
994
995 def __repr__(self):
996 return (
997 "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
998 "authority_cert_issuer={0.authority_cert_issuer}, "
999 "authority_cert_serial_number={0.authority_cert_serial_number}"
1000 ")>".format(self)
1001 )
1002
Paul Kehrer2ca2eb32015-05-03 10:04:57 -05001003 def __eq__(self, other):
1004 if not isinstance(other, AuthorityKeyIdentifier):
1005 return NotImplemented
1006
1007 return (
1008 self.key_identifier == other.key_identifier and
1009 self.authority_cert_issuer == other.authority_cert_issuer and
1010 self.authority_cert_serial_number ==
1011 other.authority_cert_serial_number
1012 )
1013
1014 def __ne__(self, other):
1015 return not self == other
1016
Paul Kehrer2eb4ed92015-04-11 15:33:45 -04001017 key_identifier = utils.read_only_property("_key_identifier")
1018 authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
1019 authority_cert_serial_number = utils.read_only_property(
1020 "_authority_cert_serial_number"
1021 )
1022
1023
Paul Kehrer806bfb22015-02-02 17:05:24 -06001024OID_COMMON_NAME = ObjectIdentifier("2.5.4.3")
1025OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6")
1026OID_LOCALITY_NAME = ObjectIdentifier("2.5.4.7")
1027OID_STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8")
1028OID_ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10")
1029OID_ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11")
1030OID_SERIAL_NUMBER = ObjectIdentifier("2.5.4.5")
1031OID_SURNAME = ObjectIdentifier("2.5.4.4")
1032OID_GIVEN_NAME = ObjectIdentifier("2.5.4.42")
1033OID_TITLE = ObjectIdentifier("2.5.4.12")
1034OID_GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44")
1035OID_DN_QUALIFIER = ObjectIdentifier("2.5.4.46")
1036OID_PSEUDONYM = ObjectIdentifier("2.5.4.65")
1037OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25")
1038OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1")
Paul Kehrer912d3fb2015-01-29 11:19:22 -06001039
Paul Kehrer1a7ba872015-02-19 18:09:05 -06001040OID_RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4")
1041OID_RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5")
1042OID_RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14")
1043OID_RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11")
1044OID_RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12")
1045OID_RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13")
Paul Kehrer56da2a52015-02-11 23:35:07 -06001046OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1")
1047OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2")
1048OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3")
1049OID_ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4")
1050OID_DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3")
1051OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1")
1052OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
1053
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001054_SIG_OIDS_TO_HASH = {
Paul Kehrer1a7ba872015-02-19 18:09:05 -06001055 OID_RSA_WITH_MD5.dotted_string: hashes.MD5(),
1056 OID_RSA_WITH_SHA1.dotted_string: hashes.SHA1(),
1057 OID_RSA_WITH_SHA224.dotted_string: hashes.SHA224(),
1058 OID_RSA_WITH_SHA256.dotted_string: hashes.SHA256(),
1059 OID_RSA_WITH_SHA384.dotted_string: hashes.SHA384(),
1060 OID_RSA_WITH_SHA512.dotted_string: hashes.SHA512(),
Paul Kehrer42a87cb2015-02-13 18:53:24 -06001061 OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(),
1062 OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(),
1063 OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(),
1064 OID_ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(),
1065 OID_DSA_WITH_SHA1.dotted_string: hashes.SHA1(),
1066 OID_DSA_WITH_SHA224.dotted_string: hashes.SHA224(),
1067 OID_DSA_WITH_SHA256.dotted_string: hashes.SHA256()
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001068}
1069
Paul Kehrere1513fa2015-03-30 23:08:17 -05001070OID_SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1")
1071OID_CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2")
1072OID_CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3")
1073OID_EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4")
1074OID_TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8")
1075OID_OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9")
1076
Paul Kehrer3e6d5582015-05-02 21:57:56 -05001077OID_CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2")
1078OID_OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1")
1079
Paul Kehrer2b622582015-04-15 11:04:29 -04001080OID_CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1")
1081OID_CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2")
1082
Paul Kehrer912d3fb2015-01-29 11:19:22 -06001083
Paul Kehrerb2de9482014-12-11 14:54:48 -06001084@six.add_metaclass(abc.ABCMeta)
Paul Kehrere76cd272014-12-14 19:00:51 -06001085class Certificate(object):
Paul Kehrerb2de9482014-12-11 14:54:48 -06001086 @abc.abstractmethod
1087 def fingerprint(self, algorithm):
1088 """
1089 Returns bytes using digest passed.
1090 """
1091
1092 @abc.abstractproperty
1093 def serial(self):
1094 """
1095 Returns certificate serial number
1096 """
1097
1098 @abc.abstractproperty
1099 def version(self):
1100 """
1101 Returns the certificate version
1102 """
1103
1104 @abc.abstractmethod
1105 def public_key(self):
1106 """
1107 Returns the public key
1108 """
1109
1110 @abc.abstractproperty
1111 def not_valid_before(self):
1112 """
1113 Not before time (represented as UTC datetime)
1114 """
1115
1116 @abc.abstractproperty
1117 def not_valid_after(self):
1118 """
1119 Not after time (represented as UTC datetime)
1120 """
Paul Kehrer719d5362015-01-01 20:03:52 -06001121
1122 @abc.abstractproperty
1123 def issuer(self):
1124 """
1125 Returns the issuer name object.
1126 """
1127
1128 @abc.abstractproperty
1129 def subject(self):
1130 """
1131 Returns the subject name object.
1132 """
Paul Kehrer56da2a52015-02-11 23:35:07 -06001133
1134 @abc.abstractproperty
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001135 def signature_hash_algorithm(self):
Paul Kehrer56da2a52015-02-11 23:35:07 -06001136 """
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001137 Returns a HashAlgorithm corresponding to the type of the digest signed
1138 in the certificate.
Paul Kehrer56da2a52015-02-11 23:35:07 -06001139 """
Paul Kehrerdc480ad2015-02-23 12:14:54 -06001140
Paul Kehrer8c234d12015-05-15 09:27:22 -07001141 @abc.abstractproperty
1142 def extensions(self):
1143 """
1144 Returns an Extensions object.
1145 """
1146
Paul Kehrer8bbdc6f2015-04-30 16:47:16 -05001147 @abc.abstractmethod
1148 def __eq__(self, other):
1149 """
1150 Checks equality.
1151 """
1152
1153 @abc.abstractmethod
1154 def __ne__(self, other):
1155 """
1156 Checks not equal.
1157 """
1158
Paul Kehrerdc480ad2015-02-23 12:14:54 -06001159
1160@six.add_metaclass(abc.ABCMeta)
Paul Kehrera1a1f232015-03-15 15:34:35 -05001161class CertificateSigningRequest(object):
Paul Kehrerdc480ad2015-02-23 12:14:54 -06001162 @abc.abstractmethod
1163 def public_key(self):
1164 """
1165 Returns the public key
1166 """
1167
1168 @abc.abstractproperty
1169 def subject(self):
1170 """
1171 Returns the subject name object.
1172 """
1173
1174 @abc.abstractproperty
1175 def signature_hash_algorithm(self):
1176 """
1177 Returns a HashAlgorithm corresponding to the type of the digest signed
1178 in the certificate.
1179 """
Andre Caron6e721a92015-05-17 15:08:48 -04001180
1181 @abc.abstractproperty
1182 def extensions(self):
1183 """
1184 Returns the extensions in the signing request.
1185 """