blob: df37934af15834dc8d0f0d39bf332fca5a758cac [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 Kehrer1eb82a62015-03-31 20:00:33 -05008import binascii
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 Kehrer806bfb22015-02-02 17:05:24 -060070}
71
72
Paul Kehrere76cd272014-12-14 19:00:51 -060073class Version(Enum):
Paul Kehrer016e08a2014-11-26 09:41:18 -100074 v1 = 0
75 v3 = 2
76
77
Paul Kehrer016e08a2014-11-26 09:41:18 -100078def load_pem_x509_certificate(data, backend):
79 return backend.load_pem_x509_certificate(data)
80
81
Paul Kehrer016e08a2014-11-26 09:41:18 -100082def load_der_x509_certificate(data, backend):
83 return backend.load_der_x509_certificate(data)
Paul Kehrera68fd332014-11-27 07:08:40 -100084
85
Paul Kehrer31e39882015-03-11 11:37:04 -050086def load_pem_x509_csr(data, backend):
87 return backend.load_pem_x509_csr(data)
Paul Kehrerdc480ad2015-02-23 12:14:54 -060088
89
Paul Kehrer1effb6e2015-03-30 15:05:59 -050090def load_der_x509_csr(data, backend):
91 return backend.load_der_x509_csr(data)
92
93
Paul Kehrere76cd272014-12-14 19:00:51 -060094class InvalidVersion(Exception):
Paul Kehrerd5cccf72014-12-15 17:20:33 -060095 def __init__(self, msg, parsed_version):
96 super(InvalidVersion, self).__init__(msg)
97 self.parsed_version = parsed_version
Paul Kehrerb2de9482014-12-11 14:54:48 -060098
99
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500100class DuplicateExtension(Exception):
101 def __init__(self, msg, oid):
102 super(DuplicateExtension, self).__init__(msg)
103 self.oid = oid
104
105
106class UnsupportedExtension(Exception):
107 def __init__(self, msg, oid):
108 super(UnsupportedExtension, self).__init__(msg)
109 self.oid = oid
110
111
Paul Kehrerfa56a232015-03-17 13:14:03 -0500112class ExtensionNotFound(Exception):
113 def __init__(self, msg, oid):
114 super(ExtensionNotFound, self).__init__(msg)
115 self.oid = oid
116
117
Paul Kehrer806bfb22015-02-02 17:05:24 -0600118class NameAttribute(object):
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600119 def __init__(self, oid, value):
120 if not isinstance(oid, ObjectIdentifier):
Paul Kehrer858b9b72015-02-05 09:50:31 -0600121 raise TypeError(
122 "oid argument must be an ObjectIdentifier instance."
123 )
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600124
125 self._oid = oid
126 self._value = value
127
128 oid = utils.read_only_property("_oid")
129 value = utils.read_only_property("_value")
130
131 def __eq__(self, other):
Paul Kehrer806bfb22015-02-02 17:05:24 -0600132 if not isinstance(other, NameAttribute):
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600133 return NotImplemented
134
135 return (
136 self.oid == other.oid and
137 self.value == other.value
138 )
139
140 def __ne__(self, other):
141 return not self == other
142
Paul Kehrera498be82015-02-12 15:00:56 -0600143 def __repr__(self):
Alex Gaynord6b63da2015-03-23 00:25:44 -0400144 return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self)
Paul Kehrera498be82015-02-12 15:00:56 -0600145
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600146
147class ObjectIdentifier(object):
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600148 def __init__(self, dotted_string):
149 self._dotted_string = dotted_string
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600150
151 def __eq__(self, other):
152 if not isinstance(other, ObjectIdentifier):
153 return NotImplemented
154
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600155 return self._dotted_string == other._dotted_string
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600156
157 def __ne__(self, other):
158 return not self == other
159
160 def __repr__(self):
161 return "<ObjectIdentifier(oid={0}, name={1})>".format(
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600162 self._dotted_string,
163 _OID_NAMES.get(self._dotted_string, "Unknown OID")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600164 )
165
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500166 def __hash__(self):
167 return hash(self.dotted_string)
168
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600169 dotted_string = utils.read_only_property("_dotted_string")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600170
171
Paul Kehrer719d5362015-01-01 20:03:52 -0600172class Name(object):
173 def __init__(self, attributes):
174 self._attributes = attributes
175
Paul Kehrere901d642015-02-11 18:50:58 -0600176 def get_attributes_for_oid(self, oid):
Alex Gaynorf9574232015-02-19 13:56:50 -0800177 return [i for i in self if i.oid == oid]
Paul Kehrer719d5362015-01-01 20:03:52 -0600178
Paul Kehrer719d5362015-01-01 20:03:52 -0600179 def __eq__(self, other):
180 if not isinstance(other, Name):
181 return NotImplemented
182
Paul Kehrer53d8d492015-02-13 18:47:30 -0600183 return self._attributes == other._attributes
Paul Kehrer719d5362015-01-01 20:03:52 -0600184
185 def __ne__(self, other):
186 return not self == other
187
Paul Kehrer53d8d492015-02-13 18:47:30 -0600188 def __iter__(self):
Paul Kehrer8b21a4a2015-02-14 07:56:36 -0600189 return iter(self._attributes)
Paul Kehrer53d8d492015-02-13 18:47:30 -0600190
191 def __len__(self):
192 return len(self._attributes)
193
Paul Kehrer719d5362015-01-01 20:03:52 -0600194
Paul Kehrerd08b5492015-04-04 15:19:16 -0500195OID_SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9")
196OID_SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14")
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500197OID_KEY_USAGE = ObjectIdentifier("2.5.29.15")
Paul Kehrerd08b5492015-04-04 15:19:16 -0500198OID_SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17")
199OID_ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500200OID_BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19")
Paul Kehrerd08b5492015-04-04 15:19:16 -0500201OID_NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30")
202OID_CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31")
203OID_CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32")
204OID_POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33")
205OID_AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35")
206OID_POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36")
207OID_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37")
208OID_FRESHEST_CRL = ObjectIdentifier("2.5.29.46")
209OID_INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54")
210OID_AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1")
211OID_SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11")
212OID_OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500213
214
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500215class Extensions(object):
216 def __init__(self, extensions):
217 self._extensions = extensions
218
Paul Kehrerfa56a232015-03-17 13:14:03 -0500219 def get_extension_for_oid(self, oid):
220 for ext in self:
221 if ext.oid == oid:
222 return ext
223
224 raise ExtensionNotFound("No {0} extension was found".format(oid), oid)
225
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500226 def __iter__(self):
227 return iter(self._extensions)
228
229 def __len__(self):
230 return len(self._extensions)
231
232
Paul Kehrer8cf26422015-03-21 09:50:24 -0500233class Extension(object):
Paul Kehrer85894662015-03-22 13:19:31 -0500234 def __init__(self, oid, critical, value):
235 if not isinstance(oid, ObjectIdentifier):
236 raise TypeError(
237 "oid argument must be an ObjectIdentifier instance."
238 )
Paul Kehrer8cf26422015-03-21 09:50:24 -0500239
240 if not isinstance(critical, bool):
241 raise TypeError("critical must be a boolean value")
242
Paul Kehrer85894662015-03-22 13:19:31 -0500243 self._oid = oid
244 self._critical = critical
245 self._value = value
246
247 oid = utils.read_only_property("_oid")
248 critical = utils.read_only_property("_critical")
249 value = utils.read_only_property("_value")
250
251 def __repr__(self):
Paul Kehrer58b75692015-03-22 23:24:58 -0500252 return ("<Extension(oid={0.oid}, critical={0.critical}, "
253 "value={0.value})>").format(self)
Paul Kehrer85894662015-03-22 13:19:31 -0500254
255
Paul Kehrerffa2a152015-03-31 08:18:25 -0500256class ExtendedKeyUsage(object):
257 def __init__(self, usages):
258 for oid in usages:
259 if not isinstance(oid, ObjectIdentifier):
260 raise TypeError(
261 "Every item in the usages list must be an ObjectIdentifier"
262 )
263
264 self._usages = usages
265
266 def __iter__(self):
267 return iter(self._usages)
268
269 def __len__(self):
270 return len(self._usages)
271
Paul Kehrer23d10c32015-04-02 23:12:32 -0500272 def __repr__(self):
273 return "<ExtendedKeyUsage({0})>".format(self._usages)
274
Paul Kehrerffa2a152015-03-31 08:18:25 -0500275
Paul Kehrer85894662015-03-22 13:19:31 -0500276class BasicConstraints(object):
277 def __init__(self, ca, path_length):
278 if not isinstance(ca, bool):
279 raise TypeError("ca must be a boolean value")
280
Paul Kehrer611d3d32015-03-22 13:31:18 -0500281 if path_length is not None and not ca:
Paul Kehrer8cf26422015-03-21 09:50:24 -0500282 raise ValueError("path_length must be None when ca is False")
283
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500284 if (
Paul Kehrer5553d572015-03-23 21:08:01 -0500285 path_length is not None and
286 (not isinstance(path_length, six.integer_types) or path_length < 0)
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500287 ):
Paul Kehrer8cf26422015-03-21 09:50:24 -0500288 raise TypeError(
289 "path_length must be a non-negative integer or None"
290 )
291
292 self._ca = ca
293 self._path_length = path_length
Paul Kehrer8cf26422015-03-21 09:50:24 -0500294
295 ca = utils.read_only_property("_ca")
296 path_length = utils.read_only_property("_path_length")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500297
298 def __repr__(self):
Paul Kehrer58b75692015-03-22 23:24:58 -0500299 return ("<BasicConstraints(ca={0.ca}, "
300 "path_length={0.path_length})>").format(self)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500301
302
Paul Kehrercecbbba2015-03-30 14:58:38 -0500303class KeyUsage(object):
304 def __init__(self, digital_signature, content_commitment, key_encipherment,
305 data_encipherment, key_agreement, key_cert_sign, crl_sign,
306 encipher_only, decipher_only):
307 if not key_agreement and (encipher_only or decipher_only):
308 raise ValueError(
309 "encipher_only and decipher_only can only be true when "
310 "key_agreement is true"
311 )
312
313 self._digital_signature = digital_signature
314 self._content_commitment = content_commitment
315 self._key_encipherment = key_encipherment
316 self._data_encipherment = data_encipherment
317 self._key_agreement = key_agreement
318 self._key_cert_sign = key_cert_sign
319 self._crl_sign = crl_sign
320 self._encipher_only = encipher_only
321 self._decipher_only = decipher_only
322
323 digital_signature = utils.read_only_property("_digital_signature")
324 content_commitment = utils.read_only_property("_content_commitment")
325 key_encipherment = utils.read_only_property("_key_encipherment")
326 data_encipherment = utils.read_only_property("_data_encipherment")
327 key_agreement = utils.read_only_property("_key_agreement")
328 key_cert_sign = utils.read_only_property("_key_cert_sign")
329 crl_sign = utils.read_only_property("_crl_sign")
330
331 @property
332 def encipher_only(self):
333 if not self.key_agreement:
334 raise ValueError(
335 "encipher_only is undefined unless key_agreement is true"
336 )
337 else:
338 return self._encipher_only
339
340 @property
341 def decipher_only(self):
342 if not self.key_agreement:
343 raise ValueError(
344 "decipher_only is undefined unless key_agreement is true"
345 )
346 else:
347 return self._decipher_only
348
349
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500350class SubjectKeyIdentifier(object):
351 def __init__(self, digest):
352 self._digest = digest
353
354 digest = utils.read_only_property("_digest")
355
356 @property
357 def hexdigest(self):
358 return binascii.hexlify(self.digest).decode("ascii")
359
360 def __repr__(self):
361 return "<SubjectKeyIdentifier(value={0})>".format(self.hexdigest)
362
363 def __eq__(self, other):
364 if not isinstance(other, SubjectKeyIdentifier):
365 return NotImplemented
366
367 return (
368 self.digest == other.digest
369 )
370
371 def __ne__(self, other):
372 return not self == other
373
374
Paul Kehrer806bfb22015-02-02 17:05:24 -0600375OID_COMMON_NAME = ObjectIdentifier("2.5.4.3")
376OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6")
377OID_LOCALITY_NAME = ObjectIdentifier("2.5.4.7")
378OID_STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8")
379OID_ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10")
380OID_ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11")
381OID_SERIAL_NUMBER = ObjectIdentifier("2.5.4.5")
382OID_SURNAME = ObjectIdentifier("2.5.4.4")
383OID_GIVEN_NAME = ObjectIdentifier("2.5.4.42")
384OID_TITLE = ObjectIdentifier("2.5.4.12")
385OID_GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44")
386OID_DN_QUALIFIER = ObjectIdentifier("2.5.4.46")
387OID_PSEUDONYM = ObjectIdentifier("2.5.4.65")
388OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25")
389OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600390
Paul Kehrer1a7ba872015-02-19 18:09:05 -0600391OID_RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4")
392OID_RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5")
393OID_RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14")
394OID_RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11")
395OID_RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12")
396OID_RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13")
Paul Kehrer56da2a52015-02-11 23:35:07 -0600397OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1")
398OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2")
399OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3")
400OID_ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4")
401OID_DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3")
402OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1")
403OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
404
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600405_SIG_OIDS_TO_HASH = {
Paul Kehrer1a7ba872015-02-19 18:09:05 -0600406 OID_RSA_WITH_MD5.dotted_string: hashes.MD5(),
407 OID_RSA_WITH_SHA1.dotted_string: hashes.SHA1(),
408 OID_RSA_WITH_SHA224.dotted_string: hashes.SHA224(),
409 OID_RSA_WITH_SHA256.dotted_string: hashes.SHA256(),
410 OID_RSA_WITH_SHA384.dotted_string: hashes.SHA384(),
411 OID_RSA_WITH_SHA512.dotted_string: hashes.SHA512(),
Paul Kehrer42a87cb2015-02-13 18:53:24 -0600412 OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(),
413 OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(),
414 OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(),
415 OID_ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(),
416 OID_DSA_WITH_SHA1.dotted_string: hashes.SHA1(),
417 OID_DSA_WITH_SHA224.dotted_string: hashes.SHA224(),
418 OID_DSA_WITH_SHA256.dotted_string: hashes.SHA256()
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600419}
420
Paul Kehrere1513fa2015-03-30 23:08:17 -0500421OID_SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1")
422OID_CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2")
423OID_CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3")
424OID_EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4")
425OID_TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8")
426OID_OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9")
427
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600428
Paul Kehrerb2de9482014-12-11 14:54:48 -0600429@six.add_metaclass(abc.ABCMeta)
Paul Kehrere76cd272014-12-14 19:00:51 -0600430class Certificate(object):
Paul Kehrerb2de9482014-12-11 14:54:48 -0600431 @abc.abstractmethod
432 def fingerprint(self, algorithm):
433 """
434 Returns bytes using digest passed.
435 """
436
437 @abc.abstractproperty
438 def serial(self):
439 """
440 Returns certificate serial number
441 """
442
443 @abc.abstractproperty
444 def version(self):
445 """
446 Returns the certificate version
447 """
448
449 @abc.abstractmethod
450 def public_key(self):
451 """
452 Returns the public key
453 """
454
455 @abc.abstractproperty
456 def not_valid_before(self):
457 """
458 Not before time (represented as UTC datetime)
459 """
460
461 @abc.abstractproperty
462 def not_valid_after(self):
463 """
464 Not after time (represented as UTC datetime)
465 """
Paul Kehrer719d5362015-01-01 20:03:52 -0600466
467 @abc.abstractproperty
468 def issuer(self):
469 """
470 Returns the issuer name object.
471 """
472
473 @abc.abstractproperty
474 def subject(self):
475 """
476 Returns the subject name object.
477 """
Paul Kehrer56da2a52015-02-11 23:35:07 -0600478
479 @abc.abstractproperty
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600480 def signature_hash_algorithm(self):
Paul Kehrer56da2a52015-02-11 23:35:07 -0600481 """
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600482 Returns a HashAlgorithm corresponding to the type of the digest signed
483 in the certificate.
Paul Kehrer56da2a52015-02-11 23:35:07 -0600484 """
Paul Kehrerdc480ad2015-02-23 12:14:54 -0600485
486
487@six.add_metaclass(abc.ABCMeta)
Paul Kehrera1a1f232015-03-15 15:34:35 -0500488class CertificateSigningRequest(object):
Paul Kehrerdc480ad2015-02-23 12:14:54 -0600489 @abc.abstractmethod
490 def public_key(self):
491 """
492 Returns the public key
493 """
494
495 @abc.abstractproperty
496 def subject(self):
497 """
498 Returns the subject name object.
499 """
500
501 @abc.abstractproperty
502 def signature_hash_algorithm(self):
503 """
504 Returns a HashAlgorithm corresponding to the type of the digest signed
505 in the certificate.
506 """