• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 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
7import abc
8import datetime
9import os
10from enum import Enum
11
12import six
13
14from cryptography import utils
15from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
16from cryptography.x509.extensions import Extension, ExtensionType
17from cryptography.x509.name import Name
18
19
20_EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1)
21
22
23def _reject_duplicate_extension(extension, extensions):
24    # This is quadratic in the number of extensions
25    for e in extensions:
26        if e.oid == extension.oid:
27            raise ValueError('This extension has already been set.')
28
29
30def _convert_to_naive_utc_time(time):
31    """Normalizes a datetime to a naive datetime in UTC.
32
33    time -- datetime to normalize. Assumed to be in UTC if not timezone
34            aware.
35    """
36    if time.tzinfo is not None:
37        offset = time.utcoffset()
38        offset = offset if offset else datetime.timedelta()
39        return time.replace(tzinfo=None) - offset
40    else:
41        return time
42
43
44class Version(Enum):
45    v1 = 0
46    v3 = 2
47
48
49def load_pem_x509_certificate(data, backend):
50    return backend.load_pem_x509_certificate(data)
51
52
53def load_der_x509_certificate(data, backend):
54    return backend.load_der_x509_certificate(data)
55
56
57def load_pem_x509_csr(data, backend):
58    return backend.load_pem_x509_csr(data)
59
60
61def load_der_x509_csr(data, backend):
62    return backend.load_der_x509_csr(data)
63
64
65def load_pem_x509_crl(data, backend):
66    return backend.load_pem_x509_crl(data)
67
68
69def load_der_x509_crl(data, backend):
70    return backend.load_der_x509_crl(data)
71
72
73class InvalidVersion(Exception):
74    def __init__(self, msg, parsed_version):
75        super(InvalidVersion, self).__init__(msg)
76        self.parsed_version = parsed_version
77
78
79@six.add_metaclass(abc.ABCMeta)
80class Certificate(object):
81    @abc.abstractmethod
82    def fingerprint(self, algorithm):
83        """
84        Returns bytes using digest passed.
85        """
86
87    @abc.abstractproperty
88    def serial_number(self):
89        """
90        Returns certificate serial number
91        """
92
93    @abc.abstractproperty
94    def version(self):
95        """
96        Returns the certificate version
97        """
98
99    @abc.abstractmethod
100    def public_key(self):
101        """
102        Returns the public key
103        """
104
105    @abc.abstractproperty
106    def not_valid_before(self):
107        """
108        Not before time (represented as UTC datetime)
109        """
110
111    @abc.abstractproperty
112    def not_valid_after(self):
113        """
114        Not after time (represented as UTC datetime)
115        """
116
117    @abc.abstractproperty
118    def issuer(self):
119        """
120        Returns the issuer name object.
121        """
122
123    @abc.abstractproperty
124    def subject(self):
125        """
126        Returns the subject name object.
127        """
128
129    @abc.abstractproperty
130    def signature_hash_algorithm(self):
131        """
132        Returns a HashAlgorithm corresponding to the type of the digest signed
133        in the certificate.
134        """
135
136    @abc.abstractproperty
137    def signature_algorithm_oid(self):
138        """
139        Returns the ObjectIdentifier of the signature algorithm.
140        """
141
142    @abc.abstractproperty
143    def extensions(self):
144        """
145        Returns an Extensions object.
146        """
147
148    @abc.abstractproperty
149    def signature(self):
150        """
151        Returns the signature bytes.
152        """
153
154    @abc.abstractproperty
155    def tbs_certificate_bytes(self):
156        """
157        Returns the tbsCertificate payload bytes as defined in RFC 5280.
158        """
159
160    @abc.abstractmethod
161    def __eq__(self, other):
162        """
163        Checks equality.
164        """
165
166    @abc.abstractmethod
167    def __ne__(self, other):
168        """
169        Checks not equal.
170        """
171
172    @abc.abstractmethod
173    def __hash__(self):
174        """
175        Computes a hash.
176        """
177
178    @abc.abstractmethod
179    def public_bytes(self, encoding):
180        """
181        Serializes the certificate to PEM or DER format.
182        """
183
184
185@six.add_metaclass(abc.ABCMeta)
186class CertificateRevocationList(object):
187    @abc.abstractmethod
188    def public_bytes(self, encoding):
189        """
190        Serializes the CRL to PEM or DER format.
191        """
192
193    @abc.abstractmethod
194    def fingerprint(self, algorithm):
195        """
196        Returns bytes using digest passed.
197        """
198
199    @abc.abstractmethod
200    def get_revoked_certificate_by_serial_number(self, serial_number):
201        """
202        Returns an instance of RevokedCertificate or None if the serial_number
203        is not in the CRL.
204        """
205
206    @abc.abstractproperty
207    def signature_hash_algorithm(self):
208        """
209        Returns a HashAlgorithm corresponding to the type of the digest signed
210        in the certificate.
211        """
212
213    @abc.abstractproperty
214    def signature_algorithm_oid(self):
215        """
216        Returns the ObjectIdentifier of the signature algorithm.
217        """
218
219    @abc.abstractproperty
220    def issuer(self):
221        """
222        Returns the X509Name with the issuer of this CRL.
223        """
224
225    @abc.abstractproperty
226    def next_update(self):
227        """
228        Returns the date of next update for this CRL.
229        """
230
231    @abc.abstractproperty
232    def last_update(self):
233        """
234        Returns the date of last update for this CRL.
235        """
236
237    @abc.abstractproperty
238    def extensions(self):
239        """
240        Returns an Extensions object containing a list of CRL extensions.
241        """
242
243    @abc.abstractproperty
244    def signature(self):
245        """
246        Returns the signature bytes.
247        """
248
249    @abc.abstractproperty
250    def tbs_certlist_bytes(self):
251        """
252        Returns the tbsCertList payload bytes as defined in RFC 5280.
253        """
254
255    @abc.abstractmethod
256    def __eq__(self, other):
257        """
258        Checks equality.
259        """
260
261    @abc.abstractmethod
262    def __ne__(self, other):
263        """
264        Checks not equal.
265        """
266
267    @abc.abstractmethod
268    def __len__(self):
269        """
270        Number of revoked certificates in the CRL.
271        """
272
273    @abc.abstractmethod
274    def __getitem__(self, idx):
275        """
276        Returns a revoked certificate (or slice of revoked certificates).
277        """
278
279    @abc.abstractmethod
280    def __iter__(self):
281        """
282        Iterator over the revoked certificates
283        """
284
285    @abc.abstractmethod
286    def is_signature_valid(self, public_key):
287        """
288        Verifies signature of revocation list against given public key.
289        """
290
291
292@six.add_metaclass(abc.ABCMeta)
293class CertificateSigningRequest(object):
294    @abc.abstractmethod
295    def __eq__(self, other):
296        """
297        Checks equality.
298        """
299
300    @abc.abstractmethod
301    def __ne__(self, other):
302        """
303        Checks not equal.
304        """
305
306    @abc.abstractmethod
307    def __hash__(self):
308        """
309        Computes a hash.
310        """
311
312    @abc.abstractmethod
313    def public_key(self):
314        """
315        Returns the public key
316        """
317
318    @abc.abstractproperty
319    def subject(self):
320        """
321        Returns the subject name object.
322        """
323
324    @abc.abstractproperty
325    def signature_hash_algorithm(self):
326        """
327        Returns a HashAlgorithm corresponding to the type of the digest signed
328        in the certificate.
329        """
330
331    @abc.abstractproperty
332    def signature_algorithm_oid(self):
333        """
334        Returns the ObjectIdentifier of the signature algorithm.
335        """
336
337    @abc.abstractproperty
338    def extensions(self):
339        """
340        Returns the extensions in the signing request.
341        """
342
343    @abc.abstractmethod
344    def public_bytes(self, encoding):
345        """
346        Encodes the request to PEM or DER format.
347        """
348
349    @abc.abstractproperty
350    def signature(self):
351        """
352        Returns the signature bytes.
353        """
354
355    @abc.abstractproperty
356    def tbs_certrequest_bytes(self):
357        """
358        Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC
359        2986.
360        """
361
362    @abc.abstractproperty
363    def is_signature_valid(self):
364        """
365        Verifies signature of signing request.
366        """
367
368
369@six.add_metaclass(abc.ABCMeta)
370class RevokedCertificate(object):
371    @abc.abstractproperty
372    def serial_number(self):
373        """
374        Returns the serial number of the revoked certificate.
375        """
376
377    @abc.abstractproperty
378    def revocation_date(self):
379        """
380        Returns the date of when this certificate was revoked.
381        """
382
383    @abc.abstractproperty
384    def extensions(self):
385        """
386        Returns an Extensions object containing a list of Revoked extensions.
387        """
388
389
390class CertificateSigningRequestBuilder(object):
391    def __init__(self, subject_name=None, extensions=[]):
392        """
393        Creates an empty X.509 certificate request (v1).
394        """
395        self._subject_name = subject_name
396        self._extensions = extensions
397
398    def subject_name(self, name):
399        """
400        Sets the certificate requestor's distinguished name.
401        """
402        if not isinstance(name, Name):
403            raise TypeError('Expecting x509.Name object.')
404        if self._subject_name is not None:
405            raise ValueError('The subject name may only be set once.')
406        return CertificateSigningRequestBuilder(name, self._extensions)
407
408    def add_extension(self, extension, critical):
409        """
410        Adds an X.509 extension to the certificate request.
411        """
412        if not isinstance(extension, ExtensionType):
413            raise TypeError("extension must be an ExtensionType")
414
415        extension = Extension(extension.oid, critical, extension)
416        _reject_duplicate_extension(extension, self._extensions)
417
418        return CertificateSigningRequestBuilder(
419            self._subject_name, self._extensions + [extension]
420        )
421
422    def sign(self, private_key, algorithm, backend):
423        """
424        Signs the request using the requestor's private key.
425        """
426        if self._subject_name is None:
427            raise ValueError("A CertificateSigningRequest must have a subject")
428        return backend.create_x509_csr(self, private_key, algorithm)
429
430
431class CertificateBuilder(object):
432    def __init__(self, issuer_name=None, subject_name=None,
433                 public_key=None, serial_number=None, not_valid_before=None,
434                 not_valid_after=None, extensions=[]):
435        self._version = Version.v3
436        self._issuer_name = issuer_name
437        self._subject_name = subject_name
438        self._public_key = public_key
439        self._serial_number = serial_number
440        self._not_valid_before = not_valid_before
441        self._not_valid_after = not_valid_after
442        self._extensions = extensions
443
444    def issuer_name(self, name):
445        """
446        Sets the CA's distinguished name.
447        """
448        if not isinstance(name, Name):
449            raise TypeError('Expecting x509.Name object.')
450        if self._issuer_name is not None:
451            raise ValueError('The issuer name may only be set once.')
452        return CertificateBuilder(
453            name, self._subject_name, self._public_key,
454            self._serial_number, self._not_valid_before,
455            self._not_valid_after, self._extensions
456        )
457
458    def subject_name(self, name):
459        """
460        Sets the requestor's distinguished name.
461        """
462        if not isinstance(name, Name):
463            raise TypeError('Expecting x509.Name object.')
464        if self._subject_name is not None:
465            raise ValueError('The subject name may only be set once.')
466        return CertificateBuilder(
467            self._issuer_name, name, self._public_key,
468            self._serial_number, self._not_valid_before,
469            self._not_valid_after, self._extensions
470        )
471
472    def public_key(self, key):
473        """
474        Sets the requestor's public key (as found in the signing request).
475        """
476        if not isinstance(key, (dsa.DSAPublicKey, rsa.RSAPublicKey,
477                                ec.EllipticCurvePublicKey)):
478            raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,'
479                            ' or EllipticCurvePublicKey.')
480        if self._public_key is not None:
481            raise ValueError('The public key may only be set once.')
482        return CertificateBuilder(
483            self._issuer_name, self._subject_name, key,
484            self._serial_number, self._not_valid_before,
485            self._not_valid_after, self._extensions
486        )
487
488    def serial_number(self, number):
489        """
490        Sets the certificate serial number.
491        """
492        if not isinstance(number, six.integer_types):
493            raise TypeError('Serial number must be of integral type.')
494        if self._serial_number is not None:
495            raise ValueError('The serial number may only be set once.')
496        if number <= 0:
497            raise ValueError('The serial number should be positive.')
498
499        # ASN.1 integers are always signed, so most significant bit must be
500        # zero.
501        if number.bit_length() >= 160:  # As defined in RFC 5280
502            raise ValueError('The serial number should not be more than 159 '
503                             'bits.')
504        return CertificateBuilder(
505            self._issuer_name, self._subject_name,
506            self._public_key, number, self._not_valid_before,
507            self._not_valid_after, self._extensions
508        )
509
510    def not_valid_before(self, time):
511        """
512        Sets the certificate activation time.
513        """
514        if not isinstance(time, datetime.datetime):
515            raise TypeError('Expecting datetime object.')
516        if self._not_valid_before is not None:
517            raise ValueError('The not valid before may only be set once.')
518        time = _convert_to_naive_utc_time(time)
519        if time < _EARLIEST_UTC_TIME:
520            raise ValueError('The not valid before date must be on or after'
521                             ' 1950 January 1).')
522        if self._not_valid_after is not None and time > self._not_valid_after:
523            raise ValueError(
524                'The not valid before date must be before the not valid after '
525                'date.'
526            )
527        return CertificateBuilder(
528            self._issuer_name, self._subject_name,
529            self._public_key, self._serial_number, time,
530            self._not_valid_after, self._extensions
531        )
532
533    def not_valid_after(self, time):
534        """
535        Sets the certificate expiration time.
536        """
537        if not isinstance(time, datetime.datetime):
538            raise TypeError('Expecting datetime object.')
539        if self._not_valid_after is not None:
540            raise ValueError('The not valid after may only be set once.')
541        time = _convert_to_naive_utc_time(time)
542        if time < _EARLIEST_UTC_TIME:
543            raise ValueError('The not valid after date must be on or after'
544                             ' 1950 January 1.')
545        if (self._not_valid_before is not None and
546                time < self._not_valid_before):
547            raise ValueError(
548                'The not valid after date must be after the not valid before '
549                'date.'
550            )
551        return CertificateBuilder(
552            self._issuer_name, self._subject_name,
553            self._public_key, self._serial_number, self._not_valid_before,
554            time, self._extensions
555        )
556
557    def add_extension(self, extension, critical):
558        """
559        Adds an X.509 extension to the certificate.
560        """
561        if not isinstance(extension, ExtensionType):
562            raise TypeError("extension must be an ExtensionType")
563
564        extension = Extension(extension.oid, critical, extension)
565        _reject_duplicate_extension(extension, self._extensions)
566
567        return CertificateBuilder(
568            self._issuer_name, self._subject_name,
569            self._public_key, self._serial_number, self._not_valid_before,
570            self._not_valid_after, self._extensions + [extension]
571        )
572
573    def sign(self, private_key, algorithm, backend):
574        """
575        Signs the certificate using the CA's private key.
576        """
577        if self._subject_name is None:
578            raise ValueError("A certificate must have a subject name")
579
580        if self._issuer_name is None:
581            raise ValueError("A certificate must have an issuer name")
582
583        if self._serial_number is None:
584            raise ValueError("A certificate must have a serial number")
585
586        if self._not_valid_before is None:
587            raise ValueError("A certificate must have a not valid before time")
588
589        if self._not_valid_after is None:
590            raise ValueError("A certificate must have a not valid after time")
591
592        if self._public_key is None:
593            raise ValueError("A certificate must have a public key")
594
595        return backend.create_x509_certificate(self, private_key, algorithm)
596
597
598class CertificateRevocationListBuilder(object):
599    def __init__(self, issuer_name=None, last_update=None, next_update=None,
600                 extensions=[], revoked_certificates=[]):
601        self._issuer_name = issuer_name
602        self._last_update = last_update
603        self._next_update = next_update
604        self._extensions = extensions
605        self._revoked_certificates = revoked_certificates
606
607    def issuer_name(self, issuer_name):
608        if not isinstance(issuer_name, Name):
609            raise TypeError('Expecting x509.Name object.')
610        if self._issuer_name is not None:
611            raise ValueError('The issuer name may only be set once.')
612        return CertificateRevocationListBuilder(
613            issuer_name, self._last_update, self._next_update,
614            self._extensions, self._revoked_certificates
615        )
616
617    def last_update(self, last_update):
618        if not isinstance(last_update, datetime.datetime):
619            raise TypeError('Expecting datetime object.')
620        if self._last_update is not None:
621            raise ValueError('Last update may only be set once.')
622        last_update = _convert_to_naive_utc_time(last_update)
623        if last_update < _EARLIEST_UTC_TIME:
624            raise ValueError('The last update date must be on or after'
625                             ' 1950 January 1.')
626        if self._next_update is not None and last_update > self._next_update:
627            raise ValueError(
628                'The last update date must be before the next update date.'
629            )
630        return CertificateRevocationListBuilder(
631            self._issuer_name, last_update, self._next_update,
632            self._extensions, self._revoked_certificates
633        )
634
635    def next_update(self, next_update):
636        if not isinstance(next_update, datetime.datetime):
637            raise TypeError('Expecting datetime object.')
638        if self._next_update is not None:
639            raise ValueError('Last update may only be set once.')
640        next_update = _convert_to_naive_utc_time(next_update)
641        if next_update < _EARLIEST_UTC_TIME:
642            raise ValueError('The last update date must be on or after'
643                             ' 1950 January 1.')
644        if self._last_update is not None and next_update < self._last_update:
645            raise ValueError(
646                'The next update date must be after the last update date.'
647            )
648        return CertificateRevocationListBuilder(
649            self._issuer_name, self._last_update, next_update,
650            self._extensions, self._revoked_certificates
651        )
652
653    def add_extension(self, extension, critical):
654        """
655        Adds an X.509 extension to the certificate revocation list.
656        """
657        if not isinstance(extension, ExtensionType):
658            raise TypeError("extension must be an ExtensionType")
659
660        extension = Extension(extension.oid, critical, extension)
661        _reject_duplicate_extension(extension, self._extensions)
662        return CertificateRevocationListBuilder(
663            self._issuer_name, self._last_update, self._next_update,
664            self._extensions + [extension], self._revoked_certificates
665        )
666
667    def add_revoked_certificate(self, revoked_certificate):
668        """
669        Adds a revoked certificate to the CRL.
670        """
671        if not isinstance(revoked_certificate, RevokedCertificate):
672            raise TypeError("Must be an instance of RevokedCertificate")
673
674        return CertificateRevocationListBuilder(
675            self._issuer_name, self._last_update,
676            self._next_update, self._extensions,
677            self._revoked_certificates + [revoked_certificate]
678        )
679
680    def sign(self, private_key, algorithm, backend):
681        if self._issuer_name is None:
682            raise ValueError("A CRL must have an issuer name")
683
684        if self._last_update is None:
685            raise ValueError("A CRL must have a last update time")
686
687        if self._next_update is None:
688            raise ValueError("A CRL must have a next update time")
689
690        return backend.create_x509_crl(self, private_key, algorithm)
691
692
693class RevokedCertificateBuilder(object):
694    def __init__(self, serial_number=None, revocation_date=None,
695                 extensions=[]):
696        self._serial_number = serial_number
697        self._revocation_date = revocation_date
698        self._extensions = extensions
699
700    def serial_number(self, number):
701        if not isinstance(number, six.integer_types):
702            raise TypeError('Serial number must be of integral type.')
703        if self._serial_number is not None:
704            raise ValueError('The serial number may only be set once.')
705        if number <= 0:
706            raise ValueError('The serial number should be positive')
707
708        # ASN.1 integers are always signed, so most significant bit must be
709        # zero.
710        if number.bit_length() >= 160:  # As defined in RFC 5280
711            raise ValueError('The serial number should not be more than 159 '
712                             'bits.')
713        return RevokedCertificateBuilder(
714            number, self._revocation_date, self._extensions
715        )
716
717    def revocation_date(self, time):
718        if not isinstance(time, datetime.datetime):
719            raise TypeError('Expecting datetime object.')
720        if self._revocation_date is not None:
721            raise ValueError('The revocation date may only be set once.')
722        time = _convert_to_naive_utc_time(time)
723        if time < _EARLIEST_UTC_TIME:
724            raise ValueError('The revocation date must be on or after'
725                             ' 1950 January 1.')
726        return RevokedCertificateBuilder(
727            self._serial_number, time, self._extensions
728        )
729
730    def add_extension(self, extension, critical):
731        if not isinstance(extension, ExtensionType):
732            raise TypeError("extension must be an ExtensionType")
733
734        extension = Extension(extension.oid, critical, extension)
735        _reject_duplicate_extension(extension, self._extensions)
736        return RevokedCertificateBuilder(
737            self._serial_number, self._revocation_date,
738            self._extensions + [extension]
739        )
740
741    def build(self, backend):
742        if self._serial_number is None:
743            raise ValueError("A revoked certificate must have a serial number")
744        if self._revocation_date is None:
745            raise ValueError(
746                "A revoked certificate must have a revocation date"
747            )
748
749        return backend.create_x509_revoked_certificate(self)
750
751
752def random_serial_number():
753    return utils.int_from_bytes(os.urandom(20), "big") >> 1
754