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