• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2# This file is dual licensed under the terms of the Apache License, Version
3# 2.0, and the BSD License. See the LICENSE file in the root of this repository
4# for complete details.
5
6from __future__ import absolute_import, division, print_function
7
8import binascii
9import collections
10import copy
11import datetime
12import ipaddress
13import os
14
15import pytest
16
17import pytz
18
19import six
20
21from cryptography import utils, x509
22from cryptography.exceptions import UnsupportedAlgorithm
23from cryptography.hazmat._der import (
24    BIT_STRING,
25    CONSTRUCTED,
26    CONTEXT_SPECIFIC,
27    DERReader,
28    GENERALIZED_TIME,
29    INTEGER,
30    OBJECT_IDENTIFIER,
31    PRINTABLE_STRING,
32    SEQUENCE,
33    SET,
34    UTC_TIME,
35)
36from cryptography.hazmat.backends.interfaces import (
37    DSABackend,
38    EllipticCurveBackend,
39    RSABackend,
40    X509Backend,
41)
42from cryptography.hazmat.primitives import hashes, serialization
43from cryptography.hazmat.primitives.asymmetric import (
44    dh,
45    dsa,
46    ec,
47    ed25519,
48    ed448,
49    padding,
50    rsa,
51)
52from cryptography.hazmat.primitives.asymmetric.utils import (
53    decode_dss_signature,
54)
55from cryptography.utils import int_from_bytes
56from cryptography.x509.name import _ASN1Type
57from cryptography.x509.oid import (
58    AuthorityInformationAccessOID,
59    ExtendedKeyUsageOID,
60    ExtensionOID,
61    NameOID,
62    SignatureAlgorithmOID,
63    SubjectInformationAccessOID,
64)
65
66from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048
67from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1
68from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512
69from ..hazmat.primitives.test_ec import _skip_curve_unsupported
70from ..utils import load_nist_vectors, load_vectors_from_file
71
72
73@utils.register_interface(x509.ExtensionType)
74class DummyExtension(object):
75    oid = x509.ObjectIdentifier("1.2.3.4")
76
77
78@utils.register_interface(x509.GeneralName)
79class FakeGeneralName(object):
80    def __init__(self, value):
81        self._value = value
82
83    value = utils.read_only_property("_value")
84
85
86def _load_cert(filename, loader, backend):
87    cert = load_vectors_from_file(
88        filename=filename,
89        loader=lambda pemfile: loader(pemfile.read(), backend),
90        mode="rb",
91    )
92    return cert
93
94
95ParsedCertificate = collections.namedtuple(
96    "ParsedCertificate",
97    ["not_before_tag", "not_after_tag", "issuer", "subject"],
98)
99
100
101def _parse_cert(der):
102    # See the Certificate structured, defined in RFC 5280.
103    with DERReader(der).read_single_element(SEQUENCE) as cert:
104        tbs_cert = cert.read_element(SEQUENCE)
105        # Skip outer signature algorithm
106        _ = cert.read_element(SEQUENCE)
107        # Skip signature
108        _ = cert.read_element(BIT_STRING)
109
110    with tbs_cert:
111        # Skip version
112        _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 0)
113        # Skip serialNumber
114        _ = tbs_cert.read_element(INTEGER)
115        # Skip inner signature algorithm
116        _ = tbs_cert.read_element(SEQUENCE)
117        issuer = tbs_cert.read_element(SEQUENCE)
118        validity = tbs_cert.read_element(SEQUENCE)
119        subject = tbs_cert.read_element(SEQUENCE)
120        # Skip subjectPublicKeyInfo
121        _ = tbs_cert.read_element(SEQUENCE)
122        # Skip issuerUniqueID
123        _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 1)
124        # Skip subjectUniqueID
125        _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 2)
126        # Skip extensions
127        _ = tbs_cert.read_optional_element(CONTEXT_SPECIFIC | CONSTRUCTED | 3)
128
129    with validity:
130        not_before_tag, _ = validity.read_any_element()
131        not_after_tag, _ = validity.read_any_element()
132
133    return ParsedCertificate(
134        not_before_tag=not_before_tag,
135        not_after_tag=not_after_tag,
136        issuer=issuer,
137        subject=subject,
138    )
139
140
141@pytest.mark.requires_backend_interface(interface=X509Backend)
142class TestCertificateRevocationList(object):
143    def test_load_pem_crl(self, backend):
144        crl = _load_cert(
145            os.path.join("x509", "custom", "crl_all_reasons.pem"),
146            x509.load_pem_x509_crl,
147            backend,
148        )
149
150        assert isinstance(crl, x509.CertificateRevocationList)
151        fingerprint = binascii.hexlify(crl.fingerprint(hashes.SHA1()))
152        assert fingerprint == b"3234b0cb4c0cedf6423724b736729dcfc9e441ef"
153        assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
154        assert (
155            crl.signature_algorithm_oid
156            == SignatureAlgorithmOID.RSA_WITH_SHA256
157        )
158
159    def test_load_der_crl(self, backend):
160        crl = _load_cert(
161            os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
162            x509.load_der_x509_crl,
163            backend,
164        )
165
166        assert isinstance(crl, x509.CertificateRevocationList)
167        fingerprint = binascii.hexlify(crl.fingerprint(hashes.SHA1()))
168        assert fingerprint == b"dd3db63c50f4c4a13e090f14053227cb1011a5ad"
169        assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
170
171    def test_invalid_pem(self, backend):
172        with pytest.raises(ValueError):
173            x509.load_pem_x509_crl(b"notacrl", backend)
174
175    def test_invalid_der(self, backend):
176        with pytest.raises(ValueError):
177            x509.load_der_x509_crl(b"notacrl", backend)
178
179    def test_unknown_signature_algorithm(self, backend):
180        crl = _load_cert(
181            os.path.join(
182                "x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
183            ),
184            x509.load_pem_x509_crl,
185            backend,
186        )
187
188        with pytest.raises(UnsupportedAlgorithm):
189            crl.signature_hash_algorithm()
190
191    def test_issuer(self, backend):
192        crl = _load_cert(
193            os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
194            x509.load_der_x509_crl,
195            backend,
196        )
197
198        assert isinstance(crl.issuer, x509.Name)
199        assert list(crl.issuer) == [
200            x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
201            x509.NameAttribute(
202                x509.OID_ORGANIZATION_NAME, u"Test Certificates 2011"
203            ),
204            x509.NameAttribute(x509.OID_COMMON_NAME, u"Good CA"),
205        ]
206        assert crl.issuer.get_attributes_for_oid(x509.OID_COMMON_NAME) == [
207            x509.NameAttribute(x509.OID_COMMON_NAME, u"Good CA")
208        ]
209
210    def test_equality(self, backend):
211        crl1 = _load_cert(
212            os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
213            x509.load_der_x509_crl,
214            backend,
215        )
216
217        crl2 = _load_cert(
218            os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
219            x509.load_der_x509_crl,
220            backend,
221        )
222
223        crl3 = _load_cert(
224            os.path.join("x509", "custom", "crl_all_reasons.pem"),
225            x509.load_pem_x509_crl,
226            backend,
227        )
228
229        assert crl1 == crl2
230        assert crl1 != crl3
231        assert crl1 != object()
232
233    def test_update_dates(self, backend):
234        crl = _load_cert(
235            os.path.join("x509", "custom", "crl_all_reasons.pem"),
236            x509.load_pem_x509_crl,
237            backend,
238        )
239
240        assert isinstance(crl.next_update, datetime.datetime)
241        assert isinstance(crl.last_update, datetime.datetime)
242
243        assert crl.next_update.isoformat() == "2016-01-01T00:00:00"
244        assert crl.last_update.isoformat() == "2015-01-01T00:00:00"
245
246    def test_revoked_cert_retrieval(self, backend):
247        crl = _load_cert(
248            os.path.join("x509", "custom", "crl_all_reasons.pem"),
249            x509.load_pem_x509_crl,
250            backend,
251        )
252
253        for r in crl:
254            assert isinstance(r, x509.RevokedCertificate)
255
256        # Check that len() works for CRLs.
257        assert len(crl) == 12
258
259    def test_get_revoked_certificate_by_serial_number(self, backend):
260        crl = _load_cert(
261            os.path.join(
262                "x509", "PKITS_data", "crls", "LongSerialNumberCACRL.crl"
263            ),
264            x509.load_der_x509_crl,
265            backend,
266        )
267        serial_number = 725064303890588110203033396814564464046290047507
268        revoked = crl.get_revoked_certificate_by_serial_number(serial_number)
269        assert revoked.serial_number == serial_number
270        assert crl.get_revoked_certificate_by_serial_number(500) is None
271
272    def test_revoked_cert_retrieval_retain_only_revoked(self, backend):
273        """
274        This test attempts to trigger the crash condition described in
275        https://github.com/pyca/cryptography/issues/2557
276        PyPy does gc at its own pace, so it will only be reliable on CPython.
277        """
278        revoked = _load_cert(
279            os.path.join("x509", "custom", "crl_all_reasons.pem"),
280            x509.load_pem_x509_crl,
281            backend,
282        )[11]
283        assert revoked.revocation_date == datetime.datetime(2015, 1, 1, 0, 0)
284        assert revoked.serial_number == 11
285
286    def test_extensions(self, backend):
287        crl = _load_cert(
288            os.path.join("x509", "custom", "crl_ian_aia_aki.pem"),
289            x509.load_pem_x509_crl,
290            backend,
291        )
292
293        crl_number = crl.extensions.get_extension_for_oid(
294            ExtensionOID.CRL_NUMBER
295        )
296        aki = crl.extensions.get_extension_for_class(
297            x509.AuthorityKeyIdentifier
298        )
299        aia = crl.extensions.get_extension_for_class(
300            x509.AuthorityInformationAccess
301        )
302        ian = crl.extensions.get_extension_for_class(
303            x509.IssuerAlternativeName
304        )
305        assert crl_number.value == x509.CRLNumber(1)
306        assert crl_number.critical is False
307        assert aki.value == x509.AuthorityKeyIdentifier(
308            key_identifier=(b"yu\xbb\x84:\xcb,\xdez\t\xbe1\x1bC\xbc\x1c*MSX"),
309            authority_cert_issuer=None,
310            authority_cert_serial_number=None,
311        )
312        assert aia.value == x509.AuthorityInformationAccess(
313            [
314                x509.AccessDescription(
315                    AuthorityInformationAccessOID.CA_ISSUERS,
316                    x509.DNSName(u"cryptography.io"),
317                )
318            ]
319        )
320        assert ian.value == x509.IssuerAlternativeName(
321            [x509.UniformResourceIdentifier(u"https://cryptography.io")]
322        )
323
324    def test_delta_crl_indicator(self, backend):
325        crl = _load_cert(
326            os.path.join("x509", "custom", "crl_delta_crl_indicator.pem"),
327            x509.load_pem_x509_crl,
328            backend,
329        )
330
331        dci = crl.extensions.get_extension_for_oid(
332            ExtensionOID.DELTA_CRL_INDICATOR
333        )
334        assert dci.value == x509.DeltaCRLIndicator(12345678901234567890)
335        assert dci.critical is True
336
337    def test_signature(self, backend):
338        crl = _load_cert(
339            os.path.join("x509", "custom", "crl_all_reasons.pem"),
340            x509.load_pem_x509_crl,
341            backend,
342        )
343
344        assert crl.signature == binascii.unhexlify(
345            b"536a5a0794f68267361e7bc2f19167a3e667a2ab141535616855d8deb2ba1af"
346            b"9fd4546b1fe76b454eb436af7b28229fedff4634dfc9dd92254266219ae0ea8"
347            b"75d9ff972e9a2da23d5945f073da18c50a4265bfed9ca16586347800ef49dd1"
348            b"6856d7265f4f3c498a57f04dc04404e2bd2e2ada1f5697057aacef779a18371"
349            b"c621edc9a5c2b8ec1716e8fa22feeb7fcec0ce9156c8d344aa6ae8d1a5d99d0"
350            b"9386df36307df3b63c83908f4a61a0ff604c1e292ad63b349d1082ddd7ae1b7"
351            b"c178bba995523ec6999310c54da5706549797bfb1230f5593ba7b4353dade4f"
352            b"d2be13a57580a6eb20b5c4083f000abac3bf32cd8b75f23e4c8f4b3a79e1e2d"
353            b"58a472b0"
354        )
355
356    def test_tbs_certlist_bytes(self, backend):
357        crl = _load_cert(
358            os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
359            x509.load_der_x509_crl,
360            backend,
361        )
362
363        ca_cert = _load_cert(
364            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
365            x509.load_der_x509_certificate,
366            backend,
367        )
368
369        ca_cert.public_key().verify(
370            crl.signature,
371            crl.tbs_certlist_bytes,
372            padding.PKCS1v15(),
373            crl.signature_hash_algorithm,
374        )
375
376    def test_public_bytes_pem(self, backend):
377        crl = _load_cert(
378            os.path.join("x509", "custom", "crl_empty.pem"),
379            x509.load_pem_x509_crl,
380            backend,
381        )
382
383        # Encode it to PEM and load it back.
384        crl = x509.load_pem_x509_crl(
385            crl.public_bytes(
386                encoding=serialization.Encoding.PEM,
387            ),
388            backend,
389        )
390
391        assert len(crl) == 0
392        assert crl.last_update == datetime.datetime(2015, 12, 20, 23, 44, 47)
393        assert crl.next_update == datetime.datetime(2015, 12, 28, 0, 44, 47)
394
395    def test_public_bytes_der(self, backend):
396        crl = _load_cert(
397            os.path.join("x509", "custom", "crl_all_reasons.pem"),
398            x509.load_pem_x509_crl,
399            backend,
400        )
401
402        # Encode it to DER and load it back.
403        crl = x509.load_der_x509_crl(
404            crl.public_bytes(
405                encoding=serialization.Encoding.DER,
406            ),
407            backend,
408        )
409
410        assert len(crl) == 12
411        assert crl.last_update == datetime.datetime(2015, 1, 1, 0, 0, 0)
412        assert crl.next_update == datetime.datetime(2016, 1, 1, 0, 0, 0)
413
414    @pytest.mark.parametrize(
415        ("cert_path", "loader_func", "encoding"),
416        [
417            (
418                os.path.join("x509", "custom", "crl_all_reasons.pem"),
419                x509.load_pem_x509_crl,
420                serialization.Encoding.PEM,
421            ),
422            (
423                os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
424                x509.load_der_x509_crl,
425                serialization.Encoding.DER,
426            ),
427        ],
428    )
429    def test_public_bytes_match(
430        self, cert_path, loader_func, encoding, backend
431    ):
432        crl_bytes = load_vectors_from_file(
433            cert_path, lambda pemfile: pemfile.read(), mode="rb"
434        )
435        crl = loader_func(crl_bytes, backend)
436        serialized = crl.public_bytes(encoding)
437        assert serialized == crl_bytes
438
439    def test_public_bytes_invalid_encoding(self, backend):
440        crl = _load_cert(
441            os.path.join("x509", "custom", "crl_empty.pem"),
442            x509.load_pem_x509_crl,
443            backend,
444        )
445
446        with pytest.raises(TypeError):
447            crl.public_bytes("NotAnEncoding")
448
449    def test_verify_bad(self, backend):
450        crl = _load_cert(
451            os.path.join("x509", "custom", "invalid_signature.pem"),
452            x509.load_pem_x509_crl,
453            backend,
454        )
455        crt = _load_cert(
456            os.path.join("x509", "custom", "invalid_signature.pem"),
457            x509.load_pem_x509_certificate,
458            backend,
459        )
460
461        assert not crl.is_signature_valid(crt.public_key())
462
463    def test_verify_good(self, backend):
464        crl = _load_cert(
465            os.path.join("x509", "custom", "valid_signature.pem"),
466            x509.load_pem_x509_crl,
467            backend,
468        )
469        crt = _load_cert(
470            os.path.join("x509", "custom", "valid_signature.pem"),
471            x509.load_pem_x509_certificate,
472            backend,
473        )
474
475        assert crl.is_signature_valid(crt.public_key())
476
477    def test_verify_argument_must_be_a_public_key(self, backend):
478        crl = _load_cert(
479            os.path.join("x509", "custom", "valid_signature.pem"),
480            x509.load_pem_x509_crl,
481            backend,
482        )
483
484        with pytest.raises(TypeError):
485            crl.is_signature_valid("not a public key")
486
487        with pytest.raises(TypeError):
488            crl.is_signature_valid(object)
489
490
491@pytest.mark.requires_backend_interface(interface=X509Backend)
492class TestRevokedCertificate(object):
493    def test_revoked_basics(self, backend):
494        crl = _load_cert(
495            os.path.join("x509", "custom", "crl_all_reasons.pem"),
496            x509.load_pem_x509_crl,
497            backend,
498        )
499
500        for i, rev in enumerate(crl):
501            assert isinstance(rev, x509.RevokedCertificate)
502            assert isinstance(rev.serial_number, int)
503            assert isinstance(rev.revocation_date, datetime.datetime)
504            assert isinstance(rev.extensions, x509.Extensions)
505
506            assert rev.serial_number == i
507            assert rev.revocation_date.isoformat() == "2015-01-01T00:00:00"
508
509    def test_revoked_extensions(self, backend):
510        crl = _load_cert(
511            os.path.join("x509", "custom", "crl_all_reasons.pem"),
512            x509.load_pem_x509_crl,
513            backend,
514        )
515
516        exp_issuer = [
517            x509.DirectoryName(
518                x509.Name(
519                    [
520                        x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
521                        x509.NameAttribute(
522                            x509.OID_COMMON_NAME, u"cryptography.io"
523                        ),
524                    ]
525                )
526            )
527        ]
528
529        # First revoked cert doesn't have extensions, test if it is handled
530        # correctly.
531        rev0 = crl[0]
532        # It should return an empty Extensions object.
533        assert isinstance(rev0.extensions, x509.Extensions)
534        assert len(rev0.extensions) == 0
535        with pytest.raises(x509.ExtensionNotFound):
536            rev0.extensions.get_extension_for_oid(x509.OID_CRL_REASON)
537        with pytest.raises(x509.ExtensionNotFound):
538            rev0.extensions.get_extension_for_oid(x509.OID_CERTIFICATE_ISSUER)
539        with pytest.raises(x509.ExtensionNotFound):
540            rev0.extensions.get_extension_for_oid(x509.OID_INVALIDITY_DATE)
541
542        # Test manual retrieval of extension values.
543        rev1 = crl[1]
544        assert isinstance(rev1.extensions, x509.Extensions)
545
546        reason = rev1.extensions.get_extension_for_class(x509.CRLReason).value
547        assert reason == x509.CRLReason(x509.ReasonFlags.unspecified)
548
549        issuer = rev1.extensions.get_extension_for_class(
550            x509.CertificateIssuer
551        ).value
552        assert issuer == x509.CertificateIssuer(exp_issuer)
553
554        date = rev1.extensions.get_extension_for_class(
555            x509.InvalidityDate
556        ).value
557        assert date == x509.InvalidityDate(datetime.datetime(2015, 1, 1, 0, 0))
558
559        # Check if all reason flags can be found in the CRL.
560        flags = set(x509.ReasonFlags)
561        for rev in crl:
562            try:
563                r = rev.extensions.get_extension_for_class(x509.CRLReason)
564            except x509.ExtensionNotFound:
565                # Not all revoked certs have a reason extension.
566                pass
567            else:
568                flags.discard(r.value.reason)
569
570        assert len(flags) == 0
571
572    def test_no_revoked_certs(self, backend):
573        crl = _load_cert(
574            os.path.join("x509", "custom", "crl_empty.pem"),
575            x509.load_pem_x509_crl,
576            backend,
577        )
578        assert len(crl) == 0
579
580    def test_duplicate_entry_ext(self, backend):
581        crl = _load_cert(
582            os.path.join("x509", "custom", "crl_dup_entry_ext.pem"),
583            x509.load_pem_x509_crl,
584            backend,
585        )
586
587        with pytest.raises(x509.DuplicateExtension):
588            crl[0].extensions
589
590    def test_unsupported_crit_entry_ext(self, backend):
591        crl = _load_cert(
592            os.path.join(
593                "x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
594            ),
595            x509.load_pem_x509_crl,
596            backend,
597        )
598
599        ext = crl[0].extensions.get_extension_for_oid(
600            x509.ObjectIdentifier("1.2.3.4")
601        )
602        assert ext.value.value == b"\n\x01\x00"
603
604    def test_unsupported_reason(self, backend):
605        crl = _load_cert(
606            os.path.join("x509", "custom", "crl_unsupported_reason.pem"),
607            x509.load_pem_x509_crl,
608            backend,
609        )
610
611        with pytest.raises(ValueError):
612            crl[0].extensions
613
614    def test_invalid_cert_issuer_ext(self, backend):
615        crl = _load_cert(
616            os.path.join(
617                "x509", "custom", "crl_inval_cert_issuer_entry_ext.pem"
618            ),
619            x509.load_pem_x509_crl,
620            backend,
621        )
622
623        with pytest.raises(ValueError):
624            crl[0].extensions
625
626    def test_indexing(self, backend):
627        crl = _load_cert(
628            os.path.join("x509", "custom", "crl_all_reasons.pem"),
629            x509.load_pem_x509_crl,
630            backend,
631        )
632
633        with pytest.raises(IndexError):
634            crl[-13]
635        with pytest.raises(IndexError):
636            crl[12]
637
638        assert crl[-1].serial_number == crl[11].serial_number
639        assert len(crl[2:4]) == 2
640        assert crl[2:4][0].serial_number == crl[2].serial_number
641        assert crl[2:4][1].serial_number == crl[3].serial_number
642
643    def test_get_revoked_certificate_doesnt_reorder(self, backend):
644        private_key = RSA_KEY_2048.private_key(backend)
645        last_update = datetime.datetime(2002, 1, 1, 12, 1)
646        next_update = datetime.datetime(2030, 1, 1, 12, 1)
647        builder = (
648            x509.CertificateRevocationListBuilder()
649            .issuer_name(
650                x509.Name(
651                    [
652                        x509.NameAttribute(
653                            NameOID.COMMON_NAME, u"cryptography.io CA"
654                        )
655                    ]
656                )
657            )
658            .last_update(last_update)
659            .next_update(next_update)
660        )
661        for i in [2, 500, 3, 49, 7, 1]:
662            revoked_cert = (
663                x509.RevokedCertificateBuilder()
664                .serial_number(i)
665                .revocation_date(datetime.datetime(2012, 1, 1, 1, 1))
666                .build(backend)
667            )
668            builder = builder.add_revoked_certificate(revoked_cert)
669        crl = builder.sign(private_key, hashes.SHA256(), backend)
670        assert crl[0].serial_number == 2
671        assert crl[2].serial_number == 3
672        # make sure get_revoked_certificate_by_serial_number doesn't affect
673        # ordering after being invoked
674        crl.get_revoked_certificate_by_serial_number(500)
675        assert crl[0].serial_number == 2
676        assert crl[2].serial_number == 3
677
678
679@pytest.mark.requires_backend_interface(interface=RSABackend)
680@pytest.mark.requires_backend_interface(interface=X509Backend)
681class TestRSACertificate(object):
682    def test_load_pem_cert(self, backend):
683        cert = _load_cert(
684            os.path.join("x509", "custom", "post2000utctime.pem"),
685            x509.load_pem_x509_certificate,
686            backend,
687        )
688        assert isinstance(cert, x509.Certificate)
689        assert cert.serial_number == 11559813051657483483
690        fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
691        assert fingerprint == b"2b619ed04bfc9c3b08eb677d272192286a0947a8"
692        assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
693        assert (
694            cert.signature_algorithm_oid == SignatureAlgorithmOID.RSA_WITH_SHA1
695        )
696
697    def test_negative_serial_number(self, backend):
698        cert = _load_cert(
699            os.path.join("x509", "custom", "negative_serial.pem"),
700            x509.load_pem_x509_certificate,
701            backend,
702        )
703        assert cert.serial_number == -18008675309
704
705    def test_alternate_rsa_with_sha1_oid(self, backend):
706        cert = _load_cert(
707            os.path.join("x509", "alternate-rsa-sha1-oid.pem"),
708            x509.load_pem_x509_certificate,
709            backend,
710        )
711        assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
712        assert (
713            cert.signature_algorithm_oid
714            == SignatureAlgorithmOID._RSA_WITH_SHA1
715        )
716
717    def test_load_der_cert(self, backend):
718        cert = _load_cert(
719            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
720            x509.load_der_x509_certificate,
721            backend,
722        )
723        assert isinstance(cert, x509.Certificate)
724        assert cert.serial_number == 2
725        fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
726        assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
727        assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)
728
729    def test_signature(self, backend):
730        cert = _load_cert(
731            os.path.join("x509", "custom", "post2000utctime.pem"),
732            x509.load_pem_x509_certificate,
733            backend,
734        )
735        assert cert.signature == binascii.unhexlify(
736            b"8e0f72fcbebe4755abcaf76c8ce0bae17cde4db16291638e1b1ce04a93cdb4c"
737            b"44a3486070986c5a880c14fdf8497e7d289b2630ccb21d24a3d1aa1b2d87482"
738            b"07f3a1e16ccdf8daa8a7ea1a33d49774f513edf09270bd8e665b6300a10f003"
739            b"66a59076905eb63cf10a81a0ca78a6ef3127f6cb2f6fb7f947fce22a30d8004"
740            b"8c243ba2c1a54c425fe12310e8a737638f4920354d4cce25cbd9dea25e6a2fe"
741            b"0d8579a5c8d929b9275be221975479f3f75075bcacf09526523b5fd67f7683f"
742            b"3cda420fabb1e9e6fc26bc0649cf61bb051d6932fac37066bb16f55903dfe78"
743            b"53dc5e505e2a10fbba4f9e93a0d3b53b7fa34b05d7ba6eef869bfc34b8e514f"
744            b"d5419f75"
745        )
746        assert len(cert.signature) == cert.public_key().key_size // 8
747
748    def test_tbs_certificate_bytes(self, backend):
749        cert = _load_cert(
750            os.path.join("x509", "custom", "post2000utctime.pem"),
751            x509.load_pem_x509_certificate,
752            backend,
753        )
754        assert cert.tbs_certificate_bytes == binascii.unhexlify(
755            b"308202d8a003020102020900a06cb4b955f7f4db300d06092a864886f70d010"
756            b"10505003058310b3009060355040613024155311330110603550408130a536f"
757            b"6d652d53746174653121301f060355040a1318496e7465726e6574205769646"
758            b"769747320507479204c74643111300f0603550403130848656c6c6f20434130"
759            b"1e170d3134313132363231343132305a170d3134313232363231343132305a3"
760            b"058310b3009060355040613024155311330110603550408130a536f6d652d53"
761            b"746174653121301f060355040a1318496e7465726e657420576964676974732"
762            b"0507479204c74643111300f0603550403130848656c6c6f2043413082012230"
763            b"0d06092a864886f70d01010105000382010f003082010a0282010100b03af70"
764            b"2059e27f1e2284b56bbb26c039153bf81f295b73a49132990645ede4d2da0a9"
765            b"13c42e7d38d3589a00d3940d194f6e6d877c2ef812da22a275e83d8be786467"
766            b"48b4e7f23d10e873fd72f57a13dec732fc56ab138b1bb308399bb412cd73921"
767            b"4ef714e1976e09603405e2556299a05522510ac4574db5e9cb2cf5f99e8f48c"
768            b"1696ab3ea2d6d2ddab7d4e1b317188b76a572977f6ece0a4ad396f0150e7d8b"
769            b"1a9986c0cb90527ec26ca56e2914c270d2a198b632fa8a2fda55079d3d39864"
770            b"b6fb96ddbe331cacb3cb8783a8494ccccd886a3525078847ca01ca5f803e892"
771            b"14403e8a4b5499539c0b86f7a0daa45b204a8e079d8a5b03db7ba1ba3d7011a"
772            b"70203010001a381bc3081b9301d0603551d0e04160414d8e89dc777e4472656"
773            b"f1864695a9f66b7b0400ae3081890603551d23048181307f8014d8e89dc777e"
774            b"4472656f1864695a9f66b7b0400aea15ca45a3058310b300906035504061302"
775            b"4155311330110603550408130a536f6d652d53746174653121301f060355040"
776            b"a1318496e7465726e6574205769646769747320507479204c74643111300f06"
777            b"03550403130848656c6c6f204341820900a06cb4b955f7f4db300c0603551d1"
778            b"3040530030101ff"
779        )
780        cert.public_key().verify(
781            cert.signature,
782            cert.tbs_certificate_bytes,
783            padding.PKCS1v15(),
784            cert.signature_hash_algorithm,
785        )
786
787    def test_issuer(self, backend):
788        cert = _load_cert(
789            os.path.join(
790                "x509",
791                "PKITS_data",
792                "certs",
793                "Validpre2000UTCnotBeforeDateTest3EE.crt",
794            ),
795            x509.load_der_x509_certificate,
796            backend,
797        )
798        issuer = cert.issuer
799        assert isinstance(issuer, x509.Name)
800        assert list(issuer) == [
801            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
802            x509.NameAttribute(
803                NameOID.ORGANIZATION_NAME, u"Test Certificates 2011"
804            ),
805            x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA"),
806        ]
807        assert issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [
808            x509.NameAttribute(NameOID.COMMON_NAME, u"Good CA")
809        ]
810
811    def test_all_issuer_name_types(self, backend):
812        cert = _load_cert(
813            os.path.join("x509", "custom", "all_supported_names.pem"),
814            x509.load_pem_x509_certificate,
815            backend,
816        )
817        issuer = cert.issuer
818
819        assert isinstance(issuer, x509.Name)
820        assert list(issuer) == [
821            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
822            x509.NameAttribute(NameOID.COUNTRY_NAME, u"CA"),
823            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
824            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Illinois"),
825            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Chicago"),
826            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
827            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Zero, LLC"),
828            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"One, LLC"),
829            x509.NameAttribute(NameOID.COMMON_NAME, u"common name 0"),
830            x509.NameAttribute(NameOID.COMMON_NAME, u"common name 1"),
831            x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"OU 0"),
832            x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"OU 1"),
833            x509.NameAttribute(NameOID.DN_QUALIFIER, u"dnQualifier0"),
834            x509.NameAttribute(NameOID.DN_QUALIFIER, u"dnQualifier1"),
835            x509.NameAttribute(NameOID.SERIAL_NUMBER, u"123"),
836            x509.NameAttribute(NameOID.SERIAL_NUMBER, u"456"),
837            x509.NameAttribute(NameOID.TITLE, u"Title 0"),
838            x509.NameAttribute(NameOID.TITLE, u"Title 1"),
839            x509.NameAttribute(NameOID.SURNAME, u"Surname 0"),
840            x509.NameAttribute(NameOID.SURNAME, u"Surname 1"),
841            x509.NameAttribute(NameOID.GIVEN_NAME, u"Given Name 0"),
842            x509.NameAttribute(NameOID.GIVEN_NAME, u"Given Name 1"),
843            x509.NameAttribute(NameOID.PSEUDONYM, u"Incognito 0"),
844            x509.NameAttribute(NameOID.PSEUDONYM, u"Incognito 1"),
845            x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Last Gen"),
846            x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Next Gen"),
847            x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc0"),
848            x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc1"),
849            x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test0@test.local"),
850            x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test1@test.local"),
851        ]
852
853    def test_subject(self, backend):
854        cert = _load_cert(
855            os.path.join(
856                "x509",
857                "PKITS_data",
858                "certs",
859                "Validpre2000UTCnotBeforeDateTest3EE.crt",
860            ),
861            x509.load_der_x509_certificate,
862            backend,
863        )
864        subject = cert.subject
865        assert isinstance(subject, x509.Name)
866        assert list(subject) == [
867            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
868            x509.NameAttribute(
869                NameOID.ORGANIZATION_NAME, u"Test Certificates 2011"
870            ),
871            x509.NameAttribute(
872                NameOID.COMMON_NAME,
873                u"Valid pre2000 UTC notBefore Date EE Certificate Test3",
874            ),
875        ]
876        assert subject.get_attributes_for_oid(NameOID.COMMON_NAME) == [
877            x509.NameAttribute(
878                NameOID.COMMON_NAME,
879                u"Valid pre2000 UTC notBefore Date EE Certificate Test3",
880            )
881        ]
882
883    def test_unicode_name(self, backend):
884        cert = _load_cert(
885            os.path.join("x509", "custom", "utf8_common_name.pem"),
886            x509.load_pem_x509_certificate,
887            backend,
888        )
889        assert cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME) == [
890            x509.NameAttribute(NameOID.COMMON_NAME, u"We heart UTF8!\u2122")
891        ]
892        assert cert.issuer.get_attributes_for_oid(NameOID.COMMON_NAME) == [
893            x509.NameAttribute(NameOID.COMMON_NAME, u"We heart UTF8!\u2122")
894        ]
895
896    def test_non_ascii_dns_name(self, backend):
897        cert = _load_cert(
898            os.path.join("x509", "utf8-dnsname.pem"),
899            x509.load_pem_x509_certificate,
900            backend,
901        )
902        san = cert.extensions.get_extension_for_class(
903            x509.SubjectAlternativeName
904        ).value
905
906        names = san.get_values_for_type(x509.DNSName)
907
908        assert names == [
909            u"partner.biztositas.hu",
910            u"biztositas.hu",
911            u"*.biztositas.hu",
912            u"biztos\xedt\xe1s.hu",
913            u"*.biztos\xedt\xe1s.hu",
914            u"xn--biztosts-fza2j.hu",
915            u"*.xn--biztosts-fza2j.hu",
916        ]
917
918    def test_all_subject_name_types(self, backend):
919        cert = _load_cert(
920            os.path.join("x509", "custom", "all_supported_names.pem"),
921            x509.load_pem_x509_certificate,
922            backend,
923        )
924        subject = cert.subject
925        assert isinstance(subject, x509.Name)
926        assert list(subject) == [
927            x509.NameAttribute(NameOID.COUNTRY_NAME, u"AU"),
928            x509.NameAttribute(NameOID.COUNTRY_NAME, u"DE"),
929            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
930            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"New York"),
931            x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
932            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Ithaca"),
933            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org Zero, LLC"),
934            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Org One, LLC"),
935            x509.NameAttribute(NameOID.COMMON_NAME, u"CN 0"),
936            x509.NameAttribute(NameOID.COMMON_NAME, u"CN 1"),
937            x509.NameAttribute(
938                NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 0"
939            ),
940            x509.NameAttribute(
941                NameOID.ORGANIZATIONAL_UNIT_NAME, u"Engineering 1"
942            ),
943            x509.NameAttribute(NameOID.DN_QUALIFIER, u"qualified0"),
944            x509.NameAttribute(NameOID.DN_QUALIFIER, u"qualified1"),
945            x509.NameAttribute(NameOID.SERIAL_NUMBER, u"789"),
946            x509.NameAttribute(NameOID.SERIAL_NUMBER, u"012"),
947            x509.NameAttribute(NameOID.TITLE, u"Title IX"),
948            x509.NameAttribute(NameOID.TITLE, u"Title X"),
949            x509.NameAttribute(NameOID.SURNAME, u"Last 0"),
950            x509.NameAttribute(NameOID.SURNAME, u"Last 1"),
951            x509.NameAttribute(NameOID.GIVEN_NAME, u"First 0"),
952            x509.NameAttribute(NameOID.GIVEN_NAME, u"First 1"),
953            x509.NameAttribute(NameOID.PSEUDONYM, u"Guy Incognito 0"),
954            x509.NameAttribute(NameOID.PSEUDONYM, u"Guy Incognito 1"),
955            x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"32X"),
956            x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"Dreamcast"),
957            x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc2"),
958            x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"dc3"),
959            x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test2@test.local"),
960            x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"test3@test.local"),
961        ]
962
963    def test_load_good_ca_cert(self, backend):
964        cert = _load_cert(
965            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
966            x509.load_der_x509_certificate,
967            backend,
968        )
969
970        assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
971        assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
972        assert cert.serial_number == 2
973        public_key = cert.public_key()
974        assert isinstance(public_key, rsa.RSAPublicKey)
975        assert cert.version is x509.Version.v3
976        fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
977        assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
978
979    def test_utc_pre_2000_not_before_cert(self, backend):
980        cert = _load_cert(
981            os.path.join(
982                "x509",
983                "PKITS_data",
984                "certs",
985                "Validpre2000UTCnotBeforeDateTest3EE.crt",
986            ),
987            x509.load_der_x509_certificate,
988            backend,
989        )
990
991        assert cert.not_valid_before == datetime.datetime(1950, 1, 1, 12, 1)
992
993    def test_pre_2000_utc_not_after_cert(self, backend):
994        cert = _load_cert(
995            os.path.join(
996                "x509",
997                "PKITS_data",
998                "certs",
999                "Invalidpre2000UTCEEnotAfterDateTest7EE.crt",
1000            ),
1001            x509.load_der_x509_certificate,
1002            backend,
1003        )
1004
1005        assert cert.not_valid_after == datetime.datetime(1999, 1, 1, 12, 1)
1006
1007    def test_post_2000_utc_cert(self, backend):
1008        cert = _load_cert(
1009            os.path.join("x509", "custom", "post2000utctime.pem"),
1010            x509.load_pem_x509_certificate,
1011            backend,
1012        )
1013        assert cert.not_valid_before == datetime.datetime(
1014            2014, 11, 26, 21, 41, 20
1015        )
1016        assert cert.not_valid_after == datetime.datetime(
1017            2014, 12, 26, 21, 41, 20
1018        )
1019
1020    def test_generalized_time_not_before_cert(self, backend):
1021        cert = _load_cert(
1022            os.path.join(
1023                "x509",
1024                "PKITS_data",
1025                "certs",
1026                "ValidGeneralizedTimenotBeforeDateTest4EE.crt",
1027            ),
1028            x509.load_der_x509_certificate,
1029            backend,
1030        )
1031        assert cert.not_valid_before == datetime.datetime(2002, 1, 1, 12, 1)
1032        assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
1033        assert cert.version is x509.Version.v3
1034
1035    def test_generalized_time_not_after_cert(self, backend):
1036        cert = _load_cert(
1037            os.path.join(
1038                "x509",
1039                "PKITS_data",
1040                "certs",
1041                "ValidGeneralizedTimenotAfterDateTest8EE.crt",
1042            ),
1043            x509.load_der_x509_certificate,
1044            backend,
1045        )
1046        assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
1047        assert cert.not_valid_after == datetime.datetime(2050, 1, 1, 12, 1)
1048        assert cert.version is x509.Version.v3
1049
1050    def test_invalid_version_cert(self, backend):
1051        with pytest.raises(x509.InvalidVersion) as exc:
1052            _load_cert(
1053                os.path.join("x509", "custom", "invalid_version.pem"),
1054                x509.load_pem_x509_certificate,
1055                backend,
1056            )
1057
1058        assert exc.value.parsed_version == 7
1059
1060    def test_eq(self, backend):
1061        cert = _load_cert(
1062            os.path.join("x509", "custom", "post2000utctime.pem"),
1063            x509.load_pem_x509_certificate,
1064            backend,
1065        )
1066        cert2 = _load_cert(
1067            os.path.join("x509", "custom", "post2000utctime.pem"),
1068            x509.load_pem_x509_certificate,
1069            backend,
1070        )
1071        assert cert == cert2
1072
1073    def test_ne(self, backend):
1074        cert = _load_cert(
1075            os.path.join("x509", "custom", "post2000utctime.pem"),
1076            x509.load_pem_x509_certificate,
1077            backend,
1078        )
1079        cert2 = _load_cert(
1080            os.path.join(
1081                "x509",
1082                "PKITS_data",
1083                "certs",
1084                "ValidGeneralizedTimenotAfterDateTest8EE.crt",
1085            ),
1086            x509.load_der_x509_certificate,
1087            backend,
1088        )
1089        assert cert != cert2
1090        assert cert != object()
1091
1092    def test_hash(self, backend):
1093        cert1 = _load_cert(
1094            os.path.join("x509", "custom", "post2000utctime.pem"),
1095            x509.load_pem_x509_certificate,
1096            backend,
1097        )
1098        cert2 = _load_cert(
1099            os.path.join("x509", "custom", "post2000utctime.pem"),
1100            x509.load_pem_x509_certificate,
1101            backend,
1102        )
1103        cert3 = _load_cert(
1104            os.path.join(
1105                "x509",
1106                "PKITS_data",
1107                "certs",
1108                "ValidGeneralizedTimenotAfterDateTest8EE.crt",
1109            ),
1110            x509.load_der_x509_certificate,
1111            backend,
1112        )
1113
1114        assert hash(cert1) == hash(cert2)
1115        assert hash(cert1) != hash(cert3)
1116
1117    def test_version_1_cert(self, backend):
1118        cert = _load_cert(
1119            os.path.join("x509", "v1_cert.pem"),
1120            x509.load_pem_x509_certificate,
1121            backend,
1122        )
1123        assert cert.version is x509.Version.v1
1124
1125    def test_invalid_pem(self, backend):
1126        with pytest.raises(ValueError):
1127            x509.load_pem_x509_certificate(b"notacert", backend)
1128
1129    def test_invalid_der(self, backend):
1130        with pytest.raises(ValueError):
1131            x509.load_der_x509_certificate(b"notacert", backend)
1132
1133    def test_unsupported_signature_hash_algorithm_cert(self, backend):
1134        cert = _load_cert(
1135            os.path.join("x509", "verisign_md2_root.pem"),
1136            x509.load_pem_x509_certificate,
1137            backend,
1138        )
1139        with pytest.raises(UnsupportedAlgorithm):
1140            cert.signature_hash_algorithm
1141
1142    def test_public_bytes_pem(self, backend):
1143        # Load an existing certificate.
1144        cert = _load_cert(
1145            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1146            x509.load_der_x509_certificate,
1147            backend,
1148        )
1149
1150        # Encode it to PEM and load it back.
1151        cert = x509.load_pem_x509_certificate(
1152            cert.public_bytes(
1153                encoding=serialization.Encoding.PEM,
1154            ),
1155            backend,
1156        )
1157
1158        # We should recover what we had to start with.
1159        assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
1160        assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
1161        assert cert.serial_number == 2
1162        public_key = cert.public_key()
1163        assert isinstance(public_key, rsa.RSAPublicKey)
1164        assert cert.version is x509.Version.v3
1165        fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
1166        assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
1167
1168    def test_public_bytes_der(self, backend):
1169        # Load an existing certificate.
1170        cert = _load_cert(
1171            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1172            x509.load_der_x509_certificate,
1173            backend,
1174        )
1175
1176        # Encode it to DER and load it back.
1177        cert = x509.load_der_x509_certificate(
1178            cert.public_bytes(
1179                encoding=serialization.Encoding.DER,
1180            ),
1181            backend,
1182        )
1183
1184        # We should recover what we had to start with.
1185        assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30)
1186        assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30)
1187        assert cert.serial_number == 2
1188        public_key = cert.public_key()
1189        assert isinstance(public_key, rsa.RSAPublicKey)
1190        assert cert.version is x509.Version.v3
1191        fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1()))
1192        assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
1193
1194    def test_public_bytes_invalid_encoding(self, backend):
1195        cert = _load_cert(
1196            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1197            x509.load_der_x509_certificate,
1198            backend,
1199        )
1200
1201        with pytest.raises(TypeError):
1202            cert.public_bytes("NotAnEncoding")
1203
1204    @pytest.mark.parametrize(
1205        ("cert_path", "loader_func", "encoding"),
1206        [
1207            (
1208                os.path.join("x509", "v1_cert.pem"),
1209                x509.load_pem_x509_certificate,
1210                serialization.Encoding.PEM,
1211            ),
1212            (
1213                os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1214                x509.load_der_x509_certificate,
1215                serialization.Encoding.DER,
1216            ),
1217        ],
1218    )
1219    def test_public_bytes_match(
1220        self, cert_path, loader_func, encoding, backend
1221    ):
1222        cert_bytes = load_vectors_from_file(
1223            cert_path, lambda pemfile: pemfile.read(), mode="rb"
1224        )
1225        cert = loader_func(cert_bytes, backend)
1226        serialized = cert.public_bytes(encoding)
1227        assert serialized == cert_bytes
1228
1229    def test_certificate_repr(self, backend):
1230        cert = _load_cert(
1231            os.path.join("x509", "cryptography.io.pem"),
1232            x509.load_pem_x509_certificate,
1233            backend,
1234        )
1235        assert repr(cert) == (
1236            "<Certificate(subject=<Name(OU=GT48742965,OU=See www.rapidssl.com"
1237            "/resources/cps (c)14,OU=Domain Control Validated - RapidSSL(R),"
1238            "CN=www.cryptography.io)>, ...)>"
1239        )
1240
1241    def test_parse_tls_feature_extension(self, backend):
1242        cert = _load_cert(
1243            os.path.join("x509", "tls-feature-ocsp-staple.pem"),
1244            x509.load_pem_x509_certificate,
1245            backend,
1246        )
1247        ext = cert.extensions.get_extension_for_class(x509.TLSFeature)
1248        assert ext.critical is False
1249        assert ext.value == x509.TLSFeature(
1250            [x509.TLSFeatureType.status_request]
1251        )
1252
1253
1254@pytest.mark.requires_backend_interface(interface=RSABackend)
1255@pytest.mark.requires_backend_interface(interface=X509Backend)
1256class TestRSACertificateRequest(object):
1257    @pytest.mark.parametrize(
1258        ("path", "loader_func"),
1259        [
1260            [
1261                os.path.join("x509", "requests", "rsa_sha1.pem"),
1262                x509.load_pem_x509_csr,
1263            ],
1264            [
1265                os.path.join("x509", "requests", "rsa_sha1.der"),
1266                x509.load_der_x509_csr,
1267            ],
1268        ],
1269    )
1270    def test_load_rsa_certificate_request(self, path, loader_func, backend):
1271        request = _load_cert(path, loader_func, backend)
1272        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
1273        assert (
1274            request.signature_algorithm_oid
1275            == SignatureAlgorithmOID.RSA_WITH_SHA1
1276        )
1277        public_key = request.public_key()
1278        assert isinstance(public_key, rsa.RSAPublicKey)
1279        subject = request.subject
1280        assert isinstance(subject, x509.Name)
1281        assert list(subject) == [
1282            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1283            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
1284            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
1285            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
1286            x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
1287        ]
1288        extensions = request.extensions
1289        assert isinstance(extensions, x509.Extensions)
1290        assert list(extensions) == []
1291
1292    def test_get_attribute_for_oid_challenge(self, backend):
1293        request = _load_cert(
1294            os.path.join("x509", "requests", "challenge.pem"),
1295            x509.load_pem_x509_csr,
1296            backend,
1297        )
1298        assert (
1299            request.get_attribute_for_oid(
1300                x509.oid.AttributeOID.CHALLENGE_PASSWORD
1301            )
1302            == b"challenge me!"
1303        )
1304
1305    def test_get_attribute_for_oid_multiple(self, backend):
1306        request = _load_cert(
1307            os.path.join("x509", "requests", "challenge-unstructured.pem"),
1308            x509.load_pem_x509_csr,
1309            backend,
1310        )
1311        assert (
1312            request.get_attribute_for_oid(
1313                x509.oid.AttributeOID.CHALLENGE_PASSWORD
1314            )
1315            == b"beauty"
1316        )
1317        assert (
1318            request.get_attribute_for_oid(
1319                x509.oid.AttributeOID.UNSTRUCTURED_NAME
1320            )
1321            == b"an unstructured field"
1322        )
1323
1324    def test_invalid_attribute_for_oid(self, backend):
1325        """
1326        This test deliberately triggers a ValueError because to parse
1327        CSR attributes we need to do a C cast. If we're wrong about the
1328        type that would be Very Bad so this test confirms we properly explode
1329        in the presence of the wrong types.
1330        """
1331        request = _load_cert(
1332            os.path.join("x509", "requests", "challenge-invalid.der"),
1333            x509.load_der_x509_csr,
1334            backend,
1335        )
1336        with pytest.raises(ValueError):
1337            request.get_attribute_for_oid(
1338                x509.oid.AttributeOID.CHALLENGE_PASSWORD
1339            )
1340
1341    def test_no_challenge_password(self, backend):
1342        request = _load_cert(
1343            os.path.join("x509", "requests", "rsa_sha256.pem"),
1344            x509.load_pem_x509_csr,
1345            backend,
1346        )
1347        with pytest.raises(x509.AttributeNotFound) as exc:
1348            request.get_attribute_for_oid(
1349                x509.oid.AttributeOID.CHALLENGE_PASSWORD
1350            )
1351        assert exc.value.oid == x509.oid.AttributeOID.CHALLENGE_PASSWORD
1352
1353    @pytest.mark.parametrize(
1354        "loader_func", [x509.load_pem_x509_csr, x509.load_der_x509_csr]
1355    )
1356    def test_invalid_certificate_request(self, loader_func, backend):
1357        with pytest.raises(ValueError):
1358            loader_func(b"notacsr", backend)
1359
1360    def test_unsupported_signature_hash_algorithm_request(self, backend):
1361        request = _load_cert(
1362            os.path.join("x509", "requests", "rsa_md4.pem"),
1363            x509.load_pem_x509_csr,
1364            backend,
1365        )
1366        with pytest.raises(UnsupportedAlgorithm):
1367            request.signature_hash_algorithm
1368
1369    def test_duplicate_extension(self, backend):
1370        request = _load_cert(
1371            os.path.join("x509", "requests", "two_basic_constraints.pem"),
1372            x509.load_pem_x509_csr,
1373            backend,
1374        )
1375        with pytest.raises(x509.DuplicateExtension) as exc:
1376            request.extensions
1377
1378        assert exc.value.oid == ExtensionOID.BASIC_CONSTRAINTS
1379
1380    def test_unsupported_critical_extension(self, backend):
1381        request = _load_cert(
1382            os.path.join(
1383                "x509", "requests", "unsupported_extension_critical.pem"
1384            ),
1385            x509.load_pem_x509_csr,
1386            backend,
1387        )
1388        ext = request.extensions.get_extension_for_oid(
1389            x509.ObjectIdentifier("1.2.3.4")
1390        )
1391        assert ext.value.value == b"value"
1392
1393    def test_unsupported_extension(self, backend):
1394        request = _load_cert(
1395            os.path.join("x509", "requests", "unsupported_extension.pem"),
1396            x509.load_pem_x509_csr,
1397            backend,
1398        )
1399        extensions = request.extensions
1400        assert len(extensions) == 1
1401        assert extensions[0].oid == x509.ObjectIdentifier("1.2.3.4")
1402        assert extensions[0].value == x509.UnrecognizedExtension(
1403            x509.ObjectIdentifier("1.2.3.4"), b"value"
1404        )
1405
1406    def test_request_basic_constraints(self, backend):
1407        request = _load_cert(
1408            os.path.join("x509", "requests", "basic_constraints.pem"),
1409            x509.load_pem_x509_csr,
1410            backend,
1411        )
1412        extensions = request.extensions
1413        assert isinstance(extensions, x509.Extensions)
1414        assert list(extensions) == [
1415            x509.Extension(
1416                ExtensionOID.BASIC_CONSTRAINTS,
1417                True,
1418                x509.BasicConstraints(ca=True, path_length=1),
1419            ),
1420        ]
1421
1422    def test_subject_alt_name(self, backend):
1423        request = _load_cert(
1424            os.path.join("x509", "requests", "san_rsa_sha1.pem"),
1425            x509.load_pem_x509_csr,
1426            backend,
1427        )
1428        ext = request.extensions.get_extension_for_oid(
1429            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
1430        )
1431        assert list(ext.value) == [
1432            x509.DNSName(u"cryptography.io"),
1433            x509.DNSName(u"sub.cryptography.io"),
1434        ]
1435
1436    def test_public_bytes_pem(self, backend):
1437        # Load an existing CSR.
1438        request = _load_cert(
1439            os.path.join("x509", "requests", "rsa_sha1.pem"),
1440            x509.load_pem_x509_csr,
1441            backend,
1442        )
1443
1444        # Encode it to PEM and load it back.
1445        request = x509.load_pem_x509_csr(
1446            request.public_bytes(
1447                encoding=serialization.Encoding.PEM,
1448            ),
1449            backend,
1450        )
1451
1452        # We should recover what we had to start with.
1453        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
1454        public_key = request.public_key()
1455        assert isinstance(public_key, rsa.RSAPublicKey)
1456        subject = request.subject
1457        assert isinstance(subject, x509.Name)
1458        assert list(subject) == [
1459            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1460            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
1461            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
1462            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
1463            x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
1464        ]
1465
1466    def test_public_bytes_der(self, backend):
1467        # Load an existing CSR.
1468        request = _load_cert(
1469            os.path.join("x509", "requests", "rsa_sha1.pem"),
1470            x509.load_pem_x509_csr,
1471            backend,
1472        )
1473
1474        # Encode it to DER and load it back.
1475        request = x509.load_der_x509_csr(
1476            request.public_bytes(
1477                encoding=serialization.Encoding.DER,
1478            ),
1479            backend,
1480        )
1481
1482        # We should recover what we had to start with.
1483        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
1484        public_key = request.public_key()
1485        assert isinstance(public_key, rsa.RSAPublicKey)
1486        subject = request.subject
1487        assert isinstance(subject, x509.Name)
1488        assert list(subject) == [
1489            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1490            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
1491            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
1492            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
1493            x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
1494        ]
1495
1496    def test_signature(self, backend):
1497        request = _load_cert(
1498            os.path.join("x509", "requests", "rsa_sha1.pem"),
1499            x509.load_pem_x509_csr,
1500            backend,
1501        )
1502        assert request.signature == binascii.unhexlify(
1503            b"8364c86ffbbfe0bfc9a21f831256658ca8989741b80576d36f08a934603a43b1"
1504            b"837246d00167a518abb1de7b51a1e5b7ebea14944800818b1a923c804f120a0d"
1505            b"624f6310ef79e8612755c2b01dcc7f59dfdbce0db3f2630f185f504b8c17af80"
1506            b"cbd364fa5fda68337153930948226cd4638287a0aed6524d3006885c19028a1e"
1507            b"e2f5a91d6e77dbaa0b49996ee0a0c60b55b61bd080a08bb34aa7f3e07e91f37f"
1508            b"6a11645be2d8654c1570dcda145ed7cc92017f7d53225d7f283f3459ec5bda41"
1509            b"cf6dd75d43676c543483385226b7e4fa29c8739f1b0eaf199613593991979862"
1510            b"e36181e8c4c270c354b7f52c128db1b70639823324c7ea24791b7bc3d7005f3b"
1511        )
1512
1513    def test_tbs_certrequest_bytes(self, backend):
1514        request = _load_cert(
1515            os.path.join("x509", "requests", "rsa_sha1.pem"),
1516            x509.load_pem_x509_csr,
1517            backend,
1518        )
1519        assert request.tbs_certrequest_bytes == binascii.unhexlify(
1520            b"308201840201003057310b3009060355040613025553310e300c060355040813"
1521            b"055465786173310f300d0603550407130641757374696e310d300b060355040a"
1522            b"130450794341311830160603550403130f63727970746f6772617068792e696f"
1523            b"30820122300d06092a864886f70d01010105000382010f003082010a02820101"
1524            b"00a840a78460cb861066dfa3045a94ba6cf1b7ab9d24c761cffddcc2cb5e3f1d"
1525            b"c3e4be253e7039ef14fe9d6d2304f50d9f2e1584c51530ab75086f357138bff7"
1526            b"b854d067d1d5f384f1f2f2c39cc3b15415e2638554ef8402648ae3ef08336f22"
1527            b"b7ecc6d4331c2b21c3091a7f7a9518180754a646640b60419e4cc6f5c798110a"
1528            b"7f030a639fe87e33b4776dfcd993940ec776ab57a181ad8598857976dc303f9a"
1529            b"573ca619ab3fe596328e92806b828683edc17cc256b41948a2bfa8d047d2158d"
1530            b"3d8e069aa05fa85b3272abb1c4b4422b6366f3b70e642377b145cd6259e5d3e7"
1531            b"db048d51921e50766a37b1b130ee6b11f507d20a834001e8de16a92c14f2e964"
1532            b"a30203010001a000"
1533        )
1534        request.public_key().verify(
1535            request.signature,
1536            request.tbs_certrequest_bytes,
1537            padding.PKCS1v15(),
1538            request.signature_hash_algorithm,
1539        )
1540
1541    def test_public_bytes_invalid_encoding(self, backend):
1542        request = _load_cert(
1543            os.path.join("x509", "requests", "rsa_sha1.pem"),
1544            x509.load_pem_x509_csr,
1545            backend,
1546        )
1547
1548        with pytest.raises(TypeError):
1549            request.public_bytes("NotAnEncoding")
1550
1551    def test_signature_invalid(self, backend):
1552        request = _load_cert(
1553            os.path.join("x509", "requests", "invalid_signature.pem"),
1554            x509.load_pem_x509_csr,
1555            backend,
1556        )
1557        assert not request.is_signature_valid
1558
1559    def test_signature_valid(self, backend):
1560        request = _load_cert(
1561            os.path.join("x509", "requests", "rsa_sha256.pem"),
1562            x509.load_pem_x509_csr,
1563            backend,
1564        )
1565        assert request.is_signature_valid
1566
1567    @pytest.mark.parametrize(
1568        ("request_path", "loader_func", "encoding"),
1569        [
1570            (
1571                os.path.join("x509", "requests", "rsa_sha1.pem"),
1572                x509.load_pem_x509_csr,
1573                serialization.Encoding.PEM,
1574            ),
1575            (
1576                os.path.join("x509", "requests", "rsa_sha1.der"),
1577                x509.load_der_x509_csr,
1578                serialization.Encoding.DER,
1579            ),
1580        ],
1581    )
1582    def test_public_bytes_match(
1583        self, request_path, loader_func, encoding, backend
1584    ):
1585        request_bytes = load_vectors_from_file(
1586            request_path, lambda pemfile: pemfile.read(), mode="rb"
1587        )
1588        request = loader_func(request_bytes, backend)
1589        serialized = request.public_bytes(encoding)
1590        assert serialized == request_bytes
1591
1592    def test_eq(self, backend):
1593        request1 = _load_cert(
1594            os.path.join("x509", "requests", "rsa_sha1.pem"),
1595            x509.load_pem_x509_csr,
1596            backend,
1597        )
1598        request2 = _load_cert(
1599            os.path.join("x509", "requests", "rsa_sha1.pem"),
1600            x509.load_pem_x509_csr,
1601            backend,
1602        )
1603
1604        assert request1 == request2
1605
1606    def test_ne(self, backend):
1607        request1 = _load_cert(
1608            os.path.join("x509", "requests", "rsa_sha1.pem"),
1609            x509.load_pem_x509_csr,
1610            backend,
1611        )
1612        request2 = _load_cert(
1613            os.path.join("x509", "requests", "san_rsa_sha1.pem"),
1614            x509.load_pem_x509_csr,
1615            backend,
1616        )
1617
1618        assert request1 != request2
1619        assert request1 != object()
1620
1621    def test_hash(self, backend):
1622        request1 = _load_cert(
1623            os.path.join("x509", "requests", "rsa_sha1.pem"),
1624            x509.load_pem_x509_csr,
1625            backend,
1626        )
1627        request2 = _load_cert(
1628            os.path.join("x509", "requests", "rsa_sha1.pem"),
1629            x509.load_pem_x509_csr,
1630            backend,
1631        )
1632        request3 = _load_cert(
1633            os.path.join("x509", "requests", "san_rsa_sha1.pem"),
1634            x509.load_pem_x509_csr,
1635            backend,
1636        )
1637
1638        assert hash(request1) == hash(request2)
1639        assert hash(request1) != hash(request3)
1640
1641    def test_build_cert(self, backend):
1642        issuer_private_key = RSA_KEY_2048.private_key(backend)
1643        subject_private_key = RSA_KEY_2048.private_key(backend)
1644
1645        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
1646        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
1647
1648        builder = (
1649            x509.CertificateBuilder()
1650            .serial_number(777)
1651            .issuer_name(
1652                x509.Name(
1653                    [
1654                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1655                        x509.NameAttribute(
1656                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
1657                        ),
1658                        x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
1659                        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
1660                        x509.NameAttribute(
1661                            NameOID.COMMON_NAME, u"cryptography.io"
1662                        ),
1663                    ]
1664                )
1665            )
1666            .subject_name(
1667                x509.Name(
1668                    [
1669                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1670                        x509.NameAttribute(
1671                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
1672                        ),
1673                        x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
1674                        x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
1675                        x509.NameAttribute(
1676                            NameOID.COMMON_NAME, u"cryptography.io"
1677                        ),
1678                    ]
1679                )
1680            )
1681            .public_key(subject_private_key.public_key())
1682            .add_extension(
1683                x509.BasicConstraints(ca=False, path_length=None),
1684                True,
1685            )
1686            .add_extension(
1687                x509.SubjectAlternativeName(
1688                    [x509.DNSName(u"cryptography.io")]
1689                ),
1690                critical=False,
1691            )
1692            .not_valid_before(not_valid_before)
1693            .not_valid_after(not_valid_after)
1694        )
1695
1696        cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
1697
1698        assert cert.version is x509.Version.v3
1699        assert cert.not_valid_before == not_valid_before
1700        assert cert.not_valid_after == not_valid_after
1701        basic_constraints = cert.extensions.get_extension_for_oid(
1702            ExtensionOID.BASIC_CONSTRAINTS
1703        )
1704        assert basic_constraints.value.ca is False
1705        assert basic_constraints.value.path_length is None
1706        subject_alternative_name = cert.extensions.get_extension_for_oid(
1707            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
1708        )
1709        assert list(subject_alternative_name.value) == [
1710            x509.DNSName(u"cryptography.io"),
1711        ]
1712
1713    def test_build_cert_private_type_encoding(self, backend):
1714        issuer_private_key = RSA_KEY_2048.private_key(backend)
1715        subject_private_key = RSA_KEY_2048.private_key(backend)
1716        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
1717        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
1718        name = x509.Name(
1719            [
1720                x509.NameAttribute(
1721                    NameOID.STATE_OR_PROVINCE_NAME,
1722                    u"Texas",
1723                    _ASN1Type.PrintableString,
1724                ),
1725                x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
1726                x509.NameAttribute(
1727                    NameOID.COMMON_NAME,
1728                    u"cryptography.io",
1729                    _ASN1Type.IA5String,
1730                ),
1731            ]
1732        )
1733        builder = (
1734            x509.CertificateBuilder()
1735            .serial_number(777)
1736            .issuer_name(name)
1737            .subject_name(name)
1738            .public_key(subject_private_key.public_key())
1739            .not_valid_before(not_valid_before)
1740            .not_valid_after(not_valid_after)
1741        )
1742        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
1743
1744        for dn in (cert.subject, cert.issuer):
1745            assert (
1746                dn.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[
1747                    0
1748                ]._type
1749                == _ASN1Type.PrintableString
1750            )
1751            assert (
1752                dn.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[
1753                    0
1754                ]._type
1755                == _ASN1Type.PrintableString
1756            )
1757            assert (
1758                dn.get_attributes_for_oid(NameOID.LOCALITY_NAME)[0]._type
1759                == _ASN1Type.UTF8String
1760            )
1761
1762    def test_build_cert_printable_string_country_name(self, backend):
1763        issuer_private_key = RSA_KEY_2048.private_key(backend)
1764        subject_private_key = RSA_KEY_2048.private_key(backend)
1765
1766        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
1767        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
1768
1769        builder = (
1770            x509.CertificateBuilder()
1771            .serial_number(777)
1772            .issuer_name(
1773                x509.Name(
1774                    [
1775                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1776                        x509.NameAttribute(
1777                            NameOID.JURISDICTION_COUNTRY_NAME, u"US"
1778                        ),
1779                        x509.NameAttribute(
1780                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
1781                        ),
1782                    ]
1783                )
1784            )
1785            .subject_name(
1786                x509.Name(
1787                    [
1788                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1789                        x509.NameAttribute(
1790                            NameOID.JURISDICTION_COUNTRY_NAME, u"US"
1791                        ),
1792                        x509.NameAttribute(
1793                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
1794                        ),
1795                    ]
1796                )
1797            )
1798            .public_key(subject_private_key.public_key())
1799            .not_valid_before(not_valid_before)
1800            .not_valid_after(not_valid_after)
1801        )
1802
1803        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
1804
1805        parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
1806        subject = parsed.subject
1807        issuer = parsed.issuer
1808
1809        def read_next_rdn_value_tag(reader):
1810            # Assume each RDN has a single attribute.
1811            with reader.read_element(SET) as rdn:
1812                attribute = rdn.read_element(SEQUENCE)
1813
1814            with attribute:
1815                _ = attribute.read_element(OBJECT_IDENTIFIER)
1816                tag, value = attribute.read_any_element()
1817                return tag
1818
1819        # Check that each value was encoded as an ASN.1 PRINTABLESTRING.
1820        assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING
1821        assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING
1822        if (
1823            # This only works correctly in OpenSSL 1.1.0f+ and 1.0.2l+
1824            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER
1825        ):
1826            assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING
1827            assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING
1828
1829
1830class TestCertificateBuilder(object):
1831    @pytest.mark.requires_backend_interface(interface=RSABackend)
1832    @pytest.mark.requires_backend_interface(interface=X509Backend)
1833    def test_checks_for_unsupported_extensions(self, backend):
1834        private_key = RSA_KEY_2048.private_key(backend)
1835        builder = (
1836            x509.CertificateBuilder()
1837            .subject_name(
1838                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1839            )
1840            .issuer_name(
1841                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1842            )
1843            .public_key(private_key.public_key())
1844            .serial_number(777)
1845            .not_valid_before(datetime.datetime(1999, 1, 1))
1846            .not_valid_after(datetime.datetime(2020, 1, 1))
1847            .add_extension(DummyExtension(), False)
1848        )
1849
1850        with pytest.raises(NotImplementedError):
1851            builder.sign(private_key, hashes.SHA1(), backend)
1852
1853    @pytest.mark.requires_backend_interface(interface=RSABackend)
1854    @pytest.mark.requires_backend_interface(interface=X509Backend)
1855    def test_encode_nonstandard_aia(self, backend):
1856        private_key = RSA_KEY_2048.private_key(backend)
1857
1858        aia = x509.AuthorityInformationAccess(
1859            [
1860                x509.AccessDescription(
1861                    x509.ObjectIdentifier("2.999.7"),
1862                    x509.UniformResourceIdentifier(u"http://example.com"),
1863                ),
1864            ]
1865        )
1866
1867        builder = (
1868            x509.CertificateBuilder()
1869            .subject_name(
1870                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1871            )
1872            .issuer_name(
1873                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1874            )
1875            .public_key(private_key.public_key())
1876            .serial_number(777)
1877            .not_valid_before(datetime.datetime(1999, 1, 1))
1878            .not_valid_after(datetime.datetime(2020, 1, 1))
1879            .add_extension(aia, False)
1880        )
1881
1882        builder.sign(private_key, hashes.SHA256(), backend)
1883
1884    @pytest.mark.requires_backend_interface(interface=RSABackend)
1885    @pytest.mark.requires_backend_interface(interface=X509Backend)
1886    def test_encode_nonstandard_sia(self, backend):
1887        private_key = RSA_KEY_2048.private_key(backend)
1888
1889        sia = x509.SubjectInformationAccess(
1890            [
1891                x509.AccessDescription(
1892                    x509.ObjectIdentifier("2.999.7"),
1893                    x509.UniformResourceIdentifier(u"http://example.com"),
1894                ),
1895            ]
1896        )
1897
1898        builder = (
1899            x509.CertificateBuilder()
1900            .subject_name(
1901                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1902            )
1903            .issuer_name(
1904                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1905            )
1906            .public_key(private_key.public_key())
1907            .serial_number(777)
1908            .not_valid_before(datetime.datetime(2015, 1, 1))
1909            .not_valid_after(datetime.datetime(2040, 1, 1))
1910            .add_extension(sia, False)
1911        )
1912
1913        cert = builder.sign(private_key, hashes.SHA256(), backend)
1914        ext = cert.extensions.get_extension_for_oid(
1915            ExtensionOID.SUBJECT_INFORMATION_ACCESS
1916        )
1917        assert ext.value == sia
1918
1919    @pytest.mark.requires_backend_interface(interface=RSABackend)
1920    @pytest.mark.requires_backend_interface(interface=X509Backend)
1921    def test_subject_dn_asn1_types(self, backend):
1922        private_key = RSA_KEY_2048.private_key(backend)
1923
1924        name = x509.Name(
1925            [
1926                x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
1927                x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
1928                x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"),
1929                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"value"),
1930                x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"),
1931                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"value"),
1932                x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"),
1933                x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"),
1934                x509.NameAttribute(NameOID.SURNAME, u"value"),
1935                x509.NameAttribute(NameOID.GIVEN_NAME, u"value"),
1936                x509.NameAttribute(NameOID.TITLE, u"value"),
1937                x509.NameAttribute(NameOID.GENERATION_QUALIFIER, u"value"),
1938                x509.NameAttribute(NameOID.X500_UNIQUE_IDENTIFIER, u"value"),
1939                x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"),
1940                x509.NameAttribute(NameOID.PSEUDONYM, u"value"),
1941                x509.NameAttribute(NameOID.USER_ID, u"value"),
1942                x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"),
1943                x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"),
1944                x509.NameAttribute(NameOID.JURISDICTION_COUNTRY_NAME, u"US"),
1945                x509.NameAttribute(
1946                    NameOID.JURISDICTION_LOCALITY_NAME, u"value"
1947                ),
1948                x509.NameAttribute(
1949                    NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, u"value"
1950                ),
1951                x509.NameAttribute(NameOID.BUSINESS_CATEGORY, u"value"),
1952                x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
1953                x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
1954            ]
1955        )
1956        cert = (
1957            x509.CertificateBuilder()
1958            .subject_name(name)
1959            .issuer_name(name)
1960            .public_key(private_key.public_key())
1961            .serial_number(777)
1962            .not_valid_before(datetime.datetime(1999, 1, 1))
1963            .not_valid_after(datetime.datetime(2020, 1, 1))
1964            .sign(private_key, hashes.SHA256(), backend)
1965        )
1966
1967        for dn in (cert.subject, cert.issuer):
1968            for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
1969                assert dn.get_attributes_for_oid(oid)[0]._type == asn1_type
1970
1971    @pytest.mark.parametrize(
1972        ("not_valid_before", "not_valid_after"),
1973        [
1974            [datetime.datetime(1970, 2, 1), datetime.datetime(9999, 1, 1)],
1975            [datetime.datetime(1970, 2, 1), datetime.datetime(9999, 12, 31)],
1976        ],
1977    )
1978    @pytest.mark.requires_backend_interface(interface=RSABackend)
1979    @pytest.mark.requires_backend_interface(interface=X509Backend)
1980    def test_extreme_times(self, not_valid_before, not_valid_after, backend):
1981        private_key = RSA_KEY_2048.private_key(backend)
1982        builder = (
1983            x509.CertificateBuilder()
1984            .subject_name(
1985                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1986            )
1987            .issuer_name(
1988                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
1989            )
1990            .public_key(private_key.public_key())
1991            .serial_number(777)
1992            .not_valid_before(not_valid_before)
1993            .not_valid_after(not_valid_after)
1994        )
1995        cert = builder.sign(private_key, hashes.SHA256(), backend)
1996        assert cert.not_valid_before == not_valid_before
1997        assert cert.not_valid_after == not_valid_after
1998        parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
1999        assert parsed.not_before_tag == UTC_TIME
2000        assert parsed.not_after_tag == GENERALIZED_TIME
2001
2002    @pytest.mark.requires_backend_interface(interface=RSABackend)
2003    @pytest.mark.requires_backend_interface(interface=X509Backend)
2004    def test_no_subject_name(self, backend):
2005        subject_private_key = RSA_KEY_2048.private_key(backend)
2006        builder = (
2007            x509.CertificateBuilder()
2008            .serial_number(777)
2009            .issuer_name(
2010                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2011            )
2012            .public_key(subject_private_key.public_key())
2013            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2014            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2015        )
2016        with pytest.raises(ValueError):
2017            builder.sign(subject_private_key, hashes.SHA256(), backend)
2018
2019    @pytest.mark.requires_backend_interface(interface=RSABackend)
2020    @pytest.mark.requires_backend_interface(interface=X509Backend)
2021    def test_no_issuer_name(self, backend):
2022        subject_private_key = RSA_KEY_2048.private_key(backend)
2023        builder = (
2024            x509.CertificateBuilder()
2025            .serial_number(777)
2026            .subject_name(
2027                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2028            )
2029            .public_key(subject_private_key.public_key())
2030            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2031            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2032        )
2033        with pytest.raises(ValueError):
2034            builder.sign(subject_private_key, hashes.SHA256(), backend)
2035
2036    @pytest.mark.requires_backend_interface(interface=RSABackend)
2037    @pytest.mark.requires_backend_interface(interface=X509Backend)
2038    def test_no_public_key(self, backend):
2039        subject_private_key = RSA_KEY_2048.private_key(backend)
2040        builder = (
2041            x509.CertificateBuilder()
2042            .serial_number(777)
2043            .issuer_name(
2044                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2045            )
2046            .subject_name(
2047                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2048            )
2049            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2050            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2051        )
2052        with pytest.raises(ValueError):
2053            builder.sign(subject_private_key, hashes.SHA256(), backend)
2054
2055    @pytest.mark.requires_backend_interface(interface=RSABackend)
2056    @pytest.mark.requires_backend_interface(interface=X509Backend)
2057    def test_no_not_valid_before(self, backend):
2058        subject_private_key = RSA_KEY_2048.private_key(backend)
2059        builder = (
2060            x509.CertificateBuilder()
2061            .serial_number(777)
2062            .issuer_name(
2063                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2064            )
2065            .subject_name(
2066                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2067            )
2068            .public_key(subject_private_key.public_key())
2069            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2070        )
2071        with pytest.raises(ValueError):
2072            builder.sign(subject_private_key, hashes.SHA256(), backend)
2073
2074    @pytest.mark.requires_backend_interface(interface=RSABackend)
2075    @pytest.mark.requires_backend_interface(interface=X509Backend)
2076    def test_no_not_valid_after(self, backend):
2077        subject_private_key = RSA_KEY_2048.private_key(backend)
2078        builder = (
2079            x509.CertificateBuilder()
2080            .serial_number(777)
2081            .issuer_name(
2082                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2083            )
2084            .subject_name(
2085                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2086            )
2087            .public_key(subject_private_key.public_key())
2088            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2089        )
2090        with pytest.raises(ValueError):
2091            builder.sign(subject_private_key, hashes.SHA256(), backend)
2092
2093    @pytest.mark.requires_backend_interface(interface=RSABackend)
2094    @pytest.mark.requires_backend_interface(interface=X509Backend)
2095    def test_no_serial_number(self, backend):
2096        subject_private_key = RSA_KEY_2048.private_key(backend)
2097        builder = (
2098            x509.CertificateBuilder()
2099            .issuer_name(
2100                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2101            )
2102            .subject_name(
2103                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2104            )
2105            .public_key(subject_private_key.public_key())
2106            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2107            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2108        )
2109        with pytest.raises(ValueError):
2110            builder.sign(subject_private_key, hashes.SHA256(), backend)
2111
2112    def test_issuer_name_must_be_a_name_type(self):
2113        builder = x509.CertificateBuilder()
2114
2115        with pytest.raises(TypeError):
2116            builder.issuer_name("subject")
2117
2118        with pytest.raises(TypeError):
2119            builder.issuer_name(object)
2120
2121    def test_issuer_name_may_only_be_set_once(self):
2122        name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2123        builder = x509.CertificateBuilder().issuer_name(name)
2124
2125        with pytest.raises(ValueError):
2126            builder.issuer_name(name)
2127
2128    def test_subject_name_must_be_a_name_type(self):
2129        builder = x509.CertificateBuilder()
2130
2131        with pytest.raises(TypeError):
2132            builder.subject_name("subject")
2133
2134        with pytest.raises(TypeError):
2135            builder.subject_name(object)
2136
2137    def test_subject_name_may_only_be_set_once(self):
2138        name = x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2139        builder = x509.CertificateBuilder().subject_name(name)
2140
2141        with pytest.raises(ValueError):
2142            builder.subject_name(name)
2143
2144    def test_not_valid_before_after_not_valid_after(self):
2145        builder = x509.CertificateBuilder()
2146
2147        builder = builder.not_valid_after(datetime.datetime(2002, 1, 1, 12, 1))
2148        with pytest.raises(ValueError):
2149            builder.not_valid_before(datetime.datetime(2003, 1, 1, 12, 1))
2150
2151    def test_not_valid_after_before_not_valid_before(self):
2152        builder = x509.CertificateBuilder()
2153
2154        builder = builder.not_valid_before(
2155            datetime.datetime(2002, 1, 1, 12, 1)
2156        )
2157        with pytest.raises(ValueError):
2158            builder.not_valid_after(datetime.datetime(2001, 1, 1, 12, 1))
2159
2160    @pytest.mark.requires_backend_interface(interface=RSABackend)
2161    @pytest.mark.requires_backend_interface(interface=X509Backend)
2162    def test_public_key_must_be_public_key(self, backend):
2163        private_key = RSA_KEY_2048.private_key(backend)
2164        builder = x509.CertificateBuilder()
2165
2166        with pytest.raises(TypeError):
2167            builder.public_key(private_key)
2168
2169    @pytest.mark.requires_backend_interface(interface=RSABackend)
2170    @pytest.mark.requires_backend_interface(interface=X509Backend)
2171    def test_public_key_may_only_be_set_once(self, backend):
2172        private_key = RSA_KEY_2048.private_key(backend)
2173        public_key = private_key.public_key()
2174        builder = x509.CertificateBuilder().public_key(public_key)
2175
2176        with pytest.raises(ValueError):
2177            builder.public_key(public_key)
2178
2179    def test_serial_number_must_be_an_integer_type(self):
2180        with pytest.raises(TypeError):
2181            x509.CertificateBuilder().serial_number(10.0)
2182
2183    def test_serial_number_must_be_non_negative(self):
2184        with pytest.raises(ValueError):
2185            x509.CertificateBuilder().serial_number(-1)
2186
2187    def test_serial_number_must_be_positive(self):
2188        with pytest.raises(ValueError):
2189            x509.CertificateBuilder().serial_number(0)
2190
2191    @pytest.mark.requires_backend_interface(interface=RSABackend)
2192    @pytest.mark.requires_backend_interface(interface=X509Backend)
2193    def test_minimal_serial_number(self, backend):
2194        subject_private_key = RSA_KEY_2048.private_key(backend)
2195        builder = (
2196            x509.CertificateBuilder()
2197            .serial_number(1)
2198            .subject_name(
2199                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
2200            )
2201            .issuer_name(
2202                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
2203            )
2204            .public_key(subject_private_key.public_key())
2205            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2206            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2207        )
2208        cert = builder.sign(subject_private_key, hashes.SHA256(), backend)
2209        assert cert.serial_number == 1
2210
2211    @pytest.mark.requires_backend_interface(interface=RSABackend)
2212    @pytest.mark.requires_backend_interface(interface=X509Backend)
2213    def test_biggest_serial_number(self, backend):
2214        subject_private_key = RSA_KEY_2048.private_key(backend)
2215        builder = (
2216            x509.CertificateBuilder()
2217            .serial_number((1 << 159) - 1)
2218            .subject_name(
2219                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
2220            )
2221            .issuer_name(
2222                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"RU")])
2223            )
2224            .public_key(subject_private_key.public_key())
2225            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2226            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
2227        )
2228        cert = builder.sign(subject_private_key, hashes.SHA256(), backend)
2229        assert cert.serial_number == (1 << 159) - 1
2230
2231    def test_serial_number_must_be_less_than_160_bits_long(self):
2232        with pytest.raises(ValueError):
2233            x509.CertificateBuilder().serial_number(1 << 159)
2234
2235    def test_serial_number_may_only_be_set_once(self):
2236        builder = x509.CertificateBuilder().serial_number(10)
2237
2238        with pytest.raises(ValueError):
2239            builder.serial_number(20)
2240
2241    @pytest.mark.requires_backend_interface(interface=RSABackend)
2242    @pytest.mark.requires_backend_interface(interface=X509Backend)
2243    def test_aware_not_valid_after(self, backend):
2244        time = datetime.datetime(2012, 1, 16, 22, 43)
2245        tz = pytz.timezone("US/Pacific")
2246        time = tz.localize(time)
2247        utc_time = datetime.datetime(2012, 1, 17, 6, 43)
2248        private_key = RSA_KEY_2048.private_key(backend)
2249        cert_builder = x509.CertificateBuilder().not_valid_after(time)
2250        cert_builder = (
2251            cert_builder.subject_name(
2252                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2253            )
2254            .issuer_name(
2255                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2256            )
2257            .serial_number(1)
2258            .public_key(private_key.public_key())
2259            .not_valid_before(utc_time - datetime.timedelta(days=365))
2260        )
2261
2262        cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
2263        assert cert.not_valid_after == utc_time
2264
2265    @pytest.mark.requires_backend_interface(interface=RSABackend)
2266    @pytest.mark.requires_backend_interface(interface=X509Backend)
2267    def test_earliest_time(self, backend):
2268        time = datetime.datetime(1950, 1, 1)
2269        private_key = RSA_KEY_2048.private_key(backend)
2270        cert_builder = (
2271            x509.CertificateBuilder()
2272            .subject_name(
2273                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2274            )
2275            .issuer_name(
2276                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2277            )
2278            .serial_number(1)
2279            .public_key(private_key.public_key())
2280            .not_valid_before(time)
2281            .not_valid_after(time)
2282        )
2283        cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
2284        assert cert.not_valid_before == time
2285        assert cert.not_valid_after == time
2286        parsed = _parse_cert(cert.public_bytes(serialization.Encoding.DER))
2287        assert parsed.not_before_tag == UTC_TIME
2288        assert parsed.not_after_tag == UTC_TIME
2289
2290    def test_invalid_not_valid_after(self):
2291        with pytest.raises(TypeError):
2292            x509.CertificateBuilder().not_valid_after(104204304504)
2293
2294        with pytest.raises(TypeError):
2295            x509.CertificateBuilder().not_valid_after(datetime.time())
2296
2297        with pytest.raises(ValueError):
2298            x509.CertificateBuilder().not_valid_after(
2299                datetime.datetime(1940, 8, 10)
2300            )
2301
2302    def test_not_valid_after_may_only_be_set_once(self):
2303        builder = x509.CertificateBuilder().not_valid_after(
2304            datetime.datetime.now()
2305        )
2306
2307        with pytest.raises(ValueError):
2308            builder.not_valid_after(datetime.datetime.now())
2309
2310    @pytest.mark.requires_backend_interface(interface=RSABackend)
2311    @pytest.mark.requires_backend_interface(interface=X509Backend)
2312    def test_aware_not_valid_before(self, backend):
2313        time = datetime.datetime(2012, 1, 16, 22, 43)
2314        tz = pytz.timezone("US/Pacific")
2315        time = tz.localize(time)
2316        utc_time = datetime.datetime(2012, 1, 17, 6, 43)
2317        private_key = RSA_KEY_2048.private_key(backend)
2318        cert_builder = x509.CertificateBuilder().not_valid_before(time)
2319        cert_builder = (
2320            cert_builder.subject_name(
2321                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2322            )
2323            .issuer_name(
2324                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2325            )
2326            .serial_number(1)
2327            .public_key(private_key.public_key())
2328            .not_valid_after(utc_time + datetime.timedelta(days=366))
2329        )
2330
2331        cert = cert_builder.sign(private_key, hashes.SHA256(), backend)
2332        assert cert.not_valid_before == utc_time
2333
2334    def test_invalid_not_valid_before(self):
2335        with pytest.raises(TypeError):
2336            x509.CertificateBuilder().not_valid_before(104204304504)
2337
2338        with pytest.raises(TypeError):
2339            x509.CertificateBuilder().not_valid_before(datetime.time())
2340
2341        with pytest.raises(ValueError):
2342            x509.CertificateBuilder().not_valid_before(
2343                datetime.datetime(1940, 8, 10)
2344            )
2345
2346    def test_not_valid_before_may_only_be_set_once(self):
2347        builder = x509.CertificateBuilder().not_valid_before(
2348            datetime.datetime.now()
2349        )
2350
2351        with pytest.raises(ValueError):
2352            builder.not_valid_before(datetime.datetime.now())
2353
2354    def test_add_extension_checks_for_duplicates(self):
2355        builder = x509.CertificateBuilder().add_extension(
2356            x509.BasicConstraints(ca=False, path_length=None),
2357            True,
2358        )
2359
2360        with pytest.raises(ValueError):
2361            builder.add_extension(
2362                x509.BasicConstraints(ca=False, path_length=None),
2363                True,
2364            )
2365
2366    def test_add_invalid_extension_type(self):
2367        builder = x509.CertificateBuilder()
2368
2369        with pytest.raises(TypeError):
2370            builder.add_extension(object(), False)
2371
2372    @pytest.mark.requires_backend_interface(interface=RSABackend)
2373    @pytest.mark.requires_backend_interface(interface=X509Backend)
2374    @pytest.mark.parametrize("algorithm", [object(), None])
2375    def test_sign_with_unsupported_hash(self, algorithm, backend):
2376        private_key = RSA_KEY_2048.private_key(backend)
2377        builder = x509.CertificateBuilder()
2378        builder = (
2379            builder.subject_name(
2380                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2381            )
2382            .issuer_name(
2383                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2384            )
2385            .serial_number(1)
2386            .public_key(private_key.public_key())
2387            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2388            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
2389        )
2390
2391        with pytest.raises(TypeError):
2392            builder.sign(private_key, algorithm, backend)
2393
2394    @pytest.mark.supported(
2395        only_if=lambda backend: backend.ed25519_supported(),
2396        skip_message="Requires OpenSSL with Ed25519 support",
2397    )
2398    @pytest.mark.requires_backend_interface(interface=X509Backend)
2399    def test_sign_with_unsupported_hash_ed25519(self, backend):
2400        private_key = ed25519.Ed25519PrivateKey.generate()
2401        builder = (
2402            x509.CertificateBuilder()
2403            .subject_name(
2404                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2405            )
2406            .issuer_name(
2407                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2408            )
2409            .serial_number(1)
2410            .public_key(private_key.public_key())
2411            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2412            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
2413        )
2414
2415        with pytest.raises(ValueError):
2416            builder.sign(private_key, hashes.SHA256(), backend)
2417
2418    @pytest.mark.supported(
2419        only_if=lambda backend: backend.ed448_supported(),
2420        skip_message="Requires OpenSSL with Ed448 support",
2421    )
2422    @pytest.mark.requires_backend_interface(interface=X509Backend)
2423    def test_sign_with_unsupported_hash_ed448(self, backend):
2424        private_key = ed448.Ed448PrivateKey.generate()
2425        builder = (
2426            x509.CertificateBuilder()
2427            .subject_name(
2428                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2429            )
2430            .issuer_name(
2431                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2432            )
2433            .serial_number(1)
2434            .public_key(private_key.public_key())
2435            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2436            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
2437        )
2438
2439        with pytest.raises(ValueError):
2440            builder.sign(private_key, hashes.SHA256(), backend)
2441
2442    @pytest.mark.requires_backend_interface(interface=RSABackend)
2443    @pytest.mark.requires_backend_interface(interface=X509Backend)
2444    @pytest.mark.supported(
2445        only_if=lambda backend: backend.hash_supported(hashes.MD5()),
2446        skip_message="Requires OpenSSL with MD5 support",
2447    )
2448    def test_sign_rsa_with_md5(self, backend):
2449        private_key = RSA_KEY_2048.private_key(backend)
2450        builder = x509.CertificateBuilder()
2451        builder = (
2452            builder.subject_name(
2453                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2454            )
2455            .issuer_name(
2456                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2457            )
2458            .serial_number(1)
2459            .public_key(private_key.public_key())
2460            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2461            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
2462        )
2463        cert = builder.sign(private_key, hashes.MD5(), backend)
2464        assert isinstance(cert.signature_hash_algorithm, hashes.MD5)
2465
2466    @pytest.mark.requires_backend_interface(interface=DSABackend)
2467    @pytest.mark.requires_backend_interface(interface=X509Backend)
2468    @pytest.mark.supported(
2469        only_if=lambda backend: backend.hash_supported(hashes.MD5()),
2470        skip_message="Requires OpenSSL with MD5 support",
2471    )
2472    def test_sign_dsa_with_md5(self, backend):
2473        private_key = DSA_KEY_2048.private_key(backend)
2474        builder = x509.CertificateBuilder()
2475        builder = (
2476            builder.subject_name(
2477                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2478            )
2479            .issuer_name(
2480                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2481            )
2482            .serial_number(1)
2483            .public_key(private_key.public_key())
2484            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2485            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
2486        )
2487        with pytest.raises(ValueError):
2488            builder.sign(private_key, hashes.MD5(), backend)
2489
2490    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
2491    @pytest.mark.requires_backend_interface(interface=X509Backend)
2492    @pytest.mark.supported(
2493        only_if=lambda backend: backend.hash_supported(hashes.MD5()),
2494        skip_message="Requires OpenSSL with MD5 support",
2495    )
2496    def test_sign_ec_with_md5(self, backend):
2497        _skip_curve_unsupported(backend, ec.SECP256R1())
2498        private_key = EC_KEY_SECP256R1.private_key(backend)
2499        builder = x509.CertificateBuilder()
2500        builder = (
2501            builder.subject_name(
2502                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2503            )
2504            .issuer_name(
2505                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2506            )
2507            .serial_number(1)
2508            .public_key(private_key.public_key())
2509            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
2510            .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1))
2511        )
2512        with pytest.raises(ValueError):
2513            builder.sign(private_key, hashes.MD5(), backend)
2514
2515    @pytest.mark.requires_backend_interface(interface=DSABackend)
2516    @pytest.mark.requires_backend_interface(interface=X509Backend)
2517    def test_build_cert_with_dsa_private_key(self, backend):
2518        issuer_private_key = DSA_KEY_2048.private_key(backend)
2519        subject_private_key = DSA_KEY_2048.private_key(backend)
2520
2521        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2522        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2523
2524        builder = (
2525            x509.CertificateBuilder()
2526            .serial_number(777)
2527            .issuer_name(
2528                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2529            )
2530            .subject_name(
2531                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2532            )
2533            .public_key(subject_private_key.public_key())
2534            .add_extension(
2535                x509.BasicConstraints(ca=False, path_length=None),
2536                True,
2537            )
2538            .add_extension(
2539                x509.SubjectAlternativeName(
2540                    [x509.DNSName(u"cryptography.io")]
2541                ),
2542                critical=False,
2543            )
2544            .not_valid_before(not_valid_before)
2545            .not_valid_after(not_valid_after)
2546        )
2547
2548        cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
2549
2550        assert cert.version is x509.Version.v3
2551        assert cert.not_valid_before == not_valid_before
2552        assert cert.not_valid_after == not_valid_after
2553        basic_constraints = cert.extensions.get_extension_for_oid(
2554            ExtensionOID.BASIC_CONSTRAINTS
2555        )
2556        assert basic_constraints.value.ca is False
2557        assert basic_constraints.value.path_length is None
2558        subject_alternative_name = cert.extensions.get_extension_for_oid(
2559            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2560        )
2561        assert list(subject_alternative_name.value) == [
2562            x509.DNSName(u"cryptography.io"),
2563        ]
2564
2565    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
2566    @pytest.mark.requires_backend_interface(interface=X509Backend)
2567    def test_build_cert_with_ec_private_key(self, backend):
2568        _skip_curve_unsupported(backend, ec.SECP256R1())
2569        issuer_private_key = ec.generate_private_key(ec.SECP256R1(), backend)
2570        subject_private_key = ec.generate_private_key(ec.SECP256R1(), backend)
2571
2572        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2573        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2574
2575        builder = (
2576            x509.CertificateBuilder()
2577            .serial_number(777)
2578            .issuer_name(
2579                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2580            )
2581            .subject_name(
2582                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2583            )
2584            .public_key(subject_private_key.public_key())
2585            .add_extension(
2586                x509.BasicConstraints(ca=False, path_length=None),
2587                True,
2588            )
2589            .add_extension(
2590                x509.SubjectAlternativeName(
2591                    [x509.DNSName(u"cryptography.io")]
2592                ),
2593                critical=False,
2594            )
2595            .not_valid_before(not_valid_before)
2596            .not_valid_after(not_valid_after)
2597        )
2598
2599        cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
2600
2601        assert cert.version is x509.Version.v3
2602        assert cert.not_valid_before == not_valid_before
2603        assert cert.not_valid_after == not_valid_after
2604        basic_constraints = cert.extensions.get_extension_for_oid(
2605            ExtensionOID.BASIC_CONSTRAINTS
2606        )
2607        assert basic_constraints.value.ca is False
2608        assert basic_constraints.value.path_length is None
2609        subject_alternative_name = cert.extensions.get_extension_for_oid(
2610            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2611        )
2612        assert list(subject_alternative_name.value) == [
2613            x509.DNSName(u"cryptography.io"),
2614        ]
2615
2616    @pytest.mark.supported(
2617        only_if=lambda backend: backend.ed25519_supported(),
2618        skip_message="Requires OpenSSL with Ed25519 support",
2619    )
2620    @pytest.mark.requires_backend_interface(interface=X509Backend)
2621    def test_build_cert_with_ed25519(self, backend):
2622        issuer_private_key = ed25519.Ed25519PrivateKey.generate()
2623        subject_private_key = ed25519.Ed25519PrivateKey.generate()
2624
2625        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2626        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2627
2628        builder = (
2629            x509.CertificateBuilder()
2630            .serial_number(777)
2631            .issuer_name(
2632                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2633            )
2634            .subject_name(
2635                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2636            )
2637            .public_key(subject_private_key.public_key())
2638            .add_extension(
2639                x509.BasicConstraints(ca=False, path_length=None),
2640                True,
2641            )
2642            .add_extension(
2643                x509.SubjectAlternativeName(
2644                    [x509.DNSName(u"cryptography.io")]
2645                ),
2646                critical=False,
2647            )
2648            .not_valid_before(not_valid_before)
2649            .not_valid_after(not_valid_after)
2650        )
2651
2652        cert = builder.sign(issuer_private_key, None, backend)
2653        issuer_private_key.public_key().verify(
2654            cert.signature, cert.tbs_certificate_bytes
2655        )
2656        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
2657        assert cert.signature_hash_algorithm is None
2658        assert isinstance(cert.public_key(), ed25519.Ed25519PublicKey)
2659        assert cert.version is x509.Version.v3
2660        assert cert.not_valid_before == not_valid_before
2661        assert cert.not_valid_after == not_valid_after
2662        basic_constraints = cert.extensions.get_extension_for_oid(
2663            ExtensionOID.BASIC_CONSTRAINTS
2664        )
2665        assert basic_constraints.value.ca is False
2666        assert basic_constraints.value.path_length is None
2667        subject_alternative_name = cert.extensions.get_extension_for_oid(
2668            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2669        )
2670        assert list(subject_alternative_name.value) == [
2671            x509.DNSName(u"cryptography.io"),
2672        ]
2673
2674    @pytest.mark.supported(
2675        only_if=lambda backend: backend.ed25519_supported(),
2676        skip_message="Requires OpenSSL with Ed25519 support",
2677    )
2678    @pytest.mark.requires_backend_interface(interface=X509Backend)
2679    @pytest.mark.requires_backend_interface(interface=RSABackend)
2680    def test_build_cert_with_public_ed25519_rsa_sig(self, backend):
2681        issuer_private_key = RSA_KEY_2048.private_key(backend)
2682        subject_private_key = ed25519.Ed25519PrivateKey.generate()
2683
2684        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2685        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2686
2687        builder = (
2688            x509.CertificateBuilder()
2689            .serial_number(777)
2690            .issuer_name(
2691                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2692            )
2693            .subject_name(
2694                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2695            )
2696            .public_key(subject_private_key.public_key())
2697            .not_valid_before(not_valid_before)
2698            .not_valid_after(not_valid_after)
2699        )
2700
2701        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
2702        issuer_private_key.public_key().verify(
2703            cert.signature,
2704            cert.tbs_certificate_bytes,
2705            padding.PKCS1v15(),
2706            cert.signature_hash_algorithm,
2707        )
2708        assert cert.signature_algorithm_oid == (
2709            SignatureAlgorithmOID.RSA_WITH_SHA256
2710        )
2711        assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)
2712        assert isinstance(cert.public_key(), ed25519.Ed25519PublicKey)
2713
2714    @pytest.mark.supported(
2715        only_if=lambda backend: backend.ed448_supported(),
2716        skip_message="Requires OpenSSL with Ed448 support",
2717    )
2718    @pytest.mark.requires_backend_interface(interface=X509Backend)
2719    def test_build_cert_with_ed448(self, backend):
2720        issuer_private_key = ed448.Ed448PrivateKey.generate()
2721        subject_private_key = ed448.Ed448PrivateKey.generate()
2722
2723        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2724        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2725
2726        builder = (
2727            x509.CertificateBuilder()
2728            .serial_number(777)
2729            .issuer_name(
2730                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2731            )
2732            .subject_name(
2733                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2734            )
2735            .public_key(subject_private_key.public_key())
2736            .add_extension(
2737                x509.BasicConstraints(ca=False, path_length=None),
2738                True,
2739            )
2740            .add_extension(
2741                x509.SubjectAlternativeName(
2742                    [x509.DNSName(u"cryptography.io")]
2743                ),
2744                critical=False,
2745            )
2746            .not_valid_before(not_valid_before)
2747            .not_valid_after(not_valid_after)
2748        )
2749
2750        cert = builder.sign(issuer_private_key, None, backend)
2751        issuer_private_key.public_key().verify(
2752            cert.signature, cert.tbs_certificate_bytes
2753        )
2754        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448
2755        assert cert.signature_hash_algorithm is None
2756        assert isinstance(cert.public_key(), ed448.Ed448PublicKey)
2757        assert cert.version is x509.Version.v3
2758        assert cert.not_valid_before == not_valid_before
2759        assert cert.not_valid_after == not_valid_after
2760        basic_constraints = cert.extensions.get_extension_for_oid(
2761            ExtensionOID.BASIC_CONSTRAINTS
2762        )
2763        assert basic_constraints.value.ca is False
2764        assert basic_constraints.value.path_length is None
2765        subject_alternative_name = cert.extensions.get_extension_for_oid(
2766            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2767        )
2768        assert list(subject_alternative_name.value) == [
2769            x509.DNSName(u"cryptography.io"),
2770        ]
2771
2772    @pytest.mark.supported(
2773        only_if=lambda backend: backend.ed448_supported(),
2774        skip_message="Requires OpenSSL with Ed448 support",
2775    )
2776    @pytest.mark.requires_backend_interface(interface=X509Backend)
2777    @pytest.mark.requires_backend_interface(interface=RSABackend)
2778    def test_build_cert_with_public_ed448_rsa_sig(self, backend):
2779        issuer_private_key = RSA_KEY_2048.private_key(backend)
2780        subject_private_key = ed448.Ed448PrivateKey.generate()
2781
2782        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2783        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2784
2785        builder = (
2786            x509.CertificateBuilder()
2787            .serial_number(777)
2788            .issuer_name(
2789                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2790            )
2791            .subject_name(
2792                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2793            )
2794            .public_key(subject_private_key.public_key())
2795            .not_valid_before(not_valid_before)
2796            .not_valid_after(not_valid_after)
2797        )
2798
2799        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
2800        issuer_private_key.public_key().verify(
2801            cert.signature,
2802            cert.tbs_certificate_bytes,
2803            padding.PKCS1v15(),
2804            cert.signature_hash_algorithm,
2805        )
2806        assert cert.signature_algorithm_oid == (
2807            SignatureAlgorithmOID.RSA_WITH_SHA256
2808        )
2809        assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)
2810        assert isinstance(cert.public_key(), ed448.Ed448PublicKey)
2811
2812    @pytest.mark.requires_backend_interface(interface=RSABackend)
2813    @pytest.mark.requires_backend_interface(interface=X509Backend)
2814    def test_build_cert_with_rsa_key_too_small(self, backend):
2815        issuer_private_key = RSA_KEY_512.private_key(backend)
2816        subject_private_key = RSA_KEY_512.private_key(backend)
2817
2818        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
2819        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
2820
2821        builder = (
2822            x509.CertificateBuilder()
2823            .serial_number(777)
2824            .issuer_name(
2825                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2826            )
2827            .subject_name(
2828                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
2829            )
2830            .public_key(subject_private_key.public_key())
2831            .not_valid_before(not_valid_before)
2832            .not_valid_after(not_valid_after)
2833        )
2834
2835        with pytest.raises(ValueError):
2836            builder.sign(issuer_private_key, hashes.SHA512(), backend)
2837
2838    @pytest.mark.requires_backend_interface(interface=RSABackend)
2839    @pytest.mark.requires_backend_interface(interface=X509Backend)
2840    @pytest.mark.parametrize(
2841        "add_ext",
2842        [
2843            x509.SubjectAlternativeName(
2844                [
2845                    # These examples exist to verify compatibility with
2846                    # certificates that have utf8 encoded data in the ia5string
2847                    x509.DNSName._init_without_validation(u"a\xedt\xe1s.test"),
2848                    x509.RFC822Name._init_without_validation(
2849                        u"test@a\xedt\xe1s.test"
2850                    ),
2851                    x509.UniformResourceIdentifier._init_without_validation(
2852                        u"http://a\xedt\xe1s.test"
2853                    ),
2854                ]
2855            ),
2856            x509.CertificatePolicies(
2857                [
2858                    x509.PolicyInformation(
2859                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
2860                        [u"http://other.com/cps"],
2861                    )
2862                ]
2863            ),
2864            x509.CertificatePolicies(
2865                [
2866                    x509.PolicyInformation(
2867                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
2868                        None,
2869                    )
2870                ]
2871            ),
2872            x509.CertificatePolicies(
2873                [
2874                    x509.PolicyInformation(
2875                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
2876                        [
2877                            u"http://example.com/cps",
2878                            u"http://other.com/cps",
2879                            x509.UserNotice(
2880                                x509.NoticeReference(u"my org", [1, 2, 3, 4]),
2881                                u"thing",
2882                            ),
2883                        ],
2884                    )
2885                ]
2886            ),
2887            x509.CertificatePolicies(
2888                [
2889                    x509.PolicyInformation(
2890                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
2891                        [
2892                            u"http://example.com/cps",
2893                            x509.UserNotice(
2894                                x509.NoticeReference(
2895                                    u"UTF8\u2122'", [1, 2, 3, 4]
2896                                ),
2897                                u"We heart UTF8!\u2122",
2898                            ),
2899                        ],
2900                    )
2901                ]
2902            ),
2903            x509.CertificatePolicies(
2904                [
2905                    x509.PolicyInformation(
2906                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
2907                        [x509.UserNotice(None, u"thing")],
2908                    )
2909                ]
2910            ),
2911            x509.CertificatePolicies(
2912                [
2913                    x509.PolicyInformation(
2914                        x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
2915                        [
2916                            x509.UserNotice(
2917                                x509.NoticeReference(u"my org", [1, 2, 3, 4]),
2918                                None,
2919                            )
2920                        ],
2921                    )
2922                ]
2923            ),
2924            x509.IssuerAlternativeName(
2925                [
2926                    x509.DNSName(u"myissuer"),
2927                    x509.RFC822Name(u"email@domain.com"),
2928                ]
2929            ),
2930            x509.ExtendedKeyUsage(
2931                [
2932                    ExtendedKeyUsageOID.CLIENT_AUTH,
2933                    ExtendedKeyUsageOID.SERVER_AUTH,
2934                    ExtendedKeyUsageOID.CODE_SIGNING,
2935                ]
2936            ),
2937            x509.InhibitAnyPolicy(3),
2938            x509.TLSFeature([x509.TLSFeatureType.status_request]),
2939            x509.TLSFeature([x509.TLSFeatureType.status_request_v2]),
2940            x509.TLSFeature(
2941                [
2942                    x509.TLSFeatureType.status_request,
2943                    x509.TLSFeatureType.status_request_v2,
2944                ]
2945            ),
2946            x509.NameConstraints(
2947                permitted_subtrees=[
2948                    x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")),
2949                    x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/29")),
2950                    x509.IPAddress(ipaddress.IPv4Network(u"127.0.0.1/32")),
2951                    x509.IPAddress(ipaddress.IPv4Network(u"8.0.0.0/8")),
2952                    x509.IPAddress(ipaddress.IPv4Network(u"0.0.0.0/0")),
2953                    x509.IPAddress(
2954                        ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/96")
2955                    ),
2956                    x509.IPAddress(
2957                        ipaddress.IPv6Network(u"FF:FF:0:0:0:0:0:0/128")
2958                    ),
2959                ],
2960                excluded_subtrees=[x509.DNSName(u"name.local")],
2961            ),
2962            x509.NameConstraints(
2963                permitted_subtrees=[
2964                    x509.IPAddress(ipaddress.IPv4Network(u"0.0.0.0/0")),
2965                ],
2966                excluded_subtrees=None,
2967            ),
2968            x509.NameConstraints(
2969                permitted_subtrees=None,
2970                excluded_subtrees=[x509.DNSName(u"name.local")],
2971            ),
2972            x509.PolicyConstraints(
2973                require_explicit_policy=None, inhibit_policy_mapping=1
2974            ),
2975            x509.PolicyConstraints(
2976                require_explicit_policy=3, inhibit_policy_mapping=1
2977            ),
2978            x509.PolicyConstraints(
2979                require_explicit_policy=0, inhibit_policy_mapping=None
2980            ),
2981            x509.CRLDistributionPoints(
2982                [
2983                    x509.DistributionPoint(
2984                        full_name=None,
2985                        relative_name=x509.RelativeDistinguishedName(
2986                            [
2987                                x509.NameAttribute(
2988                                    NameOID.COMMON_NAME,
2989                                    u"indirect CRL for indirectCRL CA3",
2990                                ),
2991                            ]
2992                        ),
2993                        reasons=None,
2994                        crl_issuer=[
2995                            x509.DirectoryName(
2996                                x509.Name(
2997                                    [
2998                                        x509.NameAttribute(
2999                                            NameOID.COUNTRY_NAME, u"US"
3000                                        ),
3001                                        x509.NameAttribute(
3002                                            NameOID.ORGANIZATION_NAME,
3003                                            u"Test Certificates 2011",
3004                                        ),
3005                                        x509.NameAttribute(
3006                                            NameOID.ORGANIZATIONAL_UNIT_NAME,
3007                                            u"indirectCRL CA3 cRLIssuer",
3008                                        ),
3009                                    ]
3010                                )
3011                            )
3012                        ],
3013                    )
3014                ]
3015            ),
3016            x509.CRLDistributionPoints(
3017                [
3018                    x509.DistributionPoint(
3019                        full_name=[
3020                            x509.DirectoryName(
3021                                x509.Name(
3022                                    [
3023                                        x509.NameAttribute(
3024                                            NameOID.COUNTRY_NAME, u"US"
3025                                        ),
3026                                    ]
3027                                )
3028                            )
3029                        ],
3030                        relative_name=None,
3031                        reasons=None,
3032                        crl_issuer=[
3033                            x509.DirectoryName(
3034                                x509.Name(
3035                                    [
3036                                        x509.NameAttribute(
3037                                            NameOID.ORGANIZATION_NAME,
3038                                            u"cryptography Testing",
3039                                        ),
3040                                    ]
3041                                )
3042                            )
3043                        ],
3044                    )
3045                ]
3046            ),
3047            x509.CRLDistributionPoints(
3048                [
3049                    x509.DistributionPoint(
3050                        full_name=[
3051                            x509.UniformResourceIdentifier(
3052                                u"http://myhost.com/myca.crl"
3053                            ),
3054                            x509.UniformResourceIdentifier(
3055                                u"http://backup.myhost.com/myca.crl"
3056                            ),
3057                        ],
3058                        relative_name=None,
3059                        reasons=frozenset(
3060                            [
3061                                x509.ReasonFlags.key_compromise,
3062                                x509.ReasonFlags.ca_compromise,
3063                            ]
3064                        ),
3065                        crl_issuer=[
3066                            x509.DirectoryName(
3067                                x509.Name(
3068                                    [
3069                                        x509.NameAttribute(
3070                                            NameOID.COUNTRY_NAME, u"US"
3071                                        ),
3072                                        x509.NameAttribute(
3073                                            NameOID.COMMON_NAME,
3074                                            u"cryptography CA",
3075                                        ),
3076                                    ]
3077                                )
3078                            )
3079                        ],
3080                    )
3081                ]
3082            ),
3083            x509.CRLDistributionPoints(
3084                [
3085                    x509.DistributionPoint(
3086                        full_name=[
3087                            x509.UniformResourceIdentifier(
3088                                u"http://domain.com/some.crl"
3089                            )
3090                        ],
3091                        relative_name=None,
3092                        reasons=frozenset(
3093                            [
3094                                x509.ReasonFlags.key_compromise,
3095                                x509.ReasonFlags.ca_compromise,
3096                                x509.ReasonFlags.affiliation_changed,
3097                                x509.ReasonFlags.superseded,
3098                                x509.ReasonFlags.privilege_withdrawn,
3099                                x509.ReasonFlags.cessation_of_operation,
3100                                x509.ReasonFlags.aa_compromise,
3101                                x509.ReasonFlags.certificate_hold,
3102                            ]
3103                        ),
3104                        crl_issuer=None,
3105                    )
3106                ]
3107            ),
3108            x509.CRLDistributionPoints(
3109                [
3110                    x509.DistributionPoint(
3111                        full_name=None,
3112                        relative_name=None,
3113                        reasons=None,
3114                        crl_issuer=[
3115                            x509.DirectoryName(
3116                                x509.Name(
3117                                    [
3118                                        x509.NameAttribute(
3119                                            NameOID.COMMON_NAME,
3120                                            u"cryptography CA",
3121                                        ),
3122                                    ]
3123                                )
3124                            )
3125                        ],
3126                    )
3127                ]
3128            ),
3129            x509.CRLDistributionPoints(
3130                [
3131                    x509.DistributionPoint(
3132                        full_name=[
3133                            x509.UniformResourceIdentifier(
3134                                u"http://domain.com/some.crl"
3135                            )
3136                        ],
3137                        relative_name=None,
3138                        reasons=frozenset([x509.ReasonFlags.aa_compromise]),
3139                        crl_issuer=None,
3140                    )
3141                ]
3142            ),
3143            x509.FreshestCRL(
3144                [
3145                    x509.DistributionPoint(
3146                        full_name=[
3147                            x509.UniformResourceIdentifier(
3148                                u"http://domain.com/some.crl"
3149                            )
3150                        ],
3151                        relative_name=None,
3152                        reasons=frozenset(
3153                            [
3154                                x509.ReasonFlags.key_compromise,
3155                                x509.ReasonFlags.ca_compromise,
3156                                x509.ReasonFlags.affiliation_changed,
3157                                x509.ReasonFlags.superseded,
3158                                x509.ReasonFlags.privilege_withdrawn,
3159                                x509.ReasonFlags.cessation_of_operation,
3160                                x509.ReasonFlags.aa_compromise,
3161                                x509.ReasonFlags.certificate_hold,
3162                            ]
3163                        ),
3164                        crl_issuer=None,
3165                    )
3166                ]
3167            ),
3168            x509.FreshestCRL(
3169                [
3170                    x509.DistributionPoint(
3171                        full_name=None,
3172                        relative_name=x509.RelativeDistinguishedName(
3173                            [
3174                                x509.NameAttribute(
3175                                    NameOID.COMMON_NAME,
3176                                    u"indirect CRL for indirectCRL CA3",
3177                                ),
3178                            ]
3179                        ),
3180                        reasons=None,
3181                        crl_issuer=None,
3182                    )
3183                ]
3184            ),
3185            x509.FreshestCRL(
3186                [
3187                    x509.DistributionPoint(
3188                        full_name=None,
3189                        relative_name=x509.RelativeDistinguishedName(
3190                            [
3191                                x509.NameAttribute(
3192                                    NameOID.COMMON_NAME,
3193                                    u"indirect CRL for indirectCRL CA3",
3194                                ),
3195                                x509.NameAttribute(
3196                                    NameOID.COUNTRY_NAME, u"US"
3197                                ),
3198                            ]
3199                        ),
3200                        reasons=None,
3201                        crl_issuer=None,
3202                    )
3203                ]
3204            ),
3205        ],
3206    )
3207    def test_ext(self, add_ext, backend):
3208        issuer_private_key = RSA_KEY_2048.private_key(backend)
3209        subject_private_key = RSA_KEY_2048.private_key(backend)
3210
3211        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
3212        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
3213
3214        cert = (
3215            x509.CertificateBuilder()
3216            .subject_name(
3217                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3218            )
3219            .issuer_name(
3220                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3221            )
3222            .not_valid_before(not_valid_before)
3223            .not_valid_after(not_valid_after)
3224            .public_key(subject_private_key.public_key())
3225            .serial_number(123)
3226            .add_extension(add_ext, critical=False)
3227            .sign(issuer_private_key, hashes.SHA256(), backend)
3228        )
3229
3230        ext = cert.extensions.get_extension_for_class(type(add_ext))
3231        assert ext.critical is False
3232        assert ext.value == add_ext
3233
3234    @pytest.mark.requires_backend_interface(interface=RSABackend)
3235    @pytest.mark.requires_backend_interface(interface=X509Backend)
3236    def test_key_usage(self, backend):
3237        issuer_private_key = RSA_KEY_2048.private_key(backend)
3238        subject_private_key = RSA_KEY_2048.private_key(backend)
3239
3240        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
3241        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
3242
3243        cert = (
3244            x509.CertificateBuilder()
3245            .subject_name(
3246                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3247            )
3248            .issuer_name(
3249                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3250            )
3251            .not_valid_before(not_valid_before)
3252            .not_valid_after(not_valid_after)
3253            .public_key(subject_private_key.public_key())
3254            .serial_number(123)
3255            .add_extension(
3256                x509.KeyUsage(
3257                    digital_signature=True,
3258                    content_commitment=True,
3259                    key_encipherment=False,
3260                    data_encipherment=False,
3261                    key_agreement=False,
3262                    key_cert_sign=True,
3263                    crl_sign=False,
3264                    encipher_only=False,
3265                    decipher_only=False,
3266                ),
3267                critical=False,
3268            )
3269            .sign(issuer_private_key, hashes.SHA256(), backend)
3270        )
3271
3272        ext = cert.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
3273        assert ext.critical is False
3274        assert ext.value == x509.KeyUsage(
3275            digital_signature=True,
3276            content_commitment=True,
3277            key_encipherment=False,
3278            data_encipherment=False,
3279            key_agreement=False,
3280            key_cert_sign=True,
3281            crl_sign=False,
3282            encipher_only=False,
3283            decipher_only=False,
3284        )
3285
3286    @pytest.mark.requires_backend_interface(interface=RSABackend)
3287    @pytest.mark.requires_backend_interface(interface=X509Backend)
3288    def test_build_ca_request_with_path_length_none(self, backend):
3289        private_key = RSA_KEY_2048.private_key(backend)
3290
3291        request = (
3292            x509.CertificateSigningRequestBuilder()
3293            .subject_name(
3294                x509.Name(
3295                    [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
3296                )
3297            )
3298            .add_extension(
3299                x509.BasicConstraints(ca=True, path_length=None), critical=True
3300            )
3301            .sign(private_key, hashes.SHA1(), backend)
3302        )
3303
3304        loaded_request = x509.load_pem_x509_csr(
3305            request.public_bytes(encoding=serialization.Encoding.PEM), backend
3306        )
3307        subject = loaded_request.subject
3308        assert isinstance(subject, x509.Name)
3309        basic_constraints = request.extensions.get_extension_for_oid(
3310            ExtensionOID.BASIC_CONSTRAINTS
3311        )
3312        assert basic_constraints.value.path_length is None
3313
3314    @pytest.mark.parametrize(
3315        "unrecognized",
3316        [
3317            x509.UnrecognizedExtension(
3318                x509.ObjectIdentifier("1.2.3.4.5"),
3319                b"abcdef",
3320            )
3321        ],
3322    )
3323    @pytest.mark.requires_backend_interface(interface=RSABackend)
3324    @pytest.mark.requires_backend_interface(interface=X509Backend)
3325    def test_unrecognized_extension(self, backend, unrecognized):
3326        private_key = RSA_KEY_2048.private_key(backend)
3327
3328        cert = (
3329            x509.CertificateBuilder()
3330            .subject_name(
3331                x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")])
3332            )
3333            .issuer_name(
3334                x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US")])
3335            )
3336            .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1))
3337            .not_valid_after(datetime.datetime(2030, 12, 31, 8, 30))
3338            .public_key(private_key.public_key())
3339            .serial_number(123)
3340            .add_extension(unrecognized, critical=False)
3341            .sign(private_key, hashes.SHA256(), backend)
3342        )
3343
3344        ext = cert.extensions.get_extension_for_oid(unrecognized.oid)
3345
3346        assert ext.value == unrecognized
3347
3348
3349@pytest.mark.requires_backend_interface(interface=X509Backend)
3350class TestCertificateSigningRequestBuilder(object):
3351    @pytest.mark.requires_backend_interface(interface=RSABackend)
3352    def test_sign_invalid_hash_algorithm(self, backend):
3353        private_key = RSA_KEY_2048.private_key(backend)
3354
3355        builder = x509.CertificateSigningRequestBuilder().subject_name(
3356            x509.Name([])
3357        )
3358        with pytest.raises(TypeError):
3359            builder.sign(private_key, "NotAHash", backend)
3360
3361    @pytest.mark.supported(
3362        only_if=lambda backend: backend.ed25519_supported(),
3363        skip_message="Requires OpenSSL with Ed25519 support",
3364    )
3365    @pytest.mark.requires_backend_interface(interface=X509Backend)
3366    def test_request_with_unsupported_hash_ed25519(self, backend):
3367        private_key = ed25519.Ed25519PrivateKey.generate()
3368        builder = x509.CertificateSigningRequestBuilder().subject_name(
3369            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3370        )
3371
3372        with pytest.raises(ValueError):
3373            builder.sign(private_key, hashes.SHA256(), backend)
3374
3375    @pytest.mark.supported(
3376        only_if=lambda backend: backend.ed448_supported(),
3377        skip_message="Requires OpenSSL with Ed448 support",
3378    )
3379    @pytest.mark.requires_backend_interface(interface=X509Backend)
3380    def test_request_with_unsupported_hash_ed448(self, backend):
3381        private_key = ed448.Ed448PrivateKey.generate()
3382        builder = x509.CertificateSigningRequestBuilder().subject_name(
3383            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3384        )
3385
3386        with pytest.raises(ValueError):
3387            builder.sign(private_key, hashes.SHA256(), backend)
3388
3389    @pytest.mark.requires_backend_interface(interface=RSABackend)
3390    @pytest.mark.supported(
3391        only_if=lambda backend: backend.hash_supported(hashes.MD5()),
3392        skip_message="Requires OpenSSL with MD5 support",
3393    )
3394    def test_sign_rsa_with_md5(self, backend):
3395        private_key = RSA_KEY_2048.private_key(backend)
3396
3397        builder = x509.CertificateSigningRequestBuilder().subject_name(
3398            x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")])
3399        )
3400        request = builder.sign(private_key, hashes.MD5(), backend)
3401        assert isinstance(request.signature_hash_algorithm, hashes.MD5)
3402
3403    @pytest.mark.requires_backend_interface(interface=DSABackend)
3404    @pytest.mark.supported(
3405        only_if=lambda backend: backend.hash_supported(hashes.MD5()),
3406        skip_message="Requires OpenSSL with MD5 support",
3407    )
3408    def test_sign_dsa_with_md5(self, backend):
3409        private_key = DSA_KEY_2048.private_key(backend)
3410        builder = x509.CertificateSigningRequestBuilder().subject_name(
3411            x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")])
3412        )
3413        with pytest.raises(ValueError):
3414            builder.sign(private_key, hashes.MD5(), backend)
3415
3416    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
3417    @pytest.mark.supported(
3418        only_if=lambda backend: backend.hash_supported(hashes.MD5()),
3419        skip_message="Requires OpenSSL with MD5 support",
3420    )
3421    def test_sign_ec_with_md5(self, backend):
3422        _skip_curve_unsupported(backend, ec.SECP256R1())
3423        private_key = EC_KEY_SECP256R1.private_key(backend)
3424        builder = x509.CertificateSigningRequestBuilder().subject_name(
3425            x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")])
3426        )
3427        with pytest.raises(ValueError):
3428            builder.sign(private_key, hashes.MD5(), backend)
3429
3430    @pytest.mark.requires_backend_interface(interface=RSABackend)
3431    def test_no_subject_name(self, backend):
3432        private_key = RSA_KEY_2048.private_key(backend)
3433
3434        builder = x509.CertificateSigningRequestBuilder()
3435        with pytest.raises(ValueError):
3436            builder.sign(private_key, hashes.SHA256(), backend)
3437
3438    @pytest.mark.requires_backend_interface(interface=RSABackend)
3439    def test_build_ca_request_with_rsa(self, backend):
3440        private_key = RSA_KEY_2048.private_key(backend)
3441
3442        request = (
3443            x509.CertificateSigningRequestBuilder()
3444            .subject_name(
3445                x509.Name(
3446                    [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
3447                )
3448            )
3449            .add_extension(
3450                x509.BasicConstraints(ca=True, path_length=2), critical=True
3451            )
3452            .sign(private_key, hashes.SHA1(), backend)
3453        )
3454
3455        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
3456        public_key = request.public_key()
3457        assert isinstance(public_key, rsa.RSAPublicKey)
3458        subject = request.subject
3459        assert isinstance(subject, x509.Name)
3460        assert list(subject) == [
3461            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
3462        ]
3463        basic_constraints = request.extensions.get_extension_for_oid(
3464            ExtensionOID.BASIC_CONSTRAINTS
3465        )
3466        assert basic_constraints.value.ca is True
3467        assert basic_constraints.value.path_length == 2
3468
3469    @pytest.mark.requires_backend_interface(interface=RSABackend)
3470    def test_build_ca_request_with_unicode(self, backend):
3471        private_key = RSA_KEY_2048.private_key(backend)
3472
3473        request = (
3474            x509.CertificateSigningRequestBuilder()
3475            .subject_name(
3476                x509.Name(
3477                    [
3478                        x509.NameAttribute(
3479                            NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a"
3480                        ),
3481                    ]
3482                )
3483            )
3484            .add_extension(
3485                x509.BasicConstraints(ca=True, path_length=2), critical=True
3486            )
3487            .sign(private_key, hashes.SHA1(), backend)
3488        )
3489
3490        loaded_request = x509.load_pem_x509_csr(
3491            request.public_bytes(encoding=serialization.Encoding.PEM), backend
3492        )
3493        subject = loaded_request.subject
3494        assert isinstance(subject, x509.Name)
3495        assert list(subject) == [
3496            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA\U0001f37a"),
3497        ]
3498
3499    @pytest.mark.requires_backend_interface(interface=RSABackend)
3500    def test_subject_dn_asn1_types(self, backend):
3501        private_key = RSA_KEY_2048.private_key(backend)
3502
3503        request = (
3504            x509.CertificateSigningRequestBuilder()
3505            .subject_name(
3506                x509.Name(
3507                    [
3508                        x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
3509                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
3510                        x509.NameAttribute(NameOID.LOCALITY_NAME, u"value"),
3511                        x509.NameAttribute(
3512                            NameOID.STATE_OR_PROVINCE_NAME, u"value"
3513                        ),
3514                        x509.NameAttribute(NameOID.STREET_ADDRESS, u"value"),
3515                        x509.NameAttribute(
3516                            NameOID.ORGANIZATION_NAME, u"value"
3517                        ),
3518                        x509.NameAttribute(
3519                            NameOID.ORGANIZATIONAL_UNIT_NAME, u"value"
3520                        ),
3521                        x509.NameAttribute(NameOID.SERIAL_NUMBER, u"value"),
3522                        x509.NameAttribute(NameOID.SURNAME, u"value"),
3523                        x509.NameAttribute(NameOID.GIVEN_NAME, u"value"),
3524                        x509.NameAttribute(NameOID.TITLE, u"value"),
3525                        x509.NameAttribute(
3526                            NameOID.GENERATION_QUALIFIER, u"value"
3527                        ),
3528                        x509.NameAttribute(
3529                            NameOID.X500_UNIQUE_IDENTIFIER, u"value"
3530                        ),
3531                        x509.NameAttribute(NameOID.DN_QUALIFIER, u"value"),
3532                        x509.NameAttribute(NameOID.PSEUDONYM, u"value"),
3533                        x509.NameAttribute(NameOID.USER_ID, u"value"),
3534                        x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"value"),
3535                        x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"value"),
3536                        x509.NameAttribute(
3537                            NameOID.JURISDICTION_COUNTRY_NAME, u"US"
3538                        ),
3539                        x509.NameAttribute(
3540                            NameOID.JURISDICTION_LOCALITY_NAME, u"value"
3541                        ),
3542                        x509.NameAttribute(
3543                            NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME,
3544                            u"value",
3545                        ),
3546                        x509.NameAttribute(
3547                            NameOID.BUSINESS_CATEGORY, u"value"
3548                        ),
3549                        x509.NameAttribute(NameOID.POSTAL_ADDRESS, u"value"),
3550                        x509.NameAttribute(NameOID.POSTAL_CODE, u"value"),
3551                    ]
3552                )
3553            )
3554            .sign(private_key, hashes.SHA256(), backend)
3555        )
3556        for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
3557            assert (
3558                request.subject.get_attributes_for_oid(oid)[0]._type
3559                == asn1_type
3560            )
3561
3562    @pytest.mark.requires_backend_interface(interface=RSABackend)
3563    def test_build_ca_request_with_multivalue_rdns(self, backend):
3564        private_key = RSA_KEY_2048.private_key(backend)
3565        subject = x509.Name(
3566            [
3567                x509.RelativeDistinguishedName(
3568                    [
3569                        x509.NameAttribute(NameOID.TITLE, u"Test"),
3570                        x509.NameAttribute(NameOID.COMMON_NAME, u"Multivalue"),
3571                        x509.NameAttribute(NameOID.SURNAME, u"RDNs"),
3572                    ]
3573                ),
3574                x509.RelativeDistinguishedName(
3575                    [x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA")]
3576                ),
3577            ]
3578        )
3579
3580        request = (
3581            x509.CertificateSigningRequestBuilder()
3582            .subject_name(subject)
3583            .sign(private_key, hashes.SHA1(), backend)
3584        )
3585
3586        loaded_request = x509.load_pem_x509_csr(
3587            request.public_bytes(encoding=serialization.Encoding.PEM), backend
3588        )
3589        assert isinstance(loaded_request.subject, x509.Name)
3590        assert loaded_request.subject == subject
3591
3592    @pytest.mark.requires_backend_interface(interface=RSABackend)
3593    def test_build_nonca_request_with_rsa(self, backend):
3594        private_key = RSA_KEY_2048.private_key(backend)
3595
3596        request = (
3597            x509.CertificateSigningRequestBuilder()
3598            .subject_name(
3599                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3600            )
3601            .add_extension(
3602                x509.BasicConstraints(ca=False, path_length=None),
3603                critical=True,
3604            )
3605            .sign(private_key, hashes.SHA1(), backend)
3606        )
3607
3608        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
3609        public_key = request.public_key()
3610        assert isinstance(public_key, rsa.RSAPublicKey)
3611        subject = request.subject
3612        assert isinstance(subject, x509.Name)
3613        assert list(subject) == [
3614            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
3615        ]
3616        basic_constraints = request.extensions.get_extension_for_oid(
3617            ExtensionOID.BASIC_CONSTRAINTS
3618        )
3619        assert basic_constraints.value.ca is False
3620        assert basic_constraints.value.path_length is None
3621
3622    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
3623    def test_build_ca_request_with_ec(self, backend):
3624        _skip_curve_unsupported(backend, ec.SECP256R1())
3625        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
3626
3627        request = (
3628            x509.CertificateSigningRequestBuilder()
3629            .subject_name(
3630                x509.Name(
3631                    [
3632                        x509.NameAttribute(
3633                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
3634                        ),
3635                    ]
3636                )
3637            )
3638            .add_extension(
3639                x509.BasicConstraints(ca=True, path_length=2), critical=True
3640            )
3641            .sign(private_key, hashes.SHA1(), backend)
3642        )
3643
3644        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
3645        public_key = request.public_key()
3646        assert isinstance(public_key, ec.EllipticCurvePublicKey)
3647        subject = request.subject
3648        assert isinstance(subject, x509.Name)
3649        assert list(subject) == [
3650            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
3651        ]
3652        basic_constraints = request.extensions.get_extension_for_oid(
3653            ExtensionOID.BASIC_CONSTRAINTS
3654        )
3655        assert basic_constraints.value.ca is True
3656        assert basic_constraints.value.path_length == 2
3657
3658    @pytest.mark.supported(
3659        only_if=lambda backend: backend.ed25519_supported(),
3660        skip_message="Requires OpenSSL with Ed25519 support",
3661    )
3662    @pytest.mark.requires_backend_interface(interface=X509Backend)
3663    def test_build_ca_request_with_ed25519(self, backend):
3664        private_key = ed25519.Ed25519PrivateKey.generate()
3665
3666        request = (
3667            x509.CertificateSigningRequestBuilder()
3668            .subject_name(
3669                x509.Name(
3670                    [
3671                        x509.NameAttribute(
3672                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
3673                        ),
3674                    ]
3675                )
3676            )
3677            .add_extension(
3678                x509.BasicConstraints(ca=True, path_length=2), critical=True
3679            )
3680            .sign(private_key, None, backend)
3681        )
3682
3683        assert request.signature_hash_algorithm is None
3684        public_key = request.public_key()
3685        assert isinstance(public_key, ed25519.Ed25519PublicKey)
3686        subject = request.subject
3687        assert isinstance(subject, x509.Name)
3688        assert list(subject) == [
3689            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
3690        ]
3691        basic_constraints = request.extensions.get_extension_for_oid(
3692            ExtensionOID.BASIC_CONSTRAINTS
3693        )
3694        assert basic_constraints.value.ca is True
3695        assert basic_constraints.value.path_length == 2
3696
3697    @pytest.mark.supported(
3698        only_if=lambda backend: backend.ed448_supported(),
3699        skip_message="Requires OpenSSL with Ed448 support",
3700    )
3701    @pytest.mark.requires_backend_interface(interface=X509Backend)
3702    def test_build_ca_request_with_ed448(self, backend):
3703        private_key = ed448.Ed448PrivateKey.generate()
3704
3705        request = (
3706            x509.CertificateSigningRequestBuilder()
3707            .subject_name(
3708                x509.Name(
3709                    [
3710                        x509.NameAttribute(
3711                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
3712                        ),
3713                    ]
3714                )
3715            )
3716            .add_extension(
3717                x509.BasicConstraints(ca=True, path_length=2), critical=True
3718            )
3719            .sign(private_key, None, backend)
3720        )
3721
3722        assert request.signature_hash_algorithm is None
3723        public_key = request.public_key()
3724        assert isinstance(public_key, ed448.Ed448PublicKey)
3725        subject = request.subject
3726        assert isinstance(subject, x509.Name)
3727        assert list(subject) == [
3728            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
3729        ]
3730        basic_constraints = request.extensions.get_extension_for_oid(
3731            ExtensionOID.BASIC_CONSTRAINTS
3732        )
3733        assert basic_constraints.value.ca is True
3734        assert basic_constraints.value.path_length == 2
3735
3736    @pytest.mark.requires_backend_interface(interface=DSABackend)
3737    def test_build_ca_request_with_dsa(self, backend):
3738        private_key = DSA_KEY_2048.private_key(backend)
3739
3740        request = (
3741            x509.CertificateSigningRequestBuilder()
3742            .subject_name(
3743                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3744            )
3745            .add_extension(
3746                x509.BasicConstraints(ca=True, path_length=2), critical=True
3747            )
3748            .sign(private_key, hashes.SHA1(), backend)
3749        )
3750
3751        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
3752        public_key = request.public_key()
3753        assert isinstance(public_key, dsa.DSAPublicKey)
3754        subject = request.subject
3755        assert isinstance(subject, x509.Name)
3756        assert list(subject) == [
3757            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
3758        ]
3759        basic_constraints = request.extensions.get_extension_for_oid(
3760            ExtensionOID.BASIC_CONSTRAINTS
3761        )
3762        assert basic_constraints.value.ca is True
3763        assert basic_constraints.value.path_length == 2
3764
3765    def test_add_duplicate_extension(self):
3766        builder = x509.CertificateSigningRequestBuilder().add_extension(
3767            x509.BasicConstraints(True, 2),
3768            critical=True,
3769        )
3770        with pytest.raises(ValueError):
3771            builder.add_extension(
3772                x509.BasicConstraints(True, 2),
3773                critical=True,
3774            )
3775
3776    def test_set_invalid_subject(self):
3777        builder = x509.CertificateSigningRequestBuilder()
3778        with pytest.raises(TypeError):
3779            builder.subject_name("NotAName")
3780
3781    def test_add_invalid_extension_type(self):
3782        builder = x509.CertificateSigningRequestBuilder()
3783
3784        with pytest.raises(TypeError):
3785            builder.add_extension(object(), False)
3786
3787    def test_add_unsupported_extension(self, backend):
3788        private_key = RSA_KEY_2048.private_key(backend)
3789        builder = x509.CertificateSigningRequestBuilder()
3790        builder = (
3791            builder.subject_name(
3792                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3793            )
3794            .add_extension(
3795                x509.SubjectAlternativeName(
3796                    [x509.DNSName(u"cryptography.io")]
3797                ),
3798                critical=False,
3799            )
3800            .add_extension(DummyExtension(), False)
3801        )
3802        with pytest.raises(NotImplementedError):
3803            builder.sign(private_key, hashes.SHA256(), backend)
3804
3805    def test_key_usage(self, backend):
3806        private_key = RSA_KEY_2048.private_key(backend)
3807        builder = x509.CertificateSigningRequestBuilder()
3808        request = (
3809            builder.subject_name(
3810                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3811            )
3812            .add_extension(
3813                x509.KeyUsage(
3814                    digital_signature=True,
3815                    content_commitment=True,
3816                    key_encipherment=False,
3817                    data_encipherment=False,
3818                    key_agreement=False,
3819                    key_cert_sign=True,
3820                    crl_sign=False,
3821                    encipher_only=False,
3822                    decipher_only=False,
3823                ),
3824                critical=False,
3825            )
3826            .sign(private_key, hashes.SHA256(), backend)
3827        )
3828        assert len(request.extensions) == 1
3829        ext = request.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
3830        assert ext.critical is False
3831        assert ext.value == x509.KeyUsage(
3832            digital_signature=True,
3833            content_commitment=True,
3834            key_encipherment=False,
3835            data_encipherment=False,
3836            key_agreement=False,
3837            key_cert_sign=True,
3838            crl_sign=False,
3839            encipher_only=False,
3840            decipher_only=False,
3841        )
3842
3843    def test_key_usage_key_agreement_bit(self, backend):
3844        private_key = RSA_KEY_2048.private_key(backend)
3845        builder = x509.CertificateSigningRequestBuilder()
3846        request = (
3847            builder.subject_name(
3848                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3849            )
3850            .add_extension(
3851                x509.KeyUsage(
3852                    digital_signature=False,
3853                    content_commitment=False,
3854                    key_encipherment=False,
3855                    data_encipherment=False,
3856                    key_agreement=True,
3857                    key_cert_sign=True,
3858                    crl_sign=False,
3859                    encipher_only=False,
3860                    decipher_only=True,
3861                ),
3862                critical=False,
3863            )
3864            .sign(private_key, hashes.SHA256(), backend)
3865        )
3866        assert len(request.extensions) == 1
3867        ext = request.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
3868        assert ext.critical is False
3869        assert ext.value == x509.KeyUsage(
3870            digital_signature=False,
3871            content_commitment=False,
3872            key_encipherment=False,
3873            data_encipherment=False,
3874            key_agreement=True,
3875            key_cert_sign=True,
3876            crl_sign=False,
3877            encipher_only=False,
3878            decipher_only=True,
3879        )
3880
3881    def test_add_two_extensions(self, backend):
3882        private_key = RSA_KEY_2048.private_key(backend)
3883        builder = x509.CertificateSigningRequestBuilder()
3884        request = (
3885            builder.subject_name(
3886                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3887            )
3888            .add_extension(
3889                x509.SubjectAlternativeName(
3890                    [x509.DNSName(u"cryptography.io")]
3891                ),
3892                critical=False,
3893            )
3894            .add_extension(
3895                x509.BasicConstraints(ca=True, path_length=2), critical=True
3896            )
3897            .sign(private_key, hashes.SHA1(), backend)
3898        )
3899
3900        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
3901        public_key = request.public_key()
3902        assert isinstance(public_key, rsa.RSAPublicKey)
3903        basic_constraints = request.extensions.get_extension_for_oid(
3904            ExtensionOID.BASIC_CONSTRAINTS
3905        )
3906        assert basic_constraints.value.ca is True
3907        assert basic_constraints.value.path_length == 2
3908        ext = request.extensions.get_extension_for_oid(
3909            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
3910        )
3911        assert list(ext.value) == [x509.DNSName(u"cryptography.io")]
3912
3913    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
3914    def test_add_attributes(self, backend):
3915        _skip_curve_unsupported(backend, ec.SECP256R1())
3916        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
3917        challenge_password = b"challenge me!"
3918        unstructured_name = b"no structure, for shame"
3919        locality = b"this shouldn't even be an X509 attribute"
3920
3921        request = (
3922            x509.CertificateSigningRequestBuilder()
3923            .subject_name(
3924                x509.Name(
3925                    [
3926                        x509.NameAttribute(
3927                            NameOID.STATE_OR_PROVINCE_NAME, u"Texas"
3928                        ),
3929                    ]
3930                )
3931            )
3932            .add_attribute(
3933                x509.oid.AttributeOID.CHALLENGE_PASSWORD, challenge_password
3934            )
3935            .add_attribute(
3936                x509.oid.AttributeOID.UNSTRUCTURED_NAME, unstructured_name
3937            )
3938            .add_attribute(x509.oid.NameOID.LOCALITY_NAME, locality)
3939            .sign(private_key, hashes.SHA256(), backend)
3940        )
3941
3942        assert (
3943            request.get_attribute_for_oid(
3944                x509.oid.AttributeOID.CHALLENGE_PASSWORD
3945            )
3946            == challenge_password
3947        )
3948        assert (
3949            request.get_attribute_for_oid(
3950                x509.oid.AttributeOID.UNSTRUCTURED_NAME
3951            )
3952            == unstructured_name
3953        )
3954        assert (
3955            request.get_attribute_for_oid(x509.oid.NameOID.LOCALITY_NAME)
3956            == locality
3957        )
3958
3959    def test_add_attribute_bad_types(self, backend):
3960        request = x509.CertificateSigningRequestBuilder()
3961        with pytest.raises(TypeError):
3962            request.add_attribute(b"not an oid", b"val")
3963
3964        with pytest.raises(TypeError):
3965            request.add_attribute(
3966                x509.oid.AttributeOID.CHALLENGE_PASSWORD, 383
3967            )
3968
3969    def test_duplicate_attribute(self, backend):
3970        request = x509.CertificateSigningRequestBuilder().add_attribute(
3971            x509.oid.AttributeOID.CHALLENGE_PASSWORD, b"val"
3972        )
3973        with pytest.raises(ValueError):
3974            request.add_attribute(
3975                x509.oid.AttributeOID.CHALLENGE_PASSWORD, b"val2"
3976            )
3977
3978    def test_set_subject_twice(self):
3979        builder = x509.CertificateSigningRequestBuilder()
3980        builder = builder.subject_name(
3981            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3982        )
3983        with pytest.raises(ValueError):
3984            builder.subject_name(
3985                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
3986            )
3987
3988    def test_subject_alt_names(self, backend):
3989        private_key = RSA_KEY_2048.private_key(backend)
3990
3991        san = x509.SubjectAlternativeName(
3992            [
3993                x509.DNSName(u"example.com"),
3994                x509.DNSName(u"*.example.com"),
3995                x509.RegisteredID(x509.ObjectIdentifier("1.2.3.4.5.6.7")),
3996                x509.DirectoryName(
3997                    x509.Name(
3998                        [
3999                            x509.NameAttribute(NameOID.COMMON_NAME, u"PyCA"),
4000                            x509.NameAttribute(
4001                                NameOID.ORGANIZATION_NAME,
4002                                u"We heart UTF8!\u2122",
4003                            ),
4004                        ]
4005                    )
4006                ),
4007                x509.IPAddress(ipaddress.ip_address(u"127.0.0.1")),
4008                x509.IPAddress(ipaddress.ip_address(u"ff::")),
4009                x509.OtherName(
4010                    type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
4011                    value=b"0\x03\x02\x01\x05",
4012                ),
4013                x509.RFC822Name(u"test@example.com"),
4014                x509.RFC822Name(u"email"),
4015                x509.RFC822Name(u"email@xn--eml-vla4c.com"),
4016                x509.UniformResourceIdentifier(
4017                    u"https://xn--80ato2c.cryptography"
4018                ),
4019                x509.UniformResourceIdentifier(
4020                    u"gopher://cryptography:70/some/path"
4021                ),
4022            ]
4023        )
4024
4025        csr = (
4026            x509.CertificateSigningRequestBuilder()
4027            .subject_name(
4028                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
4029            )
4030            .add_extension(
4031                san,
4032                critical=False,
4033            )
4034            .sign(private_key, hashes.SHA256(), backend)
4035        )
4036
4037        assert len(csr.extensions) == 1
4038        ext = csr.extensions.get_extension_for_oid(
4039            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
4040        )
4041        assert not ext.critical
4042        assert ext.oid == ExtensionOID.SUBJECT_ALTERNATIVE_NAME
4043        assert ext.value == san
4044
4045    def test_invalid_asn1_othername(self, backend):
4046        private_key = RSA_KEY_2048.private_key(backend)
4047
4048        builder = (
4049            x509.CertificateSigningRequestBuilder()
4050            .subject_name(
4051                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
4052            )
4053            .add_extension(
4054                x509.SubjectAlternativeName(
4055                    [
4056                        x509.OtherName(
4057                            type_id=x509.ObjectIdentifier("1.2.3.3.3.3"),
4058                            value=b"\x01\x02\x01\x05",
4059                        ),
4060                    ]
4061                ),
4062                critical=False,
4063            )
4064        )
4065        with pytest.raises(ValueError):
4066            builder.sign(private_key, hashes.SHA256(), backend)
4067
4068    def test_subject_alt_name_unsupported_general_name(self, backend):
4069        private_key = RSA_KEY_2048.private_key(backend)
4070
4071        builder = (
4072            x509.CertificateSigningRequestBuilder()
4073            .subject_name(
4074                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"SAN")])
4075            )
4076            .add_extension(
4077                x509.SubjectAlternativeName([FakeGeneralName("")]),
4078                critical=False,
4079            )
4080        )
4081
4082        with pytest.raises(ValueError):
4083            builder.sign(private_key, hashes.SHA256(), backend)
4084
4085    def test_extended_key_usage(self, backend):
4086        private_key = RSA_KEY_2048.private_key(backend)
4087        eku = x509.ExtendedKeyUsage(
4088            [
4089                ExtendedKeyUsageOID.CLIENT_AUTH,
4090                ExtendedKeyUsageOID.SERVER_AUTH,
4091                ExtendedKeyUsageOID.CODE_SIGNING,
4092            ]
4093        )
4094        builder = x509.CertificateSigningRequestBuilder()
4095        request = (
4096            builder.subject_name(
4097                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4098            )
4099            .add_extension(eku, critical=False)
4100            .sign(private_key, hashes.SHA256(), backend)
4101        )
4102
4103        ext = request.extensions.get_extension_for_oid(
4104            ExtensionOID.EXTENDED_KEY_USAGE
4105        )
4106        assert ext.critical is False
4107        assert ext.value == eku
4108
4109    @pytest.mark.requires_backend_interface(interface=RSABackend)
4110    def test_rsa_key_too_small(self, backend):
4111        private_key = RSA_KEY_512.private_key(backend)
4112        builder = x509.CertificateSigningRequestBuilder()
4113        builder = builder.subject_name(
4114            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4115        )
4116
4117        with pytest.raises(ValueError):
4118            builder.sign(private_key, hashes.SHA512(), backend)
4119
4120    @pytest.mark.requires_backend_interface(interface=RSABackend)
4121    @pytest.mark.requires_backend_interface(interface=X509Backend)
4122    def test_build_cert_with_aia(self, backend):
4123        issuer_private_key = RSA_KEY_2048.private_key(backend)
4124        subject_private_key = RSA_KEY_2048.private_key(backend)
4125
4126        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
4127        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
4128
4129        aia = x509.AuthorityInformationAccess(
4130            [
4131                x509.AccessDescription(
4132                    AuthorityInformationAccessOID.OCSP,
4133                    x509.UniformResourceIdentifier(u"http://ocsp.domain.com"),
4134                ),
4135                x509.AccessDescription(
4136                    AuthorityInformationAccessOID.CA_ISSUERS,
4137                    x509.UniformResourceIdentifier(
4138                        u"http://domain.com/ca.crt"
4139                    ),
4140                ),
4141            ]
4142        )
4143
4144        builder = (
4145            x509.CertificateBuilder()
4146            .serial_number(777)
4147            .issuer_name(
4148                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4149            )
4150            .subject_name(
4151                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4152            )
4153            .public_key(subject_private_key.public_key())
4154            .add_extension(aia, critical=False)
4155            .not_valid_before(not_valid_before)
4156            .not_valid_after(not_valid_after)
4157        )
4158
4159        cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
4160
4161        ext = cert.extensions.get_extension_for_oid(
4162            ExtensionOID.AUTHORITY_INFORMATION_ACCESS
4163        )
4164        assert ext.value == aia
4165
4166    @pytest.mark.requires_backend_interface(interface=RSABackend)
4167    @pytest.mark.requires_backend_interface(interface=X509Backend)
4168    def test_build_cert_with_sia(self, backend):
4169        issuer_private_key = RSA_KEY_2048.private_key(backend)
4170        subject_private_key = RSA_KEY_2048.private_key(backend)
4171
4172        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
4173        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
4174
4175        sia = x509.SubjectInformationAccess(
4176            [
4177                x509.AccessDescription(
4178                    SubjectInformationAccessOID.CA_REPOSITORY,
4179                    x509.UniformResourceIdentifier(u"http://ca.domain.com"),
4180                ),
4181            ]
4182        )
4183
4184        builder = (
4185            x509.CertificateBuilder()
4186            .serial_number(777)
4187            .issuer_name(
4188                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4189            )
4190            .subject_name(
4191                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4192            )
4193            .public_key(subject_private_key.public_key())
4194            .add_extension(sia, critical=False)
4195            .not_valid_before(not_valid_before)
4196            .not_valid_after(not_valid_after)
4197        )
4198
4199        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
4200
4201        ext = cert.extensions.get_extension_for_oid(
4202            ExtensionOID.SUBJECT_INFORMATION_ACCESS
4203        )
4204        assert ext.value == sia
4205
4206    @pytest.mark.requires_backend_interface(interface=RSABackend)
4207    @pytest.mark.requires_backend_interface(interface=X509Backend)
4208    def test_build_cert_with_ski(self, backend):
4209        issuer_private_key = RSA_KEY_2048.private_key(backend)
4210        subject_private_key = RSA_KEY_2048.private_key(backend)
4211
4212        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
4213        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
4214
4215        ski = x509.SubjectKeyIdentifier.from_public_key(
4216            subject_private_key.public_key()
4217        )
4218
4219        builder = (
4220            x509.CertificateBuilder()
4221            .serial_number(777)
4222            .issuer_name(
4223                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4224            )
4225            .subject_name(
4226                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4227            )
4228            .public_key(subject_private_key.public_key())
4229            .add_extension(ski, critical=False)
4230            .not_valid_before(not_valid_before)
4231            .not_valid_after(not_valid_after)
4232        )
4233
4234        cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
4235
4236        ext = cert.extensions.get_extension_for_oid(
4237            ExtensionOID.SUBJECT_KEY_IDENTIFIER
4238        )
4239        assert ext.value == ski
4240
4241    @pytest.mark.parametrize(
4242        "aki",
4243        [
4244            x509.AuthorityKeyIdentifier(
4245                b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
4246                b"\xcbY",
4247                None,
4248                None,
4249            ),
4250            x509.AuthorityKeyIdentifier(
4251                b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
4252                b"\xcbY",
4253                [
4254                    x509.DirectoryName(
4255                        x509.Name(
4256                            [
4257                                x509.NameAttribute(
4258                                    NameOID.ORGANIZATION_NAME, u"PyCA"
4259                                ),
4260                                x509.NameAttribute(
4261                                    NameOID.COMMON_NAME, u"cryptography CA"
4262                                ),
4263                            ]
4264                        )
4265                    )
4266                ],
4267                333,
4268            ),
4269            x509.AuthorityKeyIdentifier(
4270                None,
4271                [
4272                    x509.DirectoryName(
4273                        x509.Name(
4274                            [
4275                                x509.NameAttribute(
4276                                    NameOID.ORGANIZATION_NAME, u"PyCA"
4277                                ),
4278                                x509.NameAttribute(
4279                                    NameOID.COMMON_NAME, u"cryptography CA"
4280                                ),
4281                            ]
4282                        )
4283                    )
4284                ],
4285                333,
4286            ),
4287        ],
4288    )
4289    @pytest.mark.requires_backend_interface(interface=RSABackend)
4290    @pytest.mark.requires_backend_interface(interface=X509Backend)
4291    def test_build_cert_with_aki(self, aki, backend):
4292        issuer_private_key = RSA_KEY_2048.private_key(backend)
4293        subject_private_key = RSA_KEY_2048.private_key(backend)
4294
4295        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
4296        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
4297
4298        builder = (
4299            x509.CertificateBuilder()
4300            .serial_number(777)
4301            .issuer_name(
4302                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4303            )
4304            .subject_name(
4305                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4306            )
4307            .public_key(subject_private_key.public_key())
4308            .add_extension(aki, critical=False)
4309            .not_valid_before(not_valid_before)
4310            .not_valid_after(not_valid_after)
4311        )
4312
4313        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
4314
4315        ext = cert.extensions.get_extension_for_oid(
4316            ExtensionOID.AUTHORITY_KEY_IDENTIFIER
4317        )
4318        assert ext.value == aki
4319
4320    def test_ocsp_nocheck(self, backend):
4321        issuer_private_key = RSA_KEY_2048.private_key(backend)
4322        subject_private_key = RSA_KEY_2048.private_key(backend)
4323
4324        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
4325        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
4326
4327        builder = (
4328            x509.CertificateBuilder()
4329            .serial_number(777)
4330            .issuer_name(
4331                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4332            )
4333            .subject_name(
4334                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
4335            )
4336            .public_key(subject_private_key.public_key())
4337            .add_extension(x509.OCSPNoCheck(), critical=False)
4338            .not_valid_before(not_valid_before)
4339            .not_valid_after(not_valid_after)
4340        )
4341
4342        cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
4343
4344        ext = cert.extensions.get_extension_for_oid(ExtensionOID.OCSP_NO_CHECK)
4345        assert isinstance(ext.value, x509.OCSPNoCheck)
4346
4347
4348@pytest.mark.requires_backend_interface(interface=DSABackend)
4349@pytest.mark.requires_backend_interface(interface=X509Backend)
4350class TestDSACertificate(object):
4351    def test_load_dsa_cert(self, backend):
4352        cert = _load_cert(
4353            os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
4354            x509.load_pem_x509_certificate,
4355            backend,
4356        )
4357        assert isinstance(cert.signature_hash_algorithm, hashes.SHA1)
4358        public_key = cert.public_key()
4359        assert isinstance(public_key, dsa.DSAPublicKey)
4360        num = public_key.public_numbers()
4361        assert num.y == int(
4362            "4c08bfe5f2d76649c80acf7d431f6ae2124b217abc8c9f6aca776ddfa94"
4363            "53b6656f13e543684cd5f6431a314377d2abfa068b7080cb8ddc065afc2"
4364            "dea559f0b584c97a2b235b9b69b46bc6de1aed422a6f341832618bcaae2"
4365            "198aba388099dafb05ff0b5efecb3b0ae169a62e1c72022af50ae68af3b"
4366            "033c18e6eec1f7df4692c456ccafb79cc7e08da0a5786e9816ceda651d6"
4367            "1b4bb7b81c2783da97cea62df67af5e85991fdc13aff10fc60e06586386"
4368            "b96bb78d65750f542f86951e05a6d81baadbcd35a2e5cad4119923ae6a2"
4369            "002091a3d17017f93c52970113cdc119970b9074ca506eac91c3dd37632"
4370            "5df4af6b3911ef267d26623a5a1c5df4a6d13f1c",
4371            16,
4372        )
4373        assert num.parameter_numbers.g == int(
4374            "4b7ced71dc353965ecc10d441a9a06fc24943a32d66429dd5ef44d43e67"
4375            "d789d99770aec32c0415dc92970880872da45fef8dd1e115a3e4801387b"
4376            "a6d755861f062fd3b6e9ea8e2641152339b828315b1528ee6c7b79458d2"
4377            "1f3db973f6fc303f9397174c2799dd2351282aa2d8842c357a73495bbaa"
4378            "c4932786414c55e60d73169f5761036fba29e9eebfb049f8a3b1b7cee6f"
4379            "3fbfa136205f130bee2cf5b9c38dc1095d4006f2e73335c07352c64130a"
4380            "1ab2b89f13b48f628d3cc3868beece9bb7beade9f830eacc6fa241425c0"
4381            "b3fcc0df416a0c89f7bf35668d765ec95cdcfbe9caff49cfc156c668c76"
4382            "fa6247676a6d3ac945844a083509c6a1b436baca",
4383            16,
4384        )
4385        assert num.parameter_numbers.p == int(
4386            "bfade6048e373cd4e48b677e878c8e5b08c02102ae04eb2cb5c46a523a3"
4387            "af1c73d16b24f34a4964781ae7e50500e21777754a670bd19a7420d6330"
4388            "84e5556e33ca2c0e7d547ea5f46a07a01bf8669ae3bdec042d9b2ae5e6e"
4389            "cf49f00ba9dac99ab6eff140d2cedf722ee62c2f9736857971444c25d0a"
4390            "33d2017dc36d682a1054fe2a9428dda355a851ce6e6d61e03e419fd4ca4"
4391            "e703313743d86caa885930f62ed5bf342d8165627681e9cc3244ba72aa2"
4392            "2148400a6bbe80154e855d042c9dc2a3405f1e517be9dea50562f56da93"
4393            "f6085f844a7e705c1f043e65751c583b80d29103e590ccb26efdaa0893d"
4394            "833e36468f3907cfca788a3cb790f0341c8a31bf",
4395            16,
4396        )
4397        assert num.parameter_numbers.q == int(
4398            "822ff5d234e073b901cf5941f58e1f538e71d40d", 16
4399        )
4400
4401    def test_signature(self, backend):
4402        cert = _load_cert(
4403            os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
4404            x509.load_pem_x509_certificate,
4405            backend,
4406        )
4407        assert cert.signature == binascii.unhexlify(
4408            b"302c021425c4a84a936ab311ee017d3cbd9a3c650bb3ae4a02145d30c64b4326"
4409            b"86bdf925716b4ed059184396bcce"
4410        )
4411        r, s = decode_dss_signature(cert.signature)
4412        assert r == 215618264820276283222494627481362273536404860490
4413        assert s == 532023851299196869156027211159466197586787351758
4414
4415    def test_tbs_certificate_bytes(self, backend):
4416        cert = _load_cert(
4417            os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
4418            x509.load_pem_x509_certificate,
4419            backend,
4420        )
4421        assert cert.tbs_certificate_bytes == binascii.unhexlify(
4422            b"3082051aa003020102020900a37352e0b2142f86300906072a8648ce3804033"
4423            b"067310b3009060355040613025553310e300c06035504081305546578617331"
4424            b"0f300d0603550407130641757374696e3121301f060355040a1318496e74657"
4425            b"26e6574205769646769747320507479204c7464311430120603550403130b50"
4426            b"79434120445341204341301e170d3134313132373035313431375a170d31343"
4427            b"13232373035313431375a3067310b3009060355040613025553310e300c0603"
4428            b"55040813055465786173310f300d0603550407130641757374696e3121301f0"
4429            b"60355040a1318496e7465726e6574205769646769747320507479204c746431"
4430            b"1430120603550403130b50794341204453412043413082033a3082022d06072"
4431            b"a8648ce380401308202200282010100bfade6048e373cd4e48b677e878c8e5b"
4432            b"08c02102ae04eb2cb5c46a523a3af1c73d16b24f34a4964781ae7e50500e217"
4433            b"77754a670bd19a7420d633084e5556e33ca2c0e7d547ea5f46a07a01bf8669a"
4434            b"e3bdec042d9b2ae5e6ecf49f00ba9dac99ab6eff140d2cedf722ee62c2f9736"
4435            b"857971444c25d0a33d2017dc36d682a1054fe2a9428dda355a851ce6e6d61e0"
4436            b"3e419fd4ca4e703313743d86caa885930f62ed5bf342d8165627681e9cc3244"
4437            b"ba72aa22148400a6bbe80154e855d042c9dc2a3405f1e517be9dea50562f56d"
4438            b"a93f6085f844a7e705c1f043e65751c583b80d29103e590ccb26efdaa0893d8"
4439            b"33e36468f3907cfca788a3cb790f0341c8a31bf021500822ff5d234e073b901"
4440            b"cf5941f58e1f538e71d40d028201004b7ced71dc353965ecc10d441a9a06fc2"
4441            b"4943a32d66429dd5ef44d43e67d789d99770aec32c0415dc92970880872da45"
4442            b"fef8dd1e115a3e4801387ba6d755861f062fd3b6e9ea8e2641152339b828315"
4443            b"b1528ee6c7b79458d21f3db973f6fc303f9397174c2799dd2351282aa2d8842"
4444            b"c357a73495bbaac4932786414c55e60d73169f5761036fba29e9eebfb049f8a"
4445            b"3b1b7cee6f3fbfa136205f130bee2cf5b9c38dc1095d4006f2e73335c07352c"
4446            b"64130a1ab2b89f13b48f628d3cc3868beece9bb7beade9f830eacc6fa241425"
4447            b"c0b3fcc0df416a0c89f7bf35668d765ec95cdcfbe9caff49cfc156c668c76fa"
4448            b"6247676a6d3ac945844a083509c6a1b436baca0382010500028201004c08bfe"
4449            b"5f2d76649c80acf7d431f6ae2124b217abc8c9f6aca776ddfa9453b6656f13e"
4450            b"543684cd5f6431a314377d2abfa068b7080cb8ddc065afc2dea559f0b584c97"
4451            b"a2b235b9b69b46bc6de1aed422a6f341832618bcaae2198aba388099dafb05f"
4452            b"f0b5efecb3b0ae169a62e1c72022af50ae68af3b033c18e6eec1f7df4692c45"
4453            b"6ccafb79cc7e08da0a5786e9816ceda651d61b4bb7b81c2783da97cea62df67"
4454            b"af5e85991fdc13aff10fc60e06586386b96bb78d65750f542f86951e05a6d81"
4455            b"baadbcd35a2e5cad4119923ae6a2002091a3d17017f93c52970113cdc119970"
4456            b"b9074ca506eac91c3dd376325df4af6b3911ef267d26623a5a1c5df4a6d13f1"
4457            b"ca381cc3081c9301d0603551d0e04160414a4fb887a13fcdeb303bbae9a1dec"
4458            b"a72f125a541b3081990603551d2304819130818e8014a4fb887a13fcdeb303b"
4459            b"bae9a1deca72f125a541ba16ba4693067310b3009060355040613025553310e"
4460            b"300c060355040813055465786173310f300d0603550407130641757374696e3"
4461            b"121301f060355040a1318496e7465726e657420576964676974732050747920"
4462            b"4c7464311430120603550403130b5079434120445341204341820900a37352e"
4463            b"0b2142f86300c0603551d13040530030101ff"
4464        )
4465        cert.public_key().verify(
4466            cert.signature,
4467            cert.tbs_certificate_bytes,
4468            cert.signature_hash_algorithm,
4469        )
4470
4471
4472@pytest.mark.requires_backend_interface(interface=DSABackend)
4473@pytest.mark.requires_backend_interface(interface=X509Backend)
4474class TestDSACertificateRequest(object):
4475    @pytest.mark.parametrize(
4476        ("path", "loader_func"),
4477        [
4478            [
4479                os.path.join("x509", "requests", "dsa_sha1.pem"),
4480                x509.load_pem_x509_csr,
4481            ],
4482            [
4483                os.path.join("x509", "requests", "dsa_sha1.der"),
4484                x509.load_der_x509_csr,
4485            ],
4486        ],
4487    )
4488    def test_load_dsa_request(self, path, loader_func, backend):
4489        request = _load_cert(path, loader_func, backend)
4490        assert isinstance(request.signature_hash_algorithm, hashes.SHA1)
4491        public_key = request.public_key()
4492        assert isinstance(public_key, dsa.DSAPublicKey)
4493        subject = request.subject
4494        assert isinstance(subject, x509.Name)
4495        assert list(subject) == [
4496            x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
4497            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
4498            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4499            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
4500            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
4501        ]
4502
4503    def test_signature(self, backend):
4504        request = _load_cert(
4505            os.path.join("x509", "requests", "dsa_sha1.pem"),
4506            x509.load_pem_x509_csr,
4507            backend,
4508        )
4509        assert request.signature == binascii.unhexlify(
4510            b"302c021461d58dc028d0110818a7d817d74235727c4acfdf0214097b52e198e"
4511            b"ce95de17273f0a924df23ce9d8188"
4512        )
4513
4514    def test_tbs_certrequest_bytes(self, backend):
4515        request = _load_cert(
4516            os.path.join("x509", "requests", "dsa_sha1.pem"),
4517            x509.load_pem_x509_csr,
4518            backend,
4519        )
4520        assert request.tbs_certrequest_bytes == binascii.unhexlify(
4521            b"3082021802010030573118301606035504030c0f63727970746f677261706879"
4522            b"2e696f310d300b060355040a0c0450794341310b300906035504061302555331"
4523            b"0e300c06035504080c055465786173310f300d06035504070c0641757374696e"
4524            b"308201b63082012b06072a8648ce3804013082011e028181008d7fadbc09e284"
4525            b"aafa69154cea24177004909e519f8b35d685cde5b4ecdc9583e74d370a0f88ad"
4526            b"a98f026f27762fb3d5da7836f986dfcdb3589e5b925bea114defc03ef81dae30"
4527            b"c24bbc6df3d588e93427bba64203d4a5b1687b2b5e3b643d4c614976f89f95a3"
4528            b"8d3e4c89065fba97514c22c50adbbf289163a74b54859b35b7021500835de56b"
4529            b"d07cf7f82e2032fe78949aed117aa2ef0281801f717b5a07782fc2e4e68e311f"
4530            b"ea91a54edd36b86ac634d14f05a68a97eae9d2ef31fb1ef3de42c3d100df9ca6"
4531            b"4f5bdc2aec7bfdfb474cf831fea05853b5e059f2d24980a0ac463f1e818af352"
4532            b"3e3cb79a39d45fa92731897752842469cf8540b01491024eaafbce6018e8a1f4"
4533            b"658c343f4ba7c0b21e5376a21f4beb8491961e038184000281800713f07641f6"
4534            b"369bb5a9545274a2d4c01998367fb371bb9e13436363672ed68f82174c2de05c"
4535            b"8e839bc6de568dd50ba28d8d9d8719423aaec5557df10d773ab22d6d65cbb878"
4536            b"04a697bc8fd965b952f9f7e850edf13c8acdb5d753b6d10e59e0b5732e3c82ba"
4537            b"fa140342bc4a3bba16bd0681c8a6a2dbbb7efe6ce2b8463b170ba000"
4538        )
4539        request.public_key().verify(
4540            request.signature,
4541            request.tbs_certrequest_bytes,
4542            request.signature_hash_algorithm,
4543        )
4544
4545
4546@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
4547@pytest.mark.requires_backend_interface(interface=X509Backend)
4548class TestECDSACertificate(object):
4549    def test_load_ecdsa_cert(self, backend):
4550        _skip_curve_unsupported(backend, ec.SECP384R1())
4551        cert = _load_cert(
4552            os.path.join("x509", "ecdsa_root.pem"),
4553            x509.load_pem_x509_certificate,
4554            backend,
4555        )
4556        assert isinstance(cert.signature_hash_algorithm, hashes.SHA384)
4557        public_key = cert.public_key()
4558        assert isinstance(public_key, ec.EllipticCurvePublicKey)
4559        num = public_key.public_numbers()
4560        assert num.x == int(
4561            "dda7d9bb8ab80bfb0b7f21d2f0bebe73f3335d1abc34eadec69bbcd095f"
4562            "6f0ccd00bba615b51467e9e2d9fee8e630c17",
4563            16,
4564        )
4565        assert num.y == int(
4566            "ec0770f5cf842e40839ce83f416d3badd3a4145936789d0343ee10136c7"
4567            "2deae88a7a16bb543ce67dc23ff031ca3e23e",
4568            16,
4569        )
4570        assert isinstance(num.curve, ec.SECP384R1)
4571
4572    def test_signature(self, backend):
4573        cert = _load_cert(
4574            os.path.join("x509", "ecdsa_root.pem"),
4575            x509.load_pem_x509_certificate,
4576            backend,
4577        )
4578        assert cert.signature == binascii.unhexlify(
4579            b"3065023100adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085"
4580            b"a763f99e32de66930ff1ccb1098fdd6cabfa6b7fa0023039665bc2648db89e50"
4581            b"dca8d549a2edc7dcd1497f1701b8c8868f4e8c882ba89aa98ac5d100bdf854e2"
4582            b"9ae55b7cb32717"
4583        )
4584        r, s = decode_dss_signature(cert.signature)
4585        assert r == int(
4586            "adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085a763f99e32"
4587            "de66930ff1ccb1098fdd6cabfa6b7fa0",
4588            16,
4589        )
4590        assert s == int(
4591            "39665bc2648db89e50dca8d549a2edc7dcd1497f1701b8c8868f4e8c882ba89a"
4592            "a98ac5d100bdf854e29ae55b7cb32717",
4593            16,
4594        )
4595
4596    def test_tbs_certificate_bytes(self, backend):
4597        _skip_curve_unsupported(backend, ec.SECP384R1())
4598        cert = _load_cert(
4599            os.path.join("x509", "ecdsa_root.pem"),
4600            x509.load_pem_x509_certificate,
4601            backend,
4602        )
4603        assert cert.tbs_certificate_bytes == binascii.unhexlify(
4604            b"308201c5a0030201020210055556bcf25ea43535c3a40fd5ab4572300a06082"
4605            b"a8648ce3d0403033061310b300906035504061302555331153013060355040a"
4606            b"130c446967694365727420496e6331193017060355040b13107777772e64696"
4607            b"769636572742e636f6d3120301e06035504031317446967694365727420476c"
4608            b"6f62616c20526f6f74204733301e170d3133303830313132303030305a170d3"
4609            b"338303131353132303030305a3061310b300906035504061302555331153013"
4610            b"060355040a130c446967694365727420496e6331193017060355040b1310777"
4611            b"7772e64696769636572742e636f6d3120301e06035504031317446967694365"
4612            b"727420476c6f62616c20526f6f742047333076301006072a8648ce3d0201060"
4613            b"52b8104002203620004dda7d9bb8ab80bfb0b7f21d2f0bebe73f3335d1abc34"
4614            b"eadec69bbcd095f6f0ccd00bba615b51467e9e2d9fee8e630c17ec0770f5cf8"
4615            b"42e40839ce83f416d3badd3a4145936789d0343ee10136c72deae88a7a16bb5"
4616            b"43ce67dc23ff031ca3e23ea3423040300f0603551d130101ff040530030101f"
4617            b"f300e0603551d0f0101ff040403020186301d0603551d0e04160414b3db48a4"
4618            b"f9a1c5d8ae3641cc1163696229bc4bc6"
4619        )
4620        cert.public_key().verify(
4621            cert.signature,
4622            cert.tbs_certificate_bytes,
4623            ec.ECDSA(cert.signature_hash_algorithm),
4624        )
4625
4626    def test_load_ecdsa_no_named_curve(self, backend):
4627        _skip_curve_unsupported(backend, ec.SECP256R1())
4628        cert = _load_cert(
4629            os.path.join("x509", "custom", "ec_no_named_curve.pem"),
4630            x509.load_pem_x509_certificate,
4631            backend,
4632        )
4633        with pytest.raises(NotImplementedError):
4634            cert.public_key()
4635
4636
4637@pytest.mark.requires_backend_interface(interface=X509Backend)
4638@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
4639class TestECDSACertificateRequest(object):
4640    @pytest.mark.parametrize(
4641        ("path", "loader_func"),
4642        [
4643            [
4644                os.path.join("x509", "requests", "ec_sha256.pem"),
4645                x509.load_pem_x509_csr,
4646            ],
4647            [
4648                os.path.join("x509", "requests", "ec_sha256.der"),
4649                x509.load_der_x509_csr,
4650            ],
4651        ],
4652    )
4653    def test_load_ecdsa_certificate_request(self, path, loader_func, backend):
4654        _skip_curve_unsupported(backend, ec.SECP384R1())
4655        request = _load_cert(path, loader_func, backend)
4656        assert isinstance(request.signature_hash_algorithm, hashes.SHA256)
4657        public_key = request.public_key()
4658        assert isinstance(public_key, ec.EllipticCurvePublicKey)
4659        subject = request.subject
4660        assert isinstance(subject, x509.Name)
4661        assert list(subject) == [
4662            x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
4663            x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
4664            x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4665            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Texas"),
4666            x509.NameAttribute(NameOID.LOCALITY_NAME, u"Austin"),
4667        ]
4668
4669    def test_signature(self, backend):
4670        _skip_curve_unsupported(backend, ec.SECP384R1())
4671        request = _load_cert(
4672            os.path.join("x509", "requests", "ec_sha256.pem"),
4673            x509.load_pem_x509_csr,
4674            backend,
4675        )
4676        assert request.signature == binascii.unhexlify(
4677            b"306502302c1a9f7de8c1787332d2307a886b476a59f172b9b0e250262f3238b1"
4678            b"b45ee112bb6eb35b0fb56a123b9296eb212dffc302310094cf440c95c52827d5"
4679            b"56ae6d76500e3008255d47c29f7ee782ed7558e51bfd76aa45df6d999ed5c463"
4680            b"347fe2382d1751"
4681        )
4682
4683    def test_tbs_certrequest_bytes(self, backend):
4684        _skip_curve_unsupported(backend, ec.SECP384R1())
4685        request = _load_cert(
4686            os.path.join("x509", "requests", "ec_sha256.pem"),
4687            x509.load_pem_x509_csr,
4688            backend,
4689        )
4690        assert request.tbs_certrequest_bytes == binascii.unhexlify(
4691            b"3081d602010030573118301606035504030c0f63727970746f6772617068792"
4692            b"e696f310d300b060355040a0c0450794341310b300906035504061302555331"
4693            b"0e300c06035504080c055465786173310f300d06035504070c0641757374696"
4694            b"e3076301006072a8648ce3d020106052b8104002203620004de19b514c0b3c3"
4695            b"ae9b398ea3e26b5e816bdcf9102cad8f12fe02f9e4c9248724b39297ed7582e"
4696            b"04d8b32a551038d09086803a6d3fb91a1a1167ec02158b00efad39c9396462f"
4697            b"accff0ffaf7155812909d3726bd59fde001cff4bb9b2f5af8cbaa000"
4698        )
4699        request.public_key().verify(
4700            request.signature,
4701            request.tbs_certrequest_bytes,
4702            ec.ECDSA(request.signature_hash_algorithm),
4703        )
4704
4705
4706@pytest.mark.requires_backend_interface(interface=X509Backend)
4707class TestOtherCertificate(object):
4708    def test_unsupported_subject_public_key_info(self, backend):
4709        cert = _load_cert(
4710            os.path.join(
4711                "x509", "custom", "unsupported_subject_public_key_info.pem"
4712            ),
4713            x509.load_pem_x509_certificate,
4714            backend,
4715        )
4716
4717        with pytest.raises(ValueError):
4718            cert.public_key()
4719
4720    def test_bad_time_in_validity(self, backend):
4721        cert = _load_cert(
4722            os.path.join("x509", "badasn1time.pem"),
4723            x509.load_pem_x509_certificate,
4724            backend,
4725        )
4726
4727        with pytest.raises(ValueError, match="19020701025736Z"):
4728            cert.not_valid_after
4729
4730
4731class TestNameAttribute(object):
4732    EXPECTED_TYPES = [
4733        (NameOID.COMMON_NAME, _ASN1Type.UTF8String),
4734        (NameOID.COUNTRY_NAME, _ASN1Type.PrintableString),
4735        (NameOID.LOCALITY_NAME, _ASN1Type.UTF8String),
4736        (NameOID.STATE_OR_PROVINCE_NAME, _ASN1Type.UTF8String),
4737        (NameOID.STREET_ADDRESS, _ASN1Type.UTF8String),
4738        (NameOID.ORGANIZATION_NAME, _ASN1Type.UTF8String),
4739        (NameOID.ORGANIZATIONAL_UNIT_NAME, _ASN1Type.UTF8String),
4740        (NameOID.SERIAL_NUMBER, _ASN1Type.PrintableString),
4741        (NameOID.SURNAME, _ASN1Type.UTF8String),
4742        (NameOID.GIVEN_NAME, _ASN1Type.UTF8String),
4743        (NameOID.TITLE, _ASN1Type.UTF8String),
4744        (NameOID.GENERATION_QUALIFIER, _ASN1Type.UTF8String),
4745        (NameOID.X500_UNIQUE_IDENTIFIER, _ASN1Type.UTF8String),
4746        (NameOID.DN_QUALIFIER, _ASN1Type.PrintableString),
4747        (NameOID.PSEUDONYM, _ASN1Type.UTF8String),
4748        (NameOID.USER_ID, _ASN1Type.UTF8String),
4749        (NameOID.DOMAIN_COMPONENT, _ASN1Type.IA5String),
4750        (NameOID.EMAIL_ADDRESS, _ASN1Type.IA5String),
4751        (NameOID.JURISDICTION_COUNTRY_NAME, _ASN1Type.PrintableString),
4752        (NameOID.JURISDICTION_LOCALITY_NAME, _ASN1Type.UTF8String),
4753        (NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME, _ASN1Type.UTF8String),
4754        (NameOID.BUSINESS_CATEGORY, _ASN1Type.UTF8String),
4755        (NameOID.POSTAL_ADDRESS, _ASN1Type.UTF8String),
4756        (NameOID.POSTAL_CODE, _ASN1Type.UTF8String),
4757    ]
4758
4759    def test_default_types(self):
4760        for oid, asn1_type in TestNameAttribute.EXPECTED_TYPES:
4761            na = x509.NameAttribute(oid, u"US")
4762            assert na._type == asn1_type
4763
4764    def test_alternate_type(self):
4765        na2 = x509.NameAttribute(
4766            NameOID.COMMON_NAME, u"common", _ASN1Type.IA5String
4767        )
4768        assert na2._type == _ASN1Type.IA5String
4769
4770    def test_init_bad_oid(self):
4771        with pytest.raises(TypeError):
4772            x509.NameAttribute(None, u"value")
4773
4774    def test_init_bad_value(self):
4775        with pytest.raises(TypeError):
4776            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), b"bytes")
4777
4778    def test_init_none_value(self):
4779        with pytest.raises(TypeError):
4780            x509.NameAttribute(NameOID.ORGANIZATION_NAME, None)
4781
4782    def test_init_bad_country_code_value(self):
4783        with pytest.raises(ValueError):
4784            x509.NameAttribute(NameOID.COUNTRY_NAME, u"United States")
4785
4786        # unicode string of length 2, but > 2 bytes
4787        with pytest.raises(ValueError):
4788            x509.NameAttribute(NameOID.COUNTRY_NAME, u"\U0001F37A\U0001F37A")
4789
4790    def test_invalid_type(self):
4791        with pytest.raises(TypeError):
4792            x509.NameAttribute(NameOID.COMMON_NAME, u"common", "notanenum")
4793
4794    def test_eq(self):
4795        assert x509.NameAttribute(
4796            x509.ObjectIdentifier("2.999.1"), u"value"
4797        ) == x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value")
4798
4799    def test_ne(self):
4800        assert x509.NameAttribute(
4801            x509.ObjectIdentifier("2.5.4.3"), u"value"
4802        ) != x509.NameAttribute(x509.ObjectIdentifier("2.5.4.5"), u"value")
4803        assert x509.NameAttribute(
4804            x509.ObjectIdentifier("2.999.1"), u"value"
4805        ) != x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2")
4806        assert (
4807            x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value")
4808            != object()
4809        )
4810
4811    def test_repr(self):
4812        na = x509.NameAttribute(x509.ObjectIdentifier("2.5.4.3"), u"value")
4813        if not six.PY2:
4814            assert repr(na) == (
4815                "<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commo"
4816                "nName)>, value='value')>"
4817            )
4818        else:
4819            assert repr(na) == (
4820                "<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commo"
4821                "nName)>, value=u'value')>"
4822            )
4823
4824    def test_distinugished_name(self):
4825        # Escaping
4826        na = x509.NameAttribute(NameOID.COMMON_NAME, u'James "Jim" Smith, III')
4827        assert na.rfc4514_string() == r"CN=James \"Jim\" Smith\, III"
4828        na = x509.NameAttribute(NameOID.USER_ID, u"# escape+,;\0this ")
4829        assert na.rfc4514_string() == r"UID=\# escape\+\,\;\00this\ "
4830
4831        # Nonstandard attribute OID
4832        na = x509.NameAttribute(NameOID.EMAIL_ADDRESS, u"somebody@example.com")
4833        assert (
4834            na.rfc4514_string() == "1.2.840.113549.1.9.1=somebody@example.com"
4835        )
4836
4837    def test_empty_value(self):
4838        na = x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"")
4839        assert na.rfc4514_string() == r"ST="
4840
4841
4842class TestRelativeDistinguishedName(object):
4843    def test_init_empty(self):
4844        with pytest.raises(ValueError):
4845            x509.RelativeDistinguishedName([])
4846
4847    def test_init_not_nameattribute(self):
4848        with pytest.raises(TypeError):
4849            x509.RelativeDistinguishedName(["not-a-NameAttribute"])
4850
4851    def test_init_duplicate_attribute(self):
4852        with pytest.raises(ValueError):
4853            x509.RelativeDistinguishedName(
4854                [
4855                    x509.NameAttribute(
4856                        x509.ObjectIdentifier("2.999.1"), u"val1"
4857                    ),
4858                    x509.NameAttribute(
4859                        x509.ObjectIdentifier("2.999.1"), u"val1"
4860                    ),
4861                ]
4862            )
4863
4864    def test_hash(self):
4865        rdn1 = x509.RelativeDistinguishedName(
4866            [
4867                x509.NameAttribute(
4868                    x509.ObjectIdentifier("2.999.1"), u"value1"
4869                ),
4870                x509.NameAttribute(
4871                    x509.ObjectIdentifier("2.999.2"), u"value2"
4872                ),
4873            ]
4874        )
4875        rdn2 = x509.RelativeDistinguishedName(
4876            [
4877                x509.NameAttribute(
4878                    x509.ObjectIdentifier("2.999.2"), u"value2"
4879                ),
4880                x509.NameAttribute(
4881                    x509.ObjectIdentifier("2.999.1"), u"value1"
4882                ),
4883            ]
4884        )
4885        rdn3 = x509.RelativeDistinguishedName(
4886            [
4887                x509.NameAttribute(
4888                    x509.ObjectIdentifier("2.999.1"), u"value1"
4889                ),
4890                x509.NameAttribute(
4891                    x509.ObjectIdentifier("2.999.2"), u"value3"
4892                ),
4893            ]
4894        )
4895        assert hash(rdn1) == hash(rdn2)
4896        assert hash(rdn1) != hash(rdn3)
4897
4898    def test_eq(self):
4899        rdn1 = x509.RelativeDistinguishedName(
4900            [
4901                x509.NameAttribute(
4902                    x509.ObjectIdentifier("2.999.1"), u"value1"
4903                ),
4904                x509.NameAttribute(
4905                    x509.ObjectIdentifier("2.999.2"), u"value2"
4906                ),
4907            ]
4908        )
4909        rdn2 = x509.RelativeDistinguishedName(
4910            [
4911                x509.NameAttribute(
4912                    x509.ObjectIdentifier("2.999.2"), u"value2"
4913                ),
4914                x509.NameAttribute(
4915                    x509.ObjectIdentifier("2.999.1"), u"value1"
4916                ),
4917            ]
4918        )
4919        assert rdn1 == rdn2
4920
4921    def test_ne(self):
4922        rdn1 = x509.RelativeDistinguishedName(
4923            [
4924                x509.NameAttribute(
4925                    x509.ObjectIdentifier("2.999.1"), u"value1"
4926                ),
4927                x509.NameAttribute(
4928                    x509.ObjectIdentifier("2.999.2"), u"value2"
4929                ),
4930            ]
4931        )
4932        rdn2 = x509.RelativeDistinguishedName(
4933            [
4934                x509.NameAttribute(
4935                    x509.ObjectIdentifier("2.999.1"), u"value1"
4936                ),
4937                x509.NameAttribute(
4938                    x509.ObjectIdentifier("2.999.2"), u"value3"
4939                ),
4940            ]
4941        )
4942        assert rdn1 != rdn2
4943        assert rdn1 != object()
4944
4945    def test_iter_input(self):
4946        # Order must be preserved too
4947        attrs = [
4948            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1"),
4949            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value2"),
4950            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value3"),
4951        ]
4952        rdn = x509.RelativeDistinguishedName(iter(attrs))
4953        assert list(rdn) == attrs
4954        assert list(rdn) == attrs
4955
4956    def test_get_attributes_for_oid(self):
4957        oid = x509.ObjectIdentifier("2.999.1")
4958        attr = x509.NameAttribute(oid, u"value1")
4959        rdn = x509.RelativeDistinguishedName([attr])
4960        assert rdn.get_attributes_for_oid(oid) == [attr]
4961        assert rdn.get_attributes_for_oid(x509.ObjectIdentifier("1.2.3")) == []
4962
4963
4964class TestObjectIdentifier(object):
4965    def test_eq(self):
4966        oid1 = x509.ObjectIdentifier("2.999.1")
4967        oid2 = x509.ObjectIdentifier("2.999.1")
4968        assert oid1 == oid2
4969
4970    def test_ne(self):
4971        oid1 = x509.ObjectIdentifier("2.999.1")
4972        assert oid1 != x509.ObjectIdentifier("2.999.2")
4973        assert oid1 != object()
4974
4975    def test_repr(self):
4976        oid = x509.ObjectIdentifier("2.5.4.3")
4977        assert repr(oid) == "<ObjectIdentifier(oid=2.5.4.3, name=commonName)>"
4978        oid = x509.ObjectIdentifier("2.999.1")
4979        assert repr(oid) == "<ObjectIdentifier(oid=2.999.1, name=Unknown OID)>"
4980
4981    def test_name_property(self):
4982        oid = x509.ObjectIdentifier("2.5.4.3")
4983        assert oid._name == "commonName"
4984        oid = x509.ObjectIdentifier("2.999.1")
4985        assert oid._name == "Unknown OID"
4986
4987    def test_too_short(self):
4988        with pytest.raises(ValueError):
4989            x509.ObjectIdentifier("1")
4990
4991    def test_invalid_input(self):
4992        with pytest.raises(ValueError):
4993            x509.ObjectIdentifier("notavalidform")
4994
4995    def test_invalid_node1(self):
4996        with pytest.raises(ValueError):
4997            x509.ObjectIdentifier("7.1.37")
4998
4999    def test_invalid_node2(self):
5000        with pytest.raises(ValueError):
5001            x509.ObjectIdentifier("1.50.200")
5002
5003    def test_valid(self):
5004        x509.ObjectIdentifier("0.35.200")
5005        x509.ObjectIdentifier("1.39.999")
5006        x509.ObjectIdentifier("2.5.29.3")
5007        x509.ObjectIdentifier("2.999.37.5.22.8")
5008        x509.ObjectIdentifier("2.25.305821105408246119474742976030998643995")
5009
5010
5011class TestName(object):
5012    def test_eq(self):
5013        ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
5014        ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
5015        name1 = x509.Name([ava1, ava2])
5016        name2 = x509.Name(
5017            [
5018                x509.RelativeDistinguishedName([ava1]),
5019                x509.RelativeDistinguishedName([ava2]),
5020            ]
5021        )
5022        name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
5023        name4 = x509.Name([x509.RelativeDistinguishedName([ava2, ava1])])
5024        assert name1 == name2
5025        assert name3 == name4
5026
5027    def test_ne(self):
5028        ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
5029        ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
5030        name1 = x509.Name([ava1, ava2])
5031        name2 = x509.Name([ava2, ava1])
5032        name3 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
5033        assert name1 != name2
5034        assert name1 != name3
5035        assert name1 != object()
5036
5037    def test_hash(self):
5038        ava1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
5039        ava2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
5040        name1 = x509.Name([ava1, ava2])
5041        name2 = x509.Name(
5042            [
5043                x509.RelativeDistinguishedName([ava1]),
5044                x509.RelativeDistinguishedName([ava2]),
5045            ]
5046        )
5047        name3 = x509.Name([ava2, ava1])
5048        name4 = x509.Name([x509.RelativeDistinguishedName([ava1, ava2])])
5049        name5 = x509.Name([x509.RelativeDistinguishedName([ava2, ava1])])
5050        assert hash(name1) == hash(name2)
5051        assert hash(name1) != hash(name3)
5052        assert hash(name1) != hash(name4)
5053        assert hash(name4) == hash(name5)
5054
5055    def test_iter_input(self):
5056        attrs = [
5057            x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
5058        ]
5059        name = x509.Name(iter(attrs))
5060        assert list(name) == attrs
5061        assert list(name) == attrs
5062
5063    def test_rdns(self):
5064        rdn1 = x509.NameAttribute(x509.ObjectIdentifier("2.999.1"), u"value1")
5065        rdn2 = x509.NameAttribute(x509.ObjectIdentifier("2.999.2"), u"value2")
5066        name1 = x509.Name([rdn1, rdn2])
5067        assert name1.rdns == [
5068            x509.RelativeDistinguishedName([rdn1]),
5069            x509.RelativeDistinguishedName([rdn2]),
5070        ]
5071        name2 = x509.Name([x509.RelativeDistinguishedName([rdn1, rdn2])])
5072        assert name2.rdns == [x509.RelativeDistinguishedName([rdn1, rdn2])]
5073
5074    @pytest.mark.parametrize(
5075        ("common_name", "org_name", "expected_repr"),
5076        [
5077            (
5078                u"cryptography.io",
5079                u"PyCA",
5080                "<Name(CN=cryptography.io,O=PyCA)>",
5081            ),
5082            (
5083                u"Certificación",
5084                u"Certificación",
5085                "<Name(CN=Certificación,O=Certificación)>",
5086            ),
5087        ],
5088    )
5089    def test_repr(self, common_name, org_name, expected_repr):
5090        name = x509.Name(
5091            [
5092                x509.NameAttribute(NameOID.COMMON_NAME, common_name),
5093                x509.NameAttribute(NameOID.ORGANIZATION_NAME, org_name),
5094            ]
5095        )
5096
5097        assert repr(name) == expected_repr
5098
5099    def test_rfc4514_string(self):
5100        n = x509.Name(
5101            [
5102                x509.RelativeDistinguishedName(
5103                    [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"net")]
5104                ),
5105                x509.RelativeDistinguishedName(
5106                    [x509.NameAttribute(NameOID.DOMAIN_COMPONENT, u"example")]
5107                ),
5108                x509.RelativeDistinguishedName(
5109                    [
5110                        x509.NameAttribute(
5111                            NameOID.ORGANIZATIONAL_UNIT_NAME, u"Sales"
5112                        ),
5113                        x509.NameAttribute(NameOID.COMMON_NAME, u"J.  Smith"),
5114                    ]
5115                ),
5116            ]
5117        )
5118        assert n.rfc4514_string() == "OU=Sales+CN=J.  Smith,DC=example,DC=net"
5119
5120    def test_rfc4514_string_empty_values(self):
5121        n = x509.Name(
5122            [
5123                x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
5124                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u""),
5125                x509.NameAttribute(NameOID.LOCALITY_NAME, u""),
5126                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
5127                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
5128            ]
5129        )
5130        assert n.rfc4514_string() == "CN=cryptography.io,O=PyCA,L=,ST=,C=US"
5131
5132    def test_not_nameattribute(self):
5133        with pytest.raises(TypeError):
5134            x509.Name(["not-a-NameAttribute"])
5135
5136    @pytest.mark.requires_backend_interface(interface=X509Backend)
5137    def test_bytes(self, backend):
5138        name = x509.Name(
5139            [
5140                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io"),
5141                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
5142            ]
5143        )
5144        assert name.public_bytes(backend) == binascii.unhexlify(
5145            b"30293118301606035504030c0f63727970746f6772617068792e696f310d300"
5146            b"b060355040a0c0450794341"
5147        )
5148
5149    @pytest.mark.requires_backend_interface(interface=X509Backend)
5150    def test_bmpstring_bytes(self, backend):
5151        # For this test we need an odd length string. BMPString is UCS-2
5152        # encoded so it will always be even length and OpenSSL will error if
5153        # you pass an odd length string without encoding it properly first.
5154        name = x509.Name(
5155            [
5156                x509.NameAttribute(
5157                    NameOID.COMMON_NAME,
5158                    u"cryptography.io",
5159                    _ASN1Type.BMPString,
5160                ),
5161                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
5162            ]
5163        )
5164        assert name.public_bytes(backend) == binascii.unhexlify(
5165            b"30383127302506035504031e1e00630072007900700074006f00670072006100"
5166            b"7000680079002e0069006f310d300b060355040a0c0450794341"
5167        )
5168
5169    @pytest.mark.requires_backend_interface(interface=X509Backend)
5170    def test_universalstring_bytes(self, backend):
5171        # UniversalString is UCS-4
5172        name = x509.Name(
5173            [
5174                x509.NameAttribute(
5175                    NameOID.COMMON_NAME,
5176                    u"cryptography.io",
5177                    _ASN1Type.UniversalString,
5178                ),
5179                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"PyCA"),
5180            ]
5181        )
5182        assert name.public_bytes(backend) == binascii.unhexlify(
5183            b"30563145304306035504031c3c00000063000000720000007900000070000000"
5184            b"740000006f000000670000007200000061000000700000006800000079000000"
5185            b"2e000000690000006f310d300b060355040a0c0450794341"
5186        )
5187
5188
5189@pytest.mark.supported(
5190    only_if=lambda backend: backend.ed25519_supported(),
5191    skip_message="Requires OpenSSL with Ed25519 support",
5192)
5193@pytest.mark.requires_backend_interface(interface=X509Backend)
5194class TestEd25519Certificate(object):
5195    def test_load_pem_cert(self, backend):
5196        cert = _load_cert(
5197            os.path.join("x509", "ed25519", "root-ed25519.pem"),
5198            x509.load_pem_x509_certificate,
5199            backend,
5200        )
5201        # self-signed, so this will work
5202        cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes)
5203        assert isinstance(cert, x509.Certificate)
5204        assert cert.serial_number == 9579446940964433301
5205        assert cert.signature_hash_algorithm is None
5206        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED25519
5207
5208    def test_deepcopy(self, backend):
5209        cert = _load_cert(
5210            os.path.join("x509", "ed25519", "root-ed25519.pem"),
5211            x509.load_pem_x509_certificate,
5212            backend,
5213        )
5214        assert copy.deepcopy(cert) is cert
5215
5216
5217@pytest.mark.supported(
5218    only_if=lambda backend: backend.ed448_supported(),
5219    skip_message="Requires OpenSSL with Ed448 support",
5220)
5221@pytest.mark.requires_backend_interface(interface=X509Backend)
5222class TestEd448Certificate(object):
5223    def test_load_pem_cert(self, backend):
5224        cert = _load_cert(
5225            os.path.join("x509", "ed448", "root-ed448.pem"),
5226            x509.load_pem_x509_certificate,
5227            backend,
5228        )
5229        # self-signed, so this will work
5230        cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes)
5231        assert isinstance(cert, x509.Certificate)
5232        assert cert.serial_number == 448
5233        assert cert.signature_hash_algorithm is None
5234        assert cert.signature_algorithm_oid == SignatureAlgorithmOID.ED448
5235
5236
5237@pytest.mark.requires_backend_interface(interface=X509Backend)
5238class TestSignatureRejection(object):
5239    """Test if signing rejects DH keys properly."""
5240
5241    def load_key(self, backend):
5242        vector = load_vectors_from_file(
5243            os.path.join("asymmetric", "DH", "rfc3526.txt"),
5244            load_nist_vectors,
5245        )[1]
5246        p = int_from_bytes(binascii.unhexlify(vector["p"]), "big")
5247        params = dh.DHParameterNumbers(p, int(vector["g"]))
5248        param = params.parameters(backend)
5249        return param.generate_private_key()
5250
5251    def test_crt_signing_check(self, backend):
5252        issuer_private_key = self.load_key(backend)
5253        public_key = RSA_KEY_2048.private_key(backend).public_key()
5254        not_valid_before = datetime.datetime(2020, 1, 1, 1, 1)
5255        not_valid_after = datetime.datetime(2050, 12, 31, 8, 30)
5256        builder = (
5257            x509.CertificateBuilder()
5258            .serial_number(777)
5259            .issuer_name(
5260                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
5261            )
5262            .subject_name(
5263                x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
5264            )
5265            .public_key(public_key)
5266            .not_valid_before(not_valid_before)
5267            .not_valid_after(not_valid_after)
5268        )
5269
5270        with pytest.raises(TypeError):
5271            builder.sign(issuer_private_key, hashes.SHA256(), backend)
5272
5273    def test_csr_signing_check(self, backend):
5274        private_key = self.load_key(backend)
5275        builder = x509.CertificateSigningRequestBuilder().subject_name(
5276            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u"US")])
5277        )
5278
5279        with pytest.raises(TypeError):
5280            builder.sign(private_key, hashes.SHA256(), backend)
5281
5282    def test_crl_signing_check(self, backend):
5283        private_key = self.load_key(backend)
5284        last_time = datetime.datetime.utcnow().replace(microsecond=0)
5285        next_time = last_time
5286        builder = (
5287            x509.CertificateRevocationListBuilder()
5288            .issuer_name(
5289                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"CA")])
5290            )
5291            .last_update(last_time)
5292            .next_update(next_time)
5293        )
5294
5295        with pytest.raises(TypeError):
5296            builder.sign(private_key, hashes.SHA256(), backend)
5297
5298
5299def test_random_serial_number(monkeypatch):
5300    sample_data = os.urandom(20)
5301
5302    def notrandom(size):
5303        assert size == len(sample_data)
5304        return sample_data
5305
5306    monkeypatch.setattr(os, "urandom", notrandom)
5307
5308    serial_number = x509.random_serial_number()
5309
5310    assert serial_number == utils.int_from_bytes(sample_data, "big") >> 1
5311    assert serial_number.bit_length() < 160
5312