blob: ad7ebbe0d1302de3847992d06957e387bb4522af [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 Kehrer016e08a2014-11-26 09:41:18 -10008from enum import Enum
9
Paul Kehrerb2de9482014-12-11 14:54:48 -060010import six
11
Paul Kehrer912d3fb2015-01-29 11:19:22 -060012from cryptography import utils
Paul Kehrer8802a5b2015-02-13 12:06:57 -060013from cryptography.hazmat.primitives import hashes
Paul Kehrer912d3fb2015-01-29 11:19:22 -060014
Paul Kehrer016e08a2014-11-26 09:41:18 -100015
Paul Kehrer806bfb22015-02-02 17:05:24 -060016_OID_NAMES = {
17 "2.5.4.3": "commonName",
18 "2.5.4.6": "countryName",
19 "2.5.4.7": "localityName",
20 "2.5.4.8": "stateOrProvinceName",
21 "2.5.4.10": "organizationName",
22 "2.5.4.11": "organizationalUnitName",
23 "2.5.4.5": "serialNumber",
24 "2.5.4.4": "surname",
25 "2.5.4.42": "givenName",
26 "2.5.4.12": "title",
27 "2.5.4.44": "generationQualifier",
28 "2.5.4.46": "dnQualifier",
29 "2.5.4.65": "pseudonym",
30 "0.9.2342.19200300.100.1.25": "domainComponent",
31 "1.2.840.113549.1.9.1": "emailAddress",
Paul Kehrer71d40c62015-02-19 08:21:04 -060032 "1.2.840.113549.1.1.4": "md5WithRSAEncryption",
33 "1.2.840.113549.1.1.5": "sha1WithRSAEncryption",
Paul Kehrer56da2a52015-02-11 23:35:07 -060034 "1.2.840.113549.1.1.14": "sha224WithRSAEncryption",
35 "1.2.840.113549.1.1.11": "sha256WithRSAEncryption",
36 "1.2.840.113549.1.1.12": "sha384WithRSAEncryption",
37 "1.2.840.113549.1.1.13": "sha512WithRSAEncryption",
Paul Kehrer71d40c62015-02-19 08:21:04 -060038 "1.2.840.10045.4.3.1": "ecdsa-with-SHA224",
39 "1.2.840.10045.4.3.2": "ecdsa-with-SHA256",
40 "1.2.840.10045.4.3.3": "ecdsa-with-SHA384",
41 "1.2.840.10045.4.3.4": "ecdsa-with-SHA512",
42 "1.2.840.10040.4.3": "dsa-with-sha1",
43 "2.16.840.1.101.3.4.3.1": "dsa-with-sha224",
44 "2.16.840.1.101.3.4.3.2": "dsa-with-sha256",
Paul Kehrer806bfb22015-02-02 17:05:24 -060045}
46
47
Paul Kehrere76cd272014-12-14 19:00:51 -060048class Version(Enum):
Paul Kehrer016e08a2014-11-26 09:41:18 -100049 v1 = 0
50 v3 = 2
51
52
Paul Kehrer016e08a2014-11-26 09:41:18 -100053def load_pem_x509_certificate(data, backend):
54 return backend.load_pem_x509_certificate(data)
55
56
Paul Kehrer016e08a2014-11-26 09:41:18 -100057def load_der_x509_certificate(data, backend):
58 return backend.load_der_x509_certificate(data)
Paul Kehrera68fd332014-11-27 07:08:40 -100059
60
Paul Kehrere76cd272014-12-14 19:00:51 -060061class InvalidVersion(Exception):
Paul Kehrerd5cccf72014-12-15 17:20:33 -060062 def __init__(self, msg, parsed_version):
63 super(InvalidVersion, self).__init__(msg)
64 self.parsed_version = parsed_version
Paul Kehrerb2de9482014-12-11 14:54:48 -060065
66
Paul Kehrer806bfb22015-02-02 17:05:24 -060067class NameAttribute(object):
Paul Kehrer912d3fb2015-01-29 11:19:22 -060068 def __init__(self, oid, value):
69 if not isinstance(oid, ObjectIdentifier):
Paul Kehrer858b9b72015-02-05 09:50:31 -060070 raise TypeError(
71 "oid argument must be an ObjectIdentifier instance."
72 )
Paul Kehrer912d3fb2015-01-29 11:19:22 -060073
74 self._oid = oid
75 self._value = value
76
77 oid = utils.read_only_property("_oid")
78 value = utils.read_only_property("_value")
79
80 def __eq__(self, other):
Paul Kehrer806bfb22015-02-02 17:05:24 -060081 if not isinstance(other, NameAttribute):
Paul Kehrer912d3fb2015-01-29 11:19:22 -060082 return NotImplemented
83
84 return (
85 self.oid == other.oid and
86 self.value == other.value
87 )
88
89 def __ne__(self, other):
90 return not self == other
91
Paul Kehrera498be82015-02-12 15:00:56 -060092 def __repr__(self):
93 return "<NameAttribute(oid={oid}, value={value!r})>".format(
94 oid=self.oid,
95 value=self.value
96 )
97
Paul Kehrer912d3fb2015-01-29 11:19:22 -060098
99class ObjectIdentifier(object):
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600100 def __init__(self, dotted_string):
101 self._dotted_string = dotted_string
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600102
103 def __eq__(self, other):
104 if not isinstance(other, ObjectIdentifier):
105 return NotImplemented
106
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600107 return self._dotted_string == other._dotted_string
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600108
109 def __ne__(self, other):
110 return not self == other
111
112 def __repr__(self):
113 return "<ObjectIdentifier(oid={0}, name={1})>".format(
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600114 self._dotted_string,
115 _OID_NAMES.get(self._dotted_string, "Unknown OID")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600116 )
117
Paul Kehrerd44f9a62015-02-04 14:47:34 -0600118 dotted_string = utils.read_only_property("_dotted_string")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600119
120
Paul Kehrer719d5362015-01-01 20:03:52 -0600121class Name(object):
122 def __init__(self, attributes):
123 self._attributes = attributes
124
Paul Kehrere901d642015-02-11 18:50:58 -0600125 def get_attributes_for_oid(self, oid):
Alex Gaynorf9574232015-02-19 13:56:50 -0800126 return [i for i in self if i.oid == oid]
Paul Kehrer719d5362015-01-01 20:03:52 -0600127
Paul Kehrer719d5362015-01-01 20:03:52 -0600128 def __eq__(self, other):
129 if not isinstance(other, Name):
130 return NotImplemented
131
Paul Kehrer53d8d492015-02-13 18:47:30 -0600132 return self._attributes == other._attributes
Paul Kehrer719d5362015-01-01 20:03:52 -0600133
134 def __ne__(self, other):
135 return not self == other
136
Paul Kehrer53d8d492015-02-13 18:47:30 -0600137 def __iter__(self):
Paul Kehrer8b21a4a2015-02-14 07:56:36 -0600138 return iter(self._attributes)
Paul Kehrer53d8d492015-02-13 18:47:30 -0600139
140 def __len__(self):
141 return len(self._attributes)
142
Paul Kehrer719d5362015-01-01 20:03:52 -0600143
Paul Kehrer806bfb22015-02-02 17:05:24 -0600144OID_COMMON_NAME = ObjectIdentifier("2.5.4.3")
145OID_COUNTRY_NAME = ObjectIdentifier("2.5.4.6")
146OID_LOCALITY_NAME = ObjectIdentifier("2.5.4.7")
147OID_STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8")
148OID_ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10")
149OID_ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11")
150OID_SERIAL_NUMBER = ObjectIdentifier("2.5.4.5")
151OID_SURNAME = ObjectIdentifier("2.5.4.4")
152OID_GIVEN_NAME = ObjectIdentifier("2.5.4.42")
153OID_TITLE = ObjectIdentifier("2.5.4.12")
154OID_GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44")
155OID_DN_QUALIFIER = ObjectIdentifier("2.5.4.46")
156OID_PSEUDONYM = ObjectIdentifier("2.5.4.65")
157OID_DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25")
158OID_EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1")
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600159
Paul Kehrer1a7ba872015-02-19 18:09:05 -0600160OID_RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4")
161OID_RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5")
162OID_RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14")
163OID_RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11")
164OID_RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12")
165OID_RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13")
Paul Kehrer56da2a52015-02-11 23:35:07 -0600166OID_ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1")
167OID_ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2")
168OID_ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3")
169OID_ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4")
170OID_DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3")
171OID_DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1")
172OID_DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
173
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600174_SIG_OIDS_TO_HASH = {
Paul Kehrer1a7ba872015-02-19 18:09:05 -0600175 OID_RSA_WITH_MD5.dotted_string: hashes.MD5(),
176 OID_RSA_WITH_SHA1.dotted_string: hashes.SHA1(),
177 OID_RSA_WITH_SHA224.dotted_string: hashes.SHA224(),
178 OID_RSA_WITH_SHA256.dotted_string: hashes.SHA256(),
179 OID_RSA_WITH_SHA384.dotted_string: hashes.SHA384(),
180 OID_RSA_WITH_SHA512.dotted_string: hashes.SHA512(),
Paul Kehrer42a87cb2015-02-13 18:53:24 -0600181 OID_ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(),
182 OID_ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(),
183 OID_ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(),
184 OID_ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(),
185 OID_DSA_WITH_SHA1.dotted_string: hashes.SHA1(),
186 OID_DSA_WITH_SHA224.dotted_string: hashes.SHA224(),
187 OID_DSA_WITH_SHA256.dotted_string: hashes.SHA256()
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600188}
189
Paul Kehrer912d3fb2015-01-29 11:19:22 -0600190
Paul Kehrerb2de9482014-12-11 14:54:48 -0600191@six.add_metaclass(abc.ABCMeta)
Paul Kehrere76cd272014-12-14 19:00:51 -0600192class Certificate(object):
Paul Kehrerb2de9482014-12-11 14:54:48 -0600193 @abc.abstractmethod
194 def fingerprint(self, algorithm):
195 """
196 Returns bytes using digest passed.
197 """
198
199 @abc.abstractproperty
200 def serial(self):
201 """
202 Returns certificate serial number
203 """
204
205 @abc.abstractproperty
206 def version(self):
207 """
208 Returns the certificate version
209 """
210
211 @abc.abstractmethod
212 def public_key(self):
213 """
214 Returns the public key
215 """
216
217 @abc.abstractproperty
218 def not_valid_before(self):
219 """
220 Not before time (represented as UTC datetime)
221 """
222
223 @abc.abstractproperty
224 def not_valid_after(self):
225 """
226 Not after time (represented as UTC datetime)
227 """
Paul Kehrer719d5362015-01-01 20:03:52 -0600228
229 @abc.abstractproperty
230 def issuer(self):
231 """
232 Returns the issuer name object.
233 """
234
235 @abc.abstractproperty
236 def subject(self):
237 """
238 Returns the subject name object.
239 """
Paul Kehrer56da2a52015-02-11 23:35:07 -0600240
241 @abc.abstractproperty
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600242 def signature_hash_algorithm(self):
Paul Kehrer56da2a52015-02-11 23:35:07 -0600243 """
Paul Kehrer8802a5b2015-02-13 12:06:57 -0600244 Returns a HashAlgorithm corresponding to the type of the digest signed
245 in the certificate.
Paul Kehrer56da2a52015-02-11 23:35:07 -0600246 """