blob: ec2092bb597c64b3f0f4f54341d1653f58f1bdf0 [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
281
Paul Kehrerffa2a152015-03-31 08:18:25 -0500282class ExtendedKeyUsage(object):
283 def __init__(self, usages):
Paul Kehrerb0476172015-05-02 19:34:51 -0500284 if not all(isinstance(x, ObjectIdentifier) for x in usages):
285 raise TypeError(
286 "Every item in the usages list must be an ObjectIdentifier"
287 )
Paul Kehrerffa2a152015-03-31 08:18:25 -0500288
289 self._usages = usages
290
291 def __iter__(self):
292 return iter(self._usages)
293
294 def __len__(self):
295 return len(self._usages)
296
Paul Kehrer23d10c32015-04-02 23:12:32 -0500297 def __repr__(self):
298 return "<ExtendedKeyUsage({0})>".format(self._usages)
299
Paul Kehrerb0476172015-05-02 19:34:51 -0500300 def __eq__(self, other):
301 if not isinstance(other, ExtendedKeyUsage):
302 return NotImplemented
303
Paul Kehrerf24bad72015-05-02 19:36:20 -0500304 return self._usages == other._usages
Paul Kehrerb0476172015-05-02 19:34:51 -0500305
306 def __ne__(self, other):
307 return not self == other
308
Paul Kehrerffa2a152015-03-31 08:18:25 -0500309
Paul Kehrer85894662015-03-22 13:19:31 -0500310class BasicConstraints(object):
311 def __init__(self, ca, path_length):
312 if not isinstance(ca, bool):
313 raise TypeError("ca must be a boolean value")
314
Paul Kehrer611d3d32015-03-22 13:31:18 -0500315 if path_length is not None and not ca:
Paul Kehrer8cf26422015-03-21 09:50:24 -0500316 raise ValueError("path_length must be None when ca is False")
317
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500318 if (
Paul Kehrer5553d572015-03-23 21:08:01 -0500319 path_length is not None and
320 (not isinstance(path_length, six.integer_types) or path_length < 0)
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500321 ):
Paul Kehrer8cf26422015-03-21 09:50:24 -0500322 raise TypeError(
323 "path_length must be a non-negative integer or None"
324 )
325
326 self._ca = ca
327 self._path_length = path_length
Paul Kehrer8cf26422015-03-21 09:50:24 -0500328
329 ca = utils.read_only_property("_ca")
330 path_length = utils.read_only_property("_path_length")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500331
332 def __repr__(self):
Paul Kehrer58b75692015-03-22 23:24:58 -0500333 return ("<BasicConstraints(ca={0.ca}, "
334 "path_length={0.path_length})>").format(self)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500335
Paul Kehrer3a69b132015-05-13 10:03:46 -0500336 def __eq__(self, other):
337 if not isinstance(other, BasicConstraints):
338 return NotImplemented
339
340 return self.ca == other.ca and self.path_length == other.path_length
341
342 def __ne__(self, other):
343 return not self == other
344
Paul Kehrer8cf26422015-03-21 09:50:24 -0500345
Paul Kehrercecbbba2015-03-30 14:58:38 -0500346class KeyUsage(object):
347 def __init__(self, digital_signature, content_commitment, key_encipherment,
348 data_encipherment, key_agreement, key_cert_sign, crl_sign,
349 encipher_only, decipher_only):
350 if not key_agreement and (encipher_only or decipher_only):
351 raise ValueError(
352 "encipher_only and decipher_only can only be true when "
353 "key_agreement is true"
354 )
355
356 self._digital_signature = digital_signature
357 self._content_commitment = content_commitment
358 self._key_encipherment = key_encipherment
359 self._data_encipherment = data_encipherment
360 self._key_agreement = key_agreement
361 self._key_cert_sign = key_cert_sign
362 self._crl_sign = crl_sign
363 self._encipher_only = encipher_only
364 self._decipher_only = decipher_only
365
366 digital_signature = utils.read_only_property("_digital_signature")
367 content_commitment = utils.read_only_property("_content_commitment")
368 key_encipherment = utils.read_only_property("_key_encipherment")
369 data_encipherment = utils.read_only_property("_data_encipherment")
370 key_agreement = utils.read_only_property("_key_agreement")
371 key_cert_sign = utils.read_only_property("_key_cert_sign")
372 crl_sign = utils.read_only_property("_crl_sign")
373
374 @property
375 def encipher_only(self):
376 if not self.key_agreement:
377 raise ValueError(
378 "encipher_only is undefined unless key_agreement is true"
379 )
380 else:
381 return self._encipher_only
382
383 @property
384 def decipher_only(self):
385 if not self.key_agreement:
386 raise ValueError(
387 "decipher_only is undefined unless key_agreement is true"
388 )
389 else:
390 return self._decipher_only
391
Paul Kehrerac3e5bb2015-04-02 23:07:10 -0500392 def __repr__(self):
393 try:
394 encipher_only = self.encipher_only
395 decipher_only = self.decipher_only
396 except ValueError:
Paul Kehrerb372e672015-04-15 11:05:24 -0400397 encipher_only = None
398 decipher_only = None
Paul Kehrerac3e5bb2015-04-02 23:07:10 -0500399
400 return ("<KeyUsage(digital_signature={0.digital_signature}, "
401 "content_commitment={0.content_commitment}, "
402 "key_encipherment={0.key_encipherment}, "
403 "data_encipherment={0.data_encipherment}, "
404 "key_agreement={0.key_agreement}, "
405 "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
406 "encipher_only={1}, decipher_only={2})>").format(
407 self, encipher_only, decipher_only)
408
Paul Kehrer8565f5e2015-05-13 09:57:09 -0500409 def __eq__(self, other):
410 if not isinstance(other, KeyUsage):
411 return NotImplemented
412
413 return (
414 self.digital_signature == other.digital_signature and
415 self.content_commitment == other.content_commitment and
416 self.key_encipherment == other.key_encipherment and
417 self.data_encipherment == other.data_encipherment and
418 self.key_agreement == other.key_agreement and
419 self.key_cert_sign == other.key_cert_sign and
420 self.crl_sign == other.crl_sign and
421 self._encipher_only == other._encipher_only and
422 self._decipher_only == other._decipher_only
423 )
424
425 def __ne__(self, other):
426 return not self == other
427
Paul Kehrercecbbba2015-03-30 14:58:38 -0500428
Paul Kehrer3e6d5582015-05-02 21:57:56 -0500429class AuthorityInformationAccess(object):
430 def __init__(self, descriptions):
431 if not all(isinstance(x, AccessDescription) for x in descriptions):
432 raise TypeError(
433 "Every item in the descriptions list must be an "
434 "AccessDescription"
435 )
436
437 self._descriptions = descriptions
438
439 def __iter__(self):
440 return iter(self._descriptions)
441
442 def __len__(self):
443 return len(self._descriptions)
444
445 def __repr__(self):
446 return "<AuthorityInformationAccess({0})>".format(self._descriptions)
447
448 def __eq__(self, other):
449 if not isinstance(other, AuthorityInformationAccess):
450 return NotImplemented
451
452 return self._descriptions == other._descriptions
453
454 def __ne__(self, other):
455 return not self == other
456
457
458class AccessDescription(object):
459 def __init__(self, access_method, access_location):
460 if not (access_method == OID_OCSP or access_method == OID_CA_ISSUERS):
Paul Kehrerf506bca2015-05-02 22:31:47 -0500461 raise ValueError(
462 "access_method must be OID_OCSP or OID_CA_ISSUERS"
463 )
Paul Kehrer3e6d5582015-05-02 21:57:56 -0500464
465 if not isinstance(access_location, GeneralName):
466 raise TypeError("access_location must be a GeneralName")
467
468 self._access_method = access_method
469 self._access_location = access_location
470
471 def __repr__(self):
472 return (
473 "<AccessDescription(access_method={0.access_method}, access_locati"
474 "on={0.access_location})>".format(self)
475 )
476
477 def __eq__(self, other):
478 if not isinstance(other, AccessDescription):
479 return NotImplemented
480
481 return (
482 self.access_method == other.access_method and
483 self.access_location == other.access_location
484 )
485
486 def __ne__(self, other):
487 return not self == other
488
489 access_method = utils.read_only_property("_access_method")
490 access_location = utils.read_only_property("_access_location")
491
492
Paul Kehrer2b622582015-04-15 11:04:29 -0400493class CertificatePolicies(object):
494 def __init__(self, policies):
Paul Kehrerf61ec742015-04-18 20:42:39 -0500495 if not all(isinstance(x, PolicyInformation) for x in policies):
Paul Kehrer2b622582015-04-15 11:04:29 -0400496 raise TypeError(
497 "Every item in the policies list must be a "
498 "PolicyInformation"
499 )
500
501 self._policies = policies
502
503 def __iter__(self):
504 return iter(self._policies)
505
506 def __len__(self):
507 return len(self._policies)
508
509 def __repr__(self):
510 return "<CertificatePolicies({0})>".format(self._policies)
511
Paul Kehrerc56ab622015-05-03 09:56:31 -0500512 def __eq__(self, other):
513 if not isinstance(other, CertificatePolicies):
514 return NotImplemented
515
516 return self._policies == other._policies
517
518 def __ne__(self, other):
519 return not self == other
520
Paul Kehrer2b622582015-04-15 11:04:29 -0400521
522class PolicyInformation(object):
523 def __init__(self, policy_identifier, policy_qualifiers):
524 if not isinstance(policy_identifier, ObjectIdentifier):
525 raise TypeError("policy_identifier must be an ObjectIdentifier")
526
527 self._policy_identifier = policy_identifier
528 if policy_qualifiers and not all(
Paul Kehrerba35b3b2015-05-10 13:07:59 -0500529 isinstance(
530 x, (six.text_type, UserNotice)
531 ) for x in policy_qualifiers
Paul Kehrer2b622582015-04-15 11:04:29 -0400532 ):
533 raise TypeError(
Paul Kehrerba35b3b2015-05-10 13:07:59 -0500534 "policy_qualifiers must be a list of strings and/or UserNotice"
535 " objects or None"
Paul Kehrer2b622582015-04-15 11:04:29 -0400536 )
537
538 self._policy_qualifiers = policy_qualifiers
539
540 def __repr__(self):
541 return (
542 "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
543 "y_qualifiers={0.policy_qualifiers})>".format(self)
544 )
545
Paul Kehrerc56ab622015-05-03 09:56:31 -0500546 def __eq__(self, other):
547 if not isinstance(other, PolicyInformation):
548 return NotImplemented
549
550 return (
551 self.policy_identifier == other.policy_identifier and
552 self.policy_qualifiers == other.policy_qualifiers
553 )
554
555 def __ne__(self, other):
556 return not self == other
557
Paul Kehrer2b622582015-04-15 11:04:29 -0400558 policy_identifier = utils.read_only_property("_policy_identifier")
559 policy_qualifiers = utils.read_only_property("_policy_qualifiers")
560
561
Paul Kehrer2b622582015-04-15 11:04:29 -0400562class UserNotice(object):
563 def __init__(self, notice_reference, explicit_text):
564 if notice_reference and not isinstance(
565 notice_reference, NoticeReference
566 ):
567 raise TypeError(
568 "notice_reference must be None or a NoticeReference"
569 )
570
571 self._notice_reference = notice_reference
572 self._explicit_text = explicit_text
573
574 def __repr__(self):
575 return (
576 "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
Paul Kehrer9aaef9e2015-05-11 10:49:20 -0500577 "{0.explicit_text!r})>".format(self)
Paul Kehrer2b622582015-04-15 11:04:29 -0400578 )
579
Paul Kehrerc56ab622015-05-03 09:56:31 -0500580 def __eq__(self, other):
581 if not isinstance(other, UserNotice):
582 return NotImplemented
583
584 return (
585 self.notice_reference == other.notice_reference and
586 self.explicit_text == other.explicit_text
587 )
588
589 def __ne__(self, other):
590 return not self == other
591
Paul Kehrer2b622582015-04-15 11:04:29 -0400592 notice_reference = utils.read_only_property("_notice_reference")
593 explicit_text = utils.read_only_property("_explicit_text")
594
595
596class NoticeReference(object):
597 def __init__(self, organization, notice_numbers):
598 self._organization = organization
Paul Kehrer6e198b02015-05-12 15:53:38 -0500599 if not isinstance(notice_numbers, list) or not all(
Paul Kehrerf61ec742015-04-18 20:42:39 -0500600 isinstance(x, int) for x in notice_numbers
Paul Kehrer2b622582015-04-15 11:04:29 -0400601 ):
602 raise TypeError(
Paul Kehrer6e198b02015-05-12 15:53:38 -0500603 "notice_numbers must be a list of integers"
Paul Kehrer2b622582015-04-15 11:04:29 -0400604 )
605
606 self._notice_numbers = notice_numbers
607
608 def __repr__(self):
609 return (
Paul Kehrer73be2ca2015-05-11 21:22:38 -0500610 "<NoticeReference(organization={0.organization!r}, notice_numbers="
Paul Kehrer2b622582015-04-15 11:04:29 -0400611 "{0.notice_numbers})>".format(self)
612 )
613
Paul Kehrerc56ab622015-05-03 09:56:31 -0500614 def __eq__(self, other):
615 if not isinstance(other, NoticeReference):
616 return NotImplemented
617
618 return (
619 self.organization == other.organization and
620 self.notice_numbers == other.notice_numbers
621 )
622
623 def __ne__(self, other):
624 return not self == other
625
Paul Kehrer2b622582015-04-15 11:04:29 -0400626 organization = utils.read_only_property("_organization")
627 notice_numbers = utils.read_only_property("_notice_numbers")
628
629
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500630class SubjectKeyIdentifier(object):
631 def __init__(self, digest):
632 self._digest = digest
633
634 digest = utils.read_only_property("_digest")
635
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500636 def __repr__(self):
Paul Kehrercbfb1012015-04-10 20:57:20 -0400637 return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500638
639 def __eq__(self, other):
640 if not isinstance(other, SubjectKeyIdentifier):
641 return NotImplemented
642
643 return (
644 self.digest == other.digest
645 )
646
647 def __ne__(self, other):
648 return not self == other
649
650
Paul Kehrer5a485522015-05-06 00:29:12 -0500651class CRLDistributionPoints(object):
652 def __init__(self, distribution_points):
653 if not all(
654 isinstance(x, DistributionPoint) for x in distribution_points
655 ):
656 raise TypeError(
657 "distribution_points must be a list of DistributionPoint "
658 "objects"
659 )
660
661 self._distribution_points = distribution_points
662
663 def __iter__(self):
664 return iter(self._distribution_points)
665
666 def __len__(self):
667 return len(self._distribution_points)
668
669 def __repr__(self):
670 return "<CRLDistributionPoints({0})>".format(self._distribution_points)
671
672 def __eq__(self, other):
673 if not isinstance(other, CRLDistributionPoints):
674 return NotImplemented
675
676 return self._distribution_points == other._distribution_points
677
678 def __ne__(self, other):
679 return not self == other
680
681
682class DistributionPoint(object):
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500683 def __init__(self, full_name, relative_name, reasons, crl_issuer):
684 if full_name and relative_name:
685 raise ValueError(
686 "At least one of full_name and relative_name must be None"
687 )
688
689 if full_name and not all(
690 isinstance(x, GeneralName) for x in full_name
691 ):
692 raise TypeError(
693 "full_name must be a list of GeneralName objects"
694 )
695
696 if relative_name and not isinstance(relative_name, Name):
697 raise TypeError("relative_name must be a Name")
Paul Kehrer5a485522015-05-06 00:29:12 -0500698
699 if crl_issuer and not all(
700 isinstance(x, GeneralName) for x in crl_issuer
701 ):
702 raise TypeError(
703 "crl_issuer must be None or a list of general names"
704 )
705
Paul Kehrer3fd02602015-05-09 19:46:13 -0500706 if reasons and (not isinstance(reasons, frozenset) or not all(
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500707 isinstance(x, ReasonFlags) for x in reasons
Paul Kehrer3fd02602015-05-09 19:46:13 -0500708 )):
709 raise TypeError("reasons must be None or frozenset of ReasonFlags")
Paul Kehrer5a485522015-05-06 00:29:12 -0500710
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500711 if reasons and (
712 ReasonFlags.unspecified in reasons or
713 ReasonFlags.remove_from_crl in reasons
714 ):
Paul Kehrer5a485522015-05-06 00:29:12 -0500715 raise ValueError(
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500716 "unspecified and remove_from_crl are not valid reasons in a "
717 "DistributionPoint"
718 )
719
720 if reasons and not crl_issuer and not (full_name or relative_name):
721 raise ValueError(
722 "You must supply crl_issuer, full_name, or relative_name when "
Paul Kehrer5a485522015-05-06 00:29:12 -0500723 "reasons is not None"
724 )
725
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500726 self._full_name = full_name
727 self._relative_name = relative_name
Paul Kehrer5a485522015-05-06 00:29:12 -0500728 self._reasons = reasons
729 self._crl_issuer = crl_issuer
730
731 def __repr__(self):
732 return (
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500733 "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
734 "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_is"
735 "suer})>".format(self)
Paul Kehrer5a485522015-05-06 00:29:12 -0500736 )
737
738 def __eq__(self, other):
739 if not isinstance(other, DistributionPoint):
740 return NotImplemented
741
742 return (
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500743 self.full_name == other.full_name and
744 self.relative_name == other.relative_name and
Paul Kehrer5a485522015-05-06 00:29:12 -0500745 self.reasons == other.reasons and
746 self.crl_issuer == other.crl_issuer
747 )
748
749 def __ne__(self, other):
750 return not self == other
751
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500752 full_name = utils.read_only_property("_full_name")
753 relative_name = utils.read_only_property("_relative_name")
Paul Kehrer5a485522015-05-06 00:29:12 -0500754 reasons = utils.read_only_property("_reasons")
755 crl_issuer = utils.read_only_property("_crl_issuer")
756
757
Paul Kehrer4e8dacd2015-05-09 10:38:23 -0500758class ReasonFlags(Enum):
759 unspecified = "unspecified"
760 key_compromise = "keyCompromise"
761 ca_compromise = "cACompromise"
762 affiliation_changed = "affiliationChanged"
763 superseded = "superseded"
764 cessation_of_operation = "cessationOfOperation"
765 certificate_hold = "certificateHold"
766 privilege_withdrawn = "privilegeWithdrawn"
767 aa_compromise = "aACompromise"
768 remove_from_crl = "removeFromCRL"
Paul Kehrer5a485522015-05-06 00:29:12 -0500769
770
Paul Kehrer31bdf792015-03-25 14:11:00 -0500771@six.add_metaclass(abc.ABCMeta)
772class GeneralName(object):
773 @abc.abstractproperty
774 def value(self):
775 """
776 Return the value of the object
777 """
778
779
780@utils.register_interface(GeneralName)
781class RFC822Name(object):
782 def __init__(self, value):
783 if not isinstance(value, six.text_type):
784 raise TypeError("value must be a unicode string")
785
786 self._value = value
787
788 value = utils.read_only_property("_value")
789
790 def __repr__(self):
791 return "<RFC822Name(value={0})>".format(self.value)
792
793 def __eq__(self, other):
794 if not isinstance(other, RFC822Name):
795 return NotImplemented
796
797 return self.value == other.value
798
799 def __ne__(self, other):
800 return not self == other
801
802
803@utils.register_interface(GeneralName)
804class DNSName(object):
805 def __init__(self, value):
806 if not isinstance(value, six.text_type):
807 raise TypeError("value must be a unicode string")
808
809 self._value = value
810
811 value = utils.read_only_property("_value")
812
813 def __repr__(self):
814 return "<DNSName(value={0})>".format(self.value)
815
816 def __eq__(self, other):
817 if not isinstance(other, DNSName):
818 return NotImplemented
819
820 return self.value == other.value
821
822 def __ne__(self, other):
823 return not self == other
824
825
826@utils.register_interface(GeneralName)
827class UniformResourceIdentifier(object):
828 def __init__(self, value):
829 if not isinstance(value, six.text_type):
830 raise TypeError("value must be a unicode string")
831
832 self._value = value
833
834 value = utils.read_only_property("_value")
835
836 def __repr__(self):
837 return "<UniformResourceIdentifier(value={0})>".format(self.value)
838
839 def __eq__(self, other):
840 if not isinstance(other, UniformResourceIdentifier):
841 return NotImplemented
842
843 return self.value == other.value
844
845 def __ne__(self, other):
846 return not self == other
847
848
849@utils.register_interface(GeneralName)
850class DirectoryName(object):
851 def __init__(self, value):
852 if not isinstance(value, Name):
853 raise TypeError("value must be a Name")
854
855 self._value = value
856
857 value = utils.read_only_property("_value")
858
859 def __repr__(self):
860 return "<DirectoryName(value={0})>".format(self.value)
861
862 def __eq__(self, other):
863 if not isinstance(other, DirectoryName):
864 return NotImplemented
865
866 return self.value == other.value
867
868 def __ne__(self, other):
869 return not self == other
870
871
872@utils.register_interface(GeneralName)
873class RegisteredID(object):
874 def __init__(self, value):
875 if not isinstance(value, ObjectIdentifier):
876 raise TypeError("value must be an ObjectIdentifier")
877
878 self._value = value
879
880 value = utils.read_only_property("_value")
881
882 def __repr__(self):
883 return "<RegisteredID(value={0})>".format(self.value)
884
885 def __eq__(self, other):
886 if not isinstance(other, RegisteredID):
887 return NotImplemented
888
889 return self.value == other.value
890
891 def __ne__(self, other):
892 return not self == other
893
894
895@utils.register_interface(GeneralName)
896class IPAddress(object):
897 def __init__(self, value):
898 if not isinstance(
899 value, (ipaddress.IPv4Address, ipaddress.IPv6Address)
900 ):
901 raise TypeError(
902 "value must be an instance of ipaddress.IPv4Address or "
903 "ipaddress.IPv6Address"
904 )
905
906 self._value = value
907
908 value = utils.read_only_property("_value")
909
910 def __repr__(self):
911 return "<IPAddress(value={0})>".format(self.value)
912
913 def __eq__(self, other):
914 if not isinstance(other, IPAddress):
915 return NotImplemented
916
917 return self.value == other.value
918
919 def __ne__(self, other):
920 return not self == other
921
922
923class SubjectAlternativeName(object):
924 def __init__(self, general_names):
Paul Kehrerd04b39b2015-04-21 08:44:17 -0500925 if not all(isinstance(x, GeneralName) for x in general_names):
926 raise TypeError(
927 "Every item in the general_names list must be an "
928 "object conforming to the GeneralName interface"
929 )
930
Paul Kehrer31bdf792015-03-25 14:11:00 -0500931 self._general_names = general_names
932
933 def __iter__(self):
934 return iter(self._general_names)
935
936 def __len__(self):
937 return len(self._general_names)
938
939 def get_values_for_type(self, type):
940 return [i.value for i in self if isinstance(i, type)]
941
942 def __repr__(self):
943 return "<SubjectAlternativeName({0})>".format(self._general_names)
944
Paul Kehrer58cc3972015-05-13 10:00:41 -0500945 def __eq__(self, other):
946 if not isinstance(other, SubjectAlternativeName):
947 return NotImplemented
948
949 return self._general_names == other._general_names
950
951 def __ne__(self, other):
952 return not self == other
953
Paul Kehrer31bdf792015-03-25 14:11:00 -0500954
Paul Kehrer2eb4ed92015-04-11 15:33:45 -0400955class AuthorityKeyIdentifier(object):
956 def __init__(self, key_identifier, authority_cert_issuer,
957 authority_cert_serial_number):
958 if authority_cert_issuer or authority_cert_serial_number:
959 if not authority_cert_issuer or not authority_cert_serial_number:
960 raise ValueError(
961 "authority_cert_issuer and authority_cert_serial_number "
962 "must both be present or both None"
963 )
964
Paul Kehrerc6e0f062015-05-03 11:04:34 -0500965 if not all(
966 isinstance(x, GeneralName) for x in authority_cert_issuer
967 ):
968 raise TypeError(
969 "authority_cert_issuer must be a list of GeneralName "
970 "objects"
971 )
Paul Kehrer2eb4ed92015-04-11 15:33:45 -0400972
973 if not isinstance(authority_cert_serial_number, six.integer_types):
974 raise TypeError(
975 "authority_cert_serial_number must be an integer"
976 )
977
978 self._key_identifier = key_identifier
979 self._authority_cert_issuer = authority_cert_issuer
980 self._authority_cert_serial_number = authority_cert_serial_number
981
982 def __repr__(self):
983 return (
984 "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
985 "authority_cert_issuer={0.authority_cert_issuer}, "
986 "authority_cert_serial_number={0.authority_cert_serial_number}"
987 ")>".format(self)
988 )
989
Paul Kehrer2ca2eb32015-05-03 10:04:57 -0500990 def __eq__(self, other):
991 if not isinstance(other, AuthorityKeyIdentifier):
992 return NotImplemented
993
994 return (
995 self.key_identifier == other.key_identifier and
996 self.authority_cert_issuer == other.authority_cert_issuer and
997 self.authority_cert_serial_number ==
998 other.authority_cert_serial_number
999 )
1000
1001 def __ne__(self, other):
1002 return not self == other
1003
Paul Kehrer2eb4ed92015-04-11 15:33:45 -04001004 key_identifier = utils.read_only_property("_key_identifier")
1005 authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
1006 authority_cert_serial_number = utils.read_only_property(
1007 "_authority_cert_serial_number"
1008 )
1009
1010
Paul Kehrer806bfb22015-02-02 17:05:24 -06001011OID_COMMON_NAME = ObjectIdentifier("2.5.4.3")
1012OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6")
1013OID_LOCALITY_NAME = ObjectIdentifier("2.5.4.7")
1014OID_STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8")
1015OID_ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10")
1016OID_ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11")
1017OID_SERIAL_NUMBER = ObjectIdentifier("2.5.4.5")
1018OID_SURNAME = ObjectIdentifier("2.5.4.4")
1019OID_GIVEN_NAME = ObjectIdentifier("2.5.4.42")
1020OID_TITLE = ObjectIdentifier("2.5.4.12")
1021OID_GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44")
1022OID_DN_QUALIFIER = ObjectIdentifier("2.5.4.46")
1023OID_PSEUDONYM = ObjectIdentifier("2.5.4.65")
1024OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25")
1025OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1")
Paul Kehrer912d3fb2015-01-29 11:19:22 -06001026
Paul Kehrer1a7ba872015-02-19 18:09:05 -06001027OID_RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4")
1028OID_RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5")
1029OID_RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14")
1030OID_RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11")
1031OID_RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12")
1032OID_RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13")
Paul Kehrer56da2a52015-02-11 23:35:07 -06001033OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1")
1034OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2")
1035OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3")
1036OID_ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4")
1037OID_DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3")
1038OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1")
1039OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
1040
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001041_SIG_OIDS_TO_HASH = {
Paul Kehrer1a7ba872015-02-19 18:09:05 -06001042 OID_RSA_WITH_MD5.dotted_string: hashes.MD5(),
1043 OID_RSA_WITH_SHA1.dotted_string: hashes.SHA1(),
1044 OID_RSA_WITH_SHA224.dotted_string: hashes.SHA224(),
1045 OID_RSA_WITH_SHA256.dotted_string: hashes.SHA256(),
1046 OID_RSA_WITH_SHA384.dotted_string: hashes.SHA384(),
1047 OID_RSA_WITH_SHA512.dotted_string: hashes.SHA512(),
Paul Kehrer42a87cb2015-02-13 18:53:24 -06001048 OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(),
1049 OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(),
1050 OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(),
1051 OID_ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(),
1052 OID_DSA_WITH_SHA1.dotted_string: hashes.SHA1(),
1053 OID_DSA_WITH_SHA224.dotted_string: hashes.SHA224(),
1054 OID_DSA_WITH_SHA256.dotted_string: hashes.SHA256()
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001055}
1056
Paul Kehrere1513fa2015-03-30 23:08:17 -05001057OID_SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1")
1058OID_CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2")
1059OID_CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3")
1060OID_EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4")
1061OID_TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8")
1062OID_OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9")
1063
Paul Kehrer3e6d5582015-05-02 21:57:56 -05001064OID_CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2")
1065OID_OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1")
1066
Paul Kehrer2b622582015-04-15 11:04:29 -04001067OID_CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1")
1068OID_CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2")
1069
Paul Kehrer912d3fb2015-01-29 11:19:22 -06001070
Paul Kehrerb2de9482014-12-11 14:54:48 -06001071@six.add_metaclass(abc.ABCMeta)
Paul Kehrere76cd272014-12-14 19:00:51 -06001072class Certificate(object):
Paul Kehrerb2de9482014-12-11 14:54:48 -06001073 @abc.abstractmethod
1074 def fingerprint(self, algorithm):
1075 """
1076 Returns bytes using digest passed.
1077 """
1078
1079 @abc.abstractproperty
1080 def serial(self):
1081 """
1082 Returns certificate serial number
1083 """
1084
1085 @abc.abstractproperty
1086 def version(self):
1087 """
1088 Returns the certificate version
1089 """
1090
1091 @abc.abstractmethod
1092 def public_key(self):
1093 """
1094 Returns the public key
1095 """
1096
1097 @abc.abstractproperty
1098 def not_valid_before(self):
1099 """
1100 Not before time (represented as UTC datetime)
1101 """
1102
1103 @abc.abstractproperty
1104 def not_valid_after(self):
1105 """
1106 Not after time (represented as UTC datetime)
1107 """
Paul Kehrer719d5362015-01-01 20:03:52 -06001108
1109 @abc.abstractproperty
1110 def issuer(self):
1111 """
1112 Returns the issuer name object.
1113 """
1114
1115 @abc.abstractproperty
1116 def subject(self):
1117 """
1118 Returns the subject name object.
1119 """
Paul Kehrer56da2a52015-02-11 23:35:07 -06001120
1121 @abc.abstractproperty
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001122 def signature_hash_algorithm(self):
Paul Kehrer56da2a52015-02-11 23:35:07 -06001123 """
Paul Kehrer8802a5b2015-02-13 12:06:57 -06001124 Returns a HashAlgorithm corresponding to the type of the digest signed
1125 in the certificate.
Paul Kehrer56da2a52015-02-11 23:35:07 -06001126 """
Paul Kehrerdc480ad2015-02-23 12:14:54 -06001127
Paul Kehrer8c234d12015-05-15 09:27:22 -07001128 @abc.abstractproperty
1129 def extensions(self):
1130 """
1131 Returns an Extensions object.
1132 """
1133
Paul Kehrer8bbdc6f2015-04-30 16:47:16 -05001134 @abc.abstractmethod
1135 def __eq__(self, other):
1136 """
1137 Checks equality.
1138 """
1139
1140 @abc.abstractmethod
1141 def __ne__(self, other):
1142 """
1143 Checks not equal.
1144 """
1145
Paul Kehrerdc480ad2015-02-23 12:14:54 -06001146
1147@six.add_metaclass(abc.ABCMeta)
Paul Kehrera1a1f232015-03-15 15:34:35 -05001148class CertificateSigningRequest(object):
Paul Kehrerdc480ad2015-02-23 12:14:54 -06001149 @abc.abstractmethod
1150 def public_key(self):
1151 """
1152 Returns the public key
1153 """
1154
1155 @abc.abstractproperty
1156 def subject(self):
1157 """
1158 Returns the subject name object.
1159 """
1160
1161 @abc.abstractproperty
1162 def signature_hash_algorithm(self):
1163 """
1164 Returns a HashAlgorithm corresponding to the type of the digest signed
1165 in the certificate.
1166 """