• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
4
5from __future__ import absolute_import, division, print_function
6
7import binascii
8import datetime
9import ipaddress
10import os
11
12import pytest
13
14import six
15
16from cryptography import utils, x509
17from cryptography.hazmat.backends.interfaces import (
18    DSABackend, EllipticCurveBackend, RSABackend, X509Backend
19)
20from cryptography.hazmat.primitives import hashes
21from cryptography.hazmat.primitives.asymmetric import ec
22from cryptography.x509 import DNSName, NameConstraints, SubjectAlternativeName
23from cryptography.x509.general_name import _lazy_import_idna
24from cryptography.x509.oid import (
25    AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID,
26    NameOID, ObjectIdentifier
27)
28
29from .test_x509 import _load_cert
30from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048
31from ..hazmat.primitives.test_ec import _skip_curve_unsupported
32
33
34def _make_certbuilder(private_key):
35    name = x509.Name(
36        [x509.NameAttribute(NameOID.COMMON_NAME, u'example.org')])
37    return (
38        x509.CertificateBuilder()
39            .subject_name(name)
40            .issuer_name(name)
41            .public_key(private_key.public_key())
42            .serial_number(777)
43            .not_valid_before(datetime.datetime(1999, 1, 1))
44            .not_valid_after(datetime.datetime(2020, 1, 1))
45    )
46
47
48def test_lazy_idna_import():
49    try:
50        __import__("idna")
51        pytest.skip("idna is installed")
52    except ImportError:
53        pass
54
55    with pytest.raises(ImportError):
56        _lazy_import_idna()
57
58
59class TestExtension(object):
60    def test_not_an_oid(self):
61        bc = x509.BasicConstraints(ca=False, path_length=None)
62        with pytest.raises(TypeError):
63            x509.Extension("notanoid", True, bc)
64
65    def test_critical_not_a_bool(self):
66        bc = x509.BasicConstraints(ca=False, path_length=None)
67        with pytest.raises(TypeError):
68            x509.Extension(ExtensionOID.BASIC_CONSTRAINTS, "notabool", bc)
69
70    def test_repr(self):
71        bc = x509.BasicConstraints(ca=False, path_length=None)
72        ext = x509.Extension(ExtensionOID.BASIC_CONSTRAINTS, True, bc)
73        assert repr(ext) == (
74            "<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConst"
75            "raints)>, critical=True, value=<BasicConstraints(ca=False, path"
76            "_length=None)>)>"
77        )
78
79    def test_eq(self):
80        ext1 = x509.Extension(
81            x509.ObjectIdentifier('1.2.3.4'), False, 'value'
82        )
83        ext2 = x509.Extension(
84            x509.ObjectIdentifier('1.2.3.4'), False, 'value'
85        )
86        assert ext1 == ext2
87
88    def test_ne(self):
89        ext1 = x509.Extension(
90            x509.ObjectIdentifier('1.2.3.4'), False, 'value'
91        )
92        ext2 = x509.Extension(
93            x509.ObjectIdentifier('1.2.3.5'), False, 'value'
94        )
95        ext3 = x509.Extension(
96            x509.ObjectIdentifier('1.2.3.4'), True, 'value'
97        )
98        ext4 = x509.Extension(
99            x509.ObjectIdentifier('1.2.3.4'), False, 'value4'
100        )
101        assert ext1 != ext2
102        assert ext1 != ext3
103        assert ext1 != ext4
104        assert ext1 != object()
105
106    def test_hash(self):
107        ext1 = x509.Extension(
108            ExtensionOID.BASIC_CONSTRAINTS,
109            False,
110            x509.BasicConstraints(ca=False, path_length=None)
111        )
112        ext2 = x509.Extension(
113            ExtensionOID.BASIC_CONSTRAINTS,
114            False,
115            x509.BasicConstraints(ca=False, path_length=None)
116        )
117        ext3 = x509.Extension(
118            ExtensionOID.BASIC_CONSTRAINTS,
119            False,
120            x509.BasicConstraints(ca=True, path_length=None)
121        )
122        assert hash(ext1) == hash(ext2)
123        assert hash(ext1) != hash(ext3)
124
125
126class TestTLSFeature(object):
127    def test_not_enum_type(self):
128        with pytest.raises(TypeError):
129            x509.TLSFeature([3])
130
131    def test_empty_list(self):
132        with pytest.raises(TypeError):
133            x509.TLSFeature([])
134
135    def test_repr(self):
136        ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
137        assert repr(ext1) == (
138            "<TLSFeature(features=[<TLSFeatureType.status_request: 5>])>"
139        )
140
141    def test_eq(self):
142        ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
143        ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request])
144        assert ext1 == ext2
145
146    def test_ne(self):
147        ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
148        ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request_v2])
149        ext3 = x509.TLSFeature([
150            x509.TLSFeatureType.status_request,
151            x509.TLSFeatureType.status_request_v2
152        ])
153        assert ext1 != ext2
154        assert ext1 != ext3
155        assert ext1 != object()
156
157    def test_hash(self):
158        ext1 = x509.TLSFeature([x509.TLSFeatureType.status_request])
159        ext2 = x509.TLSFeature([x509.TLSFeatureType.status_request])
160        ext3 = x509.TLSFeature([
161            x509.TLSFeatureType.status_request,
162            x509.TLSFeatureType.status_request_v2
163        ])
164        assert hash(ext1) == hash(ext2)
165        assert hash(ext1) != hash(ext3)
166
167    def test_iter(self):
168        ext1_features = [x509.TLSFeatureType.status_request]
169        ext1 = x509.TLSFeature(ext1_features)
170        assert len(ext1) == 1
171        assert list(ext1) == ext1_features
172        ext2_features = [
173            x509.TLSFeatureType.status_request,
174            x509.TLSFeatureType.status_request_v2,
175        ]
176        ext2 = x509.TLSFeature(ext2_features)
177        assert len(ext2) == 2
178        assert list(ext2) == ext2_features
179
180    def test_indexing(self):
181        ext = x509.TLSFeature([
182            x509.TLSFeatureType.status_request,
183            x509.TLSFeatureType.status_request_v2,
184        ])
185        assert ext[-1] == ext[1]
186        assert ext[0] == x509.TLSFeatureType.status_request
187
188
189class TestUnrecognizedExtension(object):
190    def test_invalid_oid(self):
191        with pytest.raises(TypeError):
192            x509.UnrecognizedExtension("notanoid", b"somedata")
193
194    def test_eq(self):
195        ext1 = x509.UnrecognizedExtension(
196            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
197        )
198        ext2 = x509.UnrecognizedExtension(
199            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
200        )
201        assert ext1 == ext2
202
203    def test_ne(self):
204        ext1 = x509.UnrecognizedExtension(
205            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
206        )
207        ext2 = x509.UnrecognizedExtension(
208            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x02"
209        )
210        ext3 = x509.UnrecognizedExtension(
211            x509.ObjectIdentifier("1.2.3.5"), b"\x03\x02\x01"
212        )
213        assert ext1 != ext2
214        assert ext1 != ext3
215        assert ext1 != object()
216
217    def test_repr(self):
218        ext1 = x509.UnrecognizedExtension(
219            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
220        )
221        if not six.PY2:
222            assert repr(ext1) == (
223                "<UnrecognizedExtension(oid=<ObjectIdentifier(oid=1.2.3.4, "
224                "name=Unknown OID)>, value=b'\\x03\\x02\\x01')>"
225            )
226        else:
227            assert repr(ext1) == (
228                "<UnrecognizedExtension(oid=<ObjectIdentifier(oid=1.2.3.4, "
229                "name=Unknown OID)>, value='\\x03\\x02\\x01')>"
230            )
231
232    def test_hash(self):
233        ext1 = x509.UnrecognizedExtension(
234            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
235        )
236        ext2 = x509.UnrecognizedExtension(
237            x509.ObjectIdentifier("1.2.3.4"), b"\x03\x02\x01"
238        )
239        ext3 = x509.UnrecognizedExtension(
240            x509.ObjectIdentifier("1.2.3.5"), b"\x03\x02\x01"
241        )
242        assert hash(ext1) == hash(ext2)
243        assert hash(ext1) != hash(ext3)
244
245
246class TestCertificateIssuer(object):
247    def test_iter_names(self):
248        ci = x509.CertificateIssuer([
249            x509.DNSName(u"cryptography.io"),
250            x509.DNSName(u"crypto.local"),
251        ])
252        assert len(ci) == 2
253        assert list(ci) == [
254            x509.DNSName(u"cryptography.io"),
255            x509.DNSName(u"crypto.local"),
256        ]
257
258    def test_indexing(self):
259        ci = x509.CertificateIssuer([
260            x509.DNSName(u"cryptography.io"),
261            x509.DNSName(u"crypto.local"),
262            x509.DNSName(u"another.local"),
263            x509.RFC822Name(u"email@another.local"),
264            x509.UniformResourceIdentifier(u"http://another.local"),
265        ])
266        assert ci[-1] == ci[4]
267        assert ci[2:6:2] == [ci[2], ci[4]]
268
269    def test_eq(self):
270        ci1 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
271        ci2 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
272        assert ci1 == ci2
273
274    def test_ne(self):
275        ci1 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
276        ci2 = x509.CertificateIssuer([x509.DNSName(u"somethingelse.tld")])
277        assert ci1 != ci2
278        assert ci1 != object()
279
280    def test_repr(self):
281        ci = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
282        if not six.PY2:
283            assert repr(ci) == (
284                "<CertificateIssuer(<GeneralNames([<DNSName(value="
285                "'cryptography.io')>])>)>"
286            )
287        else:
288            assert repr(ci) == (
289                "<CertificateIssuer(<GeneralNames([<DNSName(value="
290                "u'cryptography.io')>])>)>"
291            )
292
293    def test_get_values_for_type(self):
294        ci = x509.CertificateIssuer(
295            [x509.DNSName(u"cryptography.io")]
296        )
297        names = ci.get_values_for_type(x509.DNSName)
298        assert names == [u"cryptography.io"]
299
300    def test_hash(self):
301        ci1 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
302        ci2 = x509.CertificateIssuer([x509.DNSName(u"cryptography.io")])
303        ci3 = x509.CertificateIssuer(
304            [x509.UniformResourceIdentifier(u"http://something")]
305        )
306        assert hash(ci1) == hash(ci2)
307        assert hash(ci1) != hash(ci3)
308
309
310class TestCRLReason(object):
311    def test_invalid_reason_flags(self):
312        with pytest.raises(TypeError):
313            x509.CRLReason("notareason")
314
315    def test_eq(self):
316        reason1 = x509.CRLReason(x509.ReasonFlags.unspecified)
317        reason2 = x509.CRLReason(x509.ReasonFlags.unspecified)
318        assert reason1 == reason2
319
320    def test_ne(self):
321        reason1 = x509.CRLReason(x509.ReasonFlags.unspecified)
322        reason2 = x509.CRLReason(x509.ReasonFlags.ca_compromise)
323        assert reason1 != reason2
324        assert reason1 != object()
325
326    def test_hash(self):
327        reason1 = x509.CRLReason(x509.ReasonFlags.unspecified)
328        reason2 = x509.CRLReason(x509.ReasonFlags.unspecified)
329        reason3 = x509.CRLReason(x509.ReasonFlags.ca_compromise)
330
331        assert hash(reason1) == hash(reason2)
332        assert hash(reason1) != hash(reason3)
333
334    def test_repr(self):
335        reason1 = x509.CRLReason(x509.ReasonFlags.unspecified)
336        assert repr(reason1) == (
337            "<CRLReason(reason=ReasonFlags.unspecified)>"
338        )
339
340
341class TestDeltaCRLIndicator(object):
342    def test_not_int(self):
343        with pytest.raises(TypeError):
344            x509.DeltaCRLIndicator("notanint")
345
346    def test_eq(self):
347        delta1 = x509.DeltaCRLIndicator(1)
348        delta2 = x509.DeltaCRLIndicator(1)
349        assert delta1 == delta2
350
351    def test_ne(self):
352        delta1 = x509.DeltaCRLIndicator(1)
353        delta2 = x509.DeltaCRLIndicator(2)
354        assert delta1 != delta2
355        assert delta1 != object()
356
357    def test_repr(self):
358        delta1 = x509.DeltaCRLIndicator(2)
359        assert repr(delta1) == (
360            "<DeltaCRLIndicator(crl_number=2)>"
361        )
362
363    def test_hash(self):
364        delta1 = x509.DeltaCRLIndicator(1)
365        delta2 = x509.DeltaCRLIndicator(1)
366        delta3 = x509.DeltaCRLIndicator(2)
367        assert hash(delta1) == hash(delta2)
368        assert hash(delta1) != hash(delta3)
369
370
371class TestInvalidityDate(object):
372    def test_invalid_invalidity_date(self):
373        with pytest.raises(TypeError):
374            x509.InvalidityDate("notadate")
375
376    def test_eq(self):
377        invalid1 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1))
378        invalid2 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1))
379        assert invalid1 == invalid2
380
381    def test_ne(self):
382        invalid1 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1))
383        invalid2 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 2))
384        assert invalid1 != invalid2
385        assert invalid1 != object()
386
387    def test_repr(self):
388        invalid1 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1))
389        assert repr(invalid1) == (
390            "<InvalidityDate(invalidity_date=2015-01-01 01:01:00)>"
391        )
392
393    def test_hash(self):
394        invalid1 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1))
395        invalid2 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 1))
396        invalid3 = x509.InvalidityDate(datetime.datetime(2015, 1, 1, 1, 2))
397        assert hash(invalid1) == hash(invalid2)
398        assert hash(invalid1) != hash(invalid3)
399
400
401class TestNoticeReference(object):
402    def test_notice_numbers_not_all_int(self):
403        with pytest.raises(TypeError):
404            x509.NoticeReference("org", [1, 2, "three"])
405
406    def test_notice_numbers_none(self):
407        with pytest.raises(TypeError):
408            x509.NoticeReference("org", None)
409
410    def test_iter_input(self):
411        numbers = [1, 3, 4]
412        nr = x509.NoticeReference(u"org", iter(numbers))
413        assert list(nr.notice_numbers) == numbers
414
415    def test_repr(self):
416        nr = x509.NoticeReference(u"org", [1, 3, 4])
417
418        if not six.PY2:
419            assert repr(nr) == (
420                "<NoticeReference(organization='org', notice_numbers=[1, 3, 4"
421                "])>"
422            )
423        else:
424            assert repr(nr) == (
425                "<NoticeReference(organization=u'org', notice_numbers=[1, 3, "
426                "4])>"
427            )
428
429    def test_eq(self):
430        nr = x509.NoticeReference("org", [1, 2])
431        nr2 = x509.NoticeReference("org", [1, 2])
432        assert nr == nr2
433
434    def test_ne(self):
435        nr = x509.NoticeReference("org", [1, 2])
436        nr2 = x509.NoticeReference("org", [1])
437        nr3 = x509.NoticeReference(None, [1, 2])
438        assert nr != nr2
439        assert nr != nr3
440        assert nr != object()
441
442    def test_hash(self):
443        nr = x509.NoticeReference("org", [1, 2])
444        nr2 = x509.NoticeReference("org", [1, 2])
445        nr3 = x509.NoticeReference(None, [1, 2])
446        assert hash(nr) == hash(nr2)
447        assert hash(nr) != hash(nr3)
448
449
450class TestUserNotice(object):
451    def test_notice_reference_invalid(self):
452        with pytest.raises(TypeError):
453            x509.UserNotice("invalid", None)
454
455    def test_notice_reference_none(self):
456        un = x509.UserNotice(None, "text")
457        assert un.notice_reference is None
458        assert un.explicit_text == "text"
459
460    def test_repr(self):
461        un = x509.UserNotice(x509.NoticeReference(u"org", [1]), u"text")
462        if not six.PY2:
463            assert repr(un) == (
464                "<UserNotice(notice_reference=<NoticeReference(organization='"
465                "org', notice_numbers=[1])>, explicit_text='text')>"
466            )
467        else:
468            assert repr(un) == (
469                "<UserNotice(notice_reference=<NoticeReference(organization=u"
470                "'org', notice_numbers=[1])>, explicit_text=u'text')>"
471            )
472
473    def test_eq(self):
474        nr = x509.NoticeReference("org", [1, 2])
475        nr2 = x509.NoticeReference("org", [1, 2])
476        un = x509.UserNotice(nr, "text")
477        un2 = x509.UserNotice(nr2, "text")
478        assert un == un2
479
480    def test_ne(self):
481        nr = x509.NoticeReference("org", [1, 2])
482        nr2 = x509.NoticeReference("org", [1])
483        un = x509.UserNotice(nr, "text")
484        un2 = x509.UserNotice(nr2, "text")
485        un3 = x509.UserNotice(nr, "text3")
486        assert un != un2
487        assert un != un3
488        assert un != object()
489
490    def test_hash(self):
491        nr = x509.NoticeReference("org", [1, 2])
492        nr2 = x509.NoticeReference("org", [1, 2])
493        un = x509.UserNotice(nr, "text")
494        un2 = x509.UserNotice(nr2, "text")
495        un3 = x509.UserNotice(None, "text")
496        assert hash(un) == hash(un2)
497        assert hash(un) != hash(un3)
498
499
500class TestPolicyInformation(object):
501    def test_invalid_policy_identifier(self):
502        with pytest.raises(TypeError):
503            x509.PolicyInformation("notanoid", None)
504
505    def test_none_policy_qualifiers(self):
506        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), None)
507        assert pi.policy_identifier == x509.ObjectIdentifier("1.2.3")
508        assert pi.policy_qualifiers is None
509
510    def test_policy_qualifiers(self):
511        pq = [u"string"]
512        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq)
513        assert pi.policy_identifier == x509.ObjectIdentifier("1.2.3")
514        assert pi.policy_qualifiers == pq
515
516    def test_invalid_policy_identifiers(self):
517        with pytest.raises(TypeError):
518            x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), [1, 2])
519
520    def test_iter_input(self):
521        qual = [u"foo", u"bar"]
522        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), iter(qual))
523        assert list(pi.policy_qualifiers) == qual
524
525    def test_repr(self):
526        pq = [u"string", x509.UserNotice(None, u"hi")]
527        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq)
528        if not six.PY2:
529            assert repr(pi) == (
530                "<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=1."
531                "2.3, name=Unknown OID)>, policy_qualifiers=['string', <UserNo"
532                "tice(notice_reference=None, explicit_text='hi')>])>"
533            )
534        else:
535            assert repr(pi) == (
536                "<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=1."
537                "2.3, name=Unknown OID)>, policy_qualifiers=[u'string', <UserN"
538                "otice(notice_reference=None, explicit_text=u'hi')>])>"
539            )
540
541    def test_eq(self):
542        pi = x509.PolicyInformation(
543            x509.ObjectIdentifier("1.2.3"),
544            [u"string", x509.UserNotice(None, u"hi")]
545        )
546        pi2 = x509.PolicyInformation(
547            x509.ObjectIdentifier("1.2.3"),
548            [u"string", x509.UserNotice(None, u"hi")]
549        )
550        assert pi == pi2
551
552    def test_ne(self):
553        pi = x509.PolicyInformation(
554            x509.ObjectIdentifier("1.2.3"), [u"string"]
555        )
556        pi2 = x509.PolicyInformation(
557            x509.ObjectIdentifier("1.2.3"), [u"string2"]
558        )
559        pi3 = x509.PolicyInformation(
560            x509.ObjectIdentifier("1.2.3.4"), [u"string"]
561        )
562        assert pi != pi2
563        assert pi != pi3
564        assert pi != object()
565
566    def test_hash(self):
567        pi = x509.PolicyInformation(
568            x509.ObjectIdentifier("1.2.3"),
569            [u"string", x509.UserNotice(None, u"hi")]
570        )
571        pi2 = x509.PolicyInformation(
572            x509.ObjectIdentifier("1.2.3"),
573            [u"string", x509.UserNotice(None, u"hi")]
574        )
575        pi3 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), None)
576        assert hash(pi) == hash(pi2)
577        assert hash(pi) != hash(pi3)
578
579
580@pytest.mark.requires_backend_interface(interface=X509Backend)
581class TestCertificatePolicies(object):
582    def test_invalid_policies(self):
583        pq = [u"string"]
584        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq)
585        with pytest.raises(TypeError):
586            x509.CertificatePolicies([1, pi])
587
588    def test_iter_len(self):
589        pq = [u"string"]
590        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq)
591        cp = x509.CertificatePolicies([pi])
592        assert len(cp) == 1
593        for policyinfo in cp:
594            assert policyinfo == pi
595
596    def test_iter_input(self):
597        policies = [
598            x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), [u"string"])
599        ]
600        cp = x509.CertificatePolicies(iter(policies))
601        assert list(cp) == policies
602
603    def test_repr(self):
604        pq = [u"string"]
605        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq)
606        cp = x509.CertificatePolicies([pi])
607        if not six.PY2:
608            assert repr(cp) == (
609                "<CertificatePolicies([<PolicyInformation(policy_identifier=<O"
610                "bjectIdentifier(oid=1.2.3, name=Unknown OID)>, policy_qualifi"
611                "ers=['string'])>])>"
612            )
613        else:
614            assert repr(cp) == (
615                "<CertificatePolicies([<PolicyInformation(policy_identifier=<O"
616                "bjectIdentifier(oid=1.2.3, name=Unknown OID)>, policy_qualifi"
617                "ers=[u'string'])>])>"
618            )
619
620    def test_eq(self):
621        pi = x509.PolicyInformation(
622            x509.ObjectIdentifier("1.2.3"), [u"string"]
623        )
624        cp = x509.CertificatePolicies([pi])
625        pi2 = x509.PolicyInformation(
626            x509.ObjectIdentifier("1.2.3"), [u"string"]
627        )
628        cp2 = x509.CertificatePolicies([pi2])
629        assert cp == cp2
630
631    def test_ne(self):
632        pi = x509.PolicyInformation(
633            x509.ObjectIdentifier("1.2.3"), [u"string"]
634        )
635        cp = x509.CertificatePolicies([pi])
636        pi2 = x509.PolicyInformation(
637            x509.ObjectIdentifier("1.2.3"), [u"string2"]
638        )
639        cp2 = x509.CertificatePolicies([pi2])
640        assert cp != cp2
641        assert cp != object()
642
643    def test_indexing(self):
644        pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), [u"test"])
645        pi2 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.4"), [u"test"])
646        pi3 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.5"), [u"test"])
647        pi4 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.6"), [u"test"])
648        pi5 = x509.PolicyInformation(x509.ObjectIdentifier("1.2.7"), [u"test"])
649        cp = x509.CertificatePolicies([pi, pi2, pi3, pi4, pi5])
650        assert cp[-1] == cp[4]
651        assert cp[2:6:2] == [cp[2], cp[4]]
652
653    def test_long_oid(self, backend):
654        """
655        Test that parsing a CertificatePolicies ext with
656        a very long OID succeeds.
657        """
658        cert = _load_cert(
659            os.path.join("x509", "bigoid.pem"),
660            x509.load_pem_x509_certificate,
661            backend
662        )
663        ext = cert.extensions.get_extension_for_class(
664            x509.CertificatePolicies)
665
666        oid = x509.ObjectIdentifier(
667            "1.3.6.1.4.1.311.21.8.8950086.10656446.2706058"
668            ".12775672.480128.147.13466065.13029902"
669        )
670
671        assert ext.value[0].policy_identifier == oid
672
673    def test_hash(self):
674        pi = x509.PolicyInformation(
675            x509.ObjectIdentifier("1.2.3"), [u"string"]
676        )
677        cp = x509.CertificatePolicies([pi])
678        pi2 = x509.PolicyInformation(
679            x509.ObjectIdentifier("1.2.3"), [u"string"]
680        )
681        cp2 = x509.CertificatePolicies([pi2])
682        pi3 = x509.PolicyInformation(
683            x509.ObjectIdentifier("1.2.3"), [x509.UserNotice(None, b"text")]
684        )
685        cp3 = x509.CertificatePolicies([pi3])
686        assert hash(cp) == hash(cp2)
687        assert hash(cp) != hash(cp3)
688
689
690@pytest.mark.requires_backend_interface(interface=RSABackend)
691@pytest.mark.requires_backend_interface(interface=X509Backend)
692class TestCertificatePoliciesExtension(object):
693    def test_cps_uri_policy_qualifier(self, backend):
694        cert = _load_cert(
695            os.path.join("x509", "custom", "cp_cps_uri.pem"),
696            x509.load_pem_x509_certificate,
697            backend
698        )
699
700        cp = cert.extensions.get_extension_for_oid(
701            ExtensionOID.CERTIFICATE_POLICIES
702        ).value
703
704        assert cp == x509.CertificatePolicies([
705            x509.PolicyInformation(
706                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
707                [u"http://other.com/cps"]
708            )
709        ])
710
711    def test_user_notice_with_notice_reference(self, backend):
712        cert = _load_cert(
713            os.path.join(
714                "x509", "custom", "cp_user_notice_with_notice_reference.pem"
715            ),
716            x509.load_pem_x509_certificate,
717            backend
718        )
719
720        cp = cert.extensions.get_extension_for_oid(
721            ExtensionOID.CERTIFICATE_POLICIES
722        ).value
723
724        assert cp == x509.CertificatePolicies([
725            x509.PolicyInformation(
726                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
727                [
728                    u"http://example.com/cps",
729                    u"http://other.com/cps",
730                    x509.UserNotice(
731                        x509.NoticeReference(u"my org", [1, 2, 3, 4]),
732                        u"thing"
733                    )
734                ]
735            )
736        ])
737
738    def test_user_notice_with_explicit_text(self, backend):
739        cert = _load_cert(
740            os.path.join(
741                "x509", "custom", "cp_user_notice_with_explicit_text.pem"
742            ),
743            x509.load_pem_x509_certificate,
744            backend
745        )
746
747        cp = cert.extensions.get_extension_for_oid(
748            ExtensionOID.CERTIFICATE_POLICIES
749        ).value
750
751        assert cp == x509.CertificatePolicies([
752            x509.PolicyInformation(
753                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
754                [x509.UserNotice(None, u"thing")]
755            )
756        ])
757
758    def test_user_notice_no_explicit_text(self, backend):
759        cert = _load_cert(
760            os.path.join(
761                "x509", "custom", "cp_user_notice_no_explicit_text.pem"
762            ),
763            x509.load_pem_x509_certificate,
764            backend
765        )
766
767        cp = cert.extensions.get_extension_for_oid(
768            ExtensionOID.CERTIFICATE_POLICIES
769        ).value
770
771        assert cp == x509.CertificatePolicies([
772            x509.PolicyInformation(
773                x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
774                [
775                    x509.UserNotice(
776                        x509.NoticeReference(u"my org", [1, 2, 3, 4]),
777                        None
778                    )
779                ]
780            )
781        ])
782
783
784class TestKeyUsage(object):
785    def test_key_agreement_false_encipher_decipher_true(self):
786        with pytest.raises(ValueError):
787            x509.KeyUsage(
788                digital_signature=False,
789                content_commitment=False,
790                key_encipherment=False,
791                data_encipherment=False,
792                key_agreement=False,
793                key_cert_sign=False,
794                crl_sign=False,
795                encipher_only=True,
796                decipher_only=False
797            )
798
799        with pytest.raises(ValueError):
800            x509.KeyUsage(
801                digital_signature=False,
802                content_commitment=False,
803                key_encipherment=False,
804                data_encipherment=False,
805                key_agreement=False,
806                key_cert_sign=False,
807                crl_sign=False,
808                encipher_only=True,
809                decipher_only=True
810            )
811
812        with pytest.raises(ValueError):
813            x509.KeyUsage(
814                digital_signature=False,
815                content_commitment=False,
816                key_encipherment=False,
817                data_encipherment=False,
818                key_agreement=False,
819                key_cert_sign=False,
820                crl_sign=False,
821                encipher_only=False,
822                decipher_only=True
823            )
824
825    def test_properties_key_agreement_true(self):
826        ku = x509.KeyUsage(
827            digital_signature=True,
828            content_commitment=True,
829            key_encipherment=False,
830            data_encipherment=False,
831            key_agreement=False,
832            key_cert_sign=True,
833            crl_sign=False,
834            encipher_only=False,
835            decipher_only=False
836        )
837        assert ku.digital_signature is True
838        assert ku.content_commitment is True
839        assert ku.key_encipherment is False
840        assert ku.data_encipherment is False
841        assert ku.key_agreement is False
842        assert ku.key_cert_sign is True
843        assert ku.crl_sign is False
844
845    def test_key_agreement_true_properties(self):
846        ku = x509.KeyUsage(
847            digital_signature=False,
848            content_commitment=False,
849            key_encipherment=False,
850            data_encipherment=False,
851            key_agreement=True,
852            key_cert_sign=False,
853            crl_sign=False,
854            encipher_only=False,
855            decipher_only=True
856        )
857        assert ku.key_agreement is True
858        assert ku.encipher_only is False
859        assert ku.decipher_only is True
860
861    def test_key_agreement_false_properties(self):
862        ku = x509.KeyUsage(
863            digital_signature=False,
864            content_commitment=False,
865            key_encipherment=False,
866            data_encipherment=False,
867            key_agreement=False,
868            key_cert_sign=False,
869            crl_sign=False,
870            encipher_only=False,
871            decipher_only=False
872        )
873        assert ku.key_agreement is False
874        with pytest.raises(ValueError):
875            ku.encipher_only
876
877        with pytest.raises(ValueError):
878            ku.decipher_only
879
880    def test_repr_key_agreement_false(self):
881        ku = x509.KeyUsage(
882            digital_signature=True,
883            content_commitment=True,
884            key_encipherment=False,
885            data_encipherment=False,
886            key_agreement=False,
887            key_cert_sign=True,
888            crl_sign=False,
889            encipher_only=False,
890            decipher_only=False
891        )
892        assert repr(ku) == (
893            "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
894            "cipherment=False, data_encipherment=False, key_agreement=False, k"
895            "ey_cert_sign=True, crl_sign=False, encipher_only=None, decipher_o"
896            "nly=None)>"
897        )
898
899    def test_repr_key_agreement_true(self):
900        ku = x509.KeyUsage(
901            digital_signature=True,
902            content_commitment=True,
903            key_encipherment=False,
904            data_encipherment=False,
905            key_agreement=True,
906            key_cert_sign=True,
907            crl_sign=False,
908            encipher_only=False,
909            decipher_only=False
910        )
911        assert repr(ku) == (
912            "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
913            "cipherment=False, data_encipherment=False, key_agreement=True, k"
914            "ey_cert_sign=True, crl_sign=False, encipher_only=False, decipher_"
915            "only=False)>"
916        )
917
918    def test_eq(self):
919        ku = x509.KeyUsage(
920            digital_signature=False,
921            content_commitment=False,
922            key_encipherment=False,
923            data_encipherment=False,
924            key_agreement=True,
925            key_cert_sign=False,
926            crl_sign=False,
927            encipher_only=False,
928            decipher_only=True
929        )
930        ku2 = x509.KeyUsage(
931            digital_signature=False,
932            content_commitment=False,
933            key_encipherment=False,
934            data_encipherment=False,
935            key_agreement=True,
936            key_cert_sign=False,
937            crl_sign=False,
938            encipher_only=False,
939            decipher_only=True
940        )
941        assert ku == ku2
942
943    def test_ne(self):
944        ku = x509.KeyUsage(
945            digital_signature=False,
946            content_commitment=False,
947            key_encipherment=False,
948            data_encipherment=False,
949            key_agreement=True,
950            key_cert_sign=False,
951            crl_sign=False,
952            encipher_only=False,
953            decipher_only=True
954        )
955        ku2 = x509.KeyUsage(
956            digital_signature=False,
957            content_commitment=False,
958            key_encipherment=False,
959            data_encipherment=False,
960            key_agreement=False,
961            key_cert_sign=False,
962            crl_sign=False,
963            encipher_only=False,
964            decipher_only=False
965        )
966        assert ku != ku2
967        assert ku != object()
968
969    def test_hash(self):
970        ku = x509.KeyUsage(
971            digital_signature=False,
972            content_commitment=False,
973            key_encipherment=False,
974            data_encipherment=False,
975            key_agreement=True,
976            key_cert_sign=False,
977            crl_sign=False,
978            encipher_only=False,
979            decipher_only=True
980        )
981        ku2 = x509.KeyUsage(
982            digital_signature=False,
983            content_commitment=False,
984            key_encipherment=False,
985            data_encipherment=False,
986            key_agreement=True,
987            key_cert_sign=False,
988            crl_sign=False,
989            encipher_only=False,
990            decipher_only=True
991        )
992        ku3 = x509.KeyUsage(
993            digital_signature=False,
994            content_commitment=True,
995            key_encipherment=False,
996            data_encipherment=False,
997            key_agreement=False,
998            key_cert_sign=False,
999            crl_sign=False,
1000            encipher_only=False,
1001            decipher_only=False
1002        )
1003        assert hash(ku) == hash(ku2)
1004        assert hash(ku) != hash(ku3)
1005
1006
1007class TestSubjectKeyIdentifier(object):
1008    def test_properties(self):
1009        value = binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1010        ski = x509.SubjectKeyIdentifier(value)
1011        assert ski.digest == value
1012
1013    def test_repr(self):
1014        ski = x509.SubjectKeyIdentifier(
1015            binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1016        )
1017        ext = x509.Extension(ExtensionOID.SUBJECT_KEY_IDENTIFIER, False, ski)
1018        if not six.PY2:
1019            assert repr(ext) == (
1020                "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
1021                "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
1022                "igest=b\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
1023                "\\xf7\\xff:\\xc9\')>)>"
1024            )
1025        else:
1026            assert repr(ext) == (
1027                "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
1028                "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
1029                "igest=\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
1030                "\\xf7\\xff:\\xc9\')>)>"
1031            )
1032
1033    def test_eq(self):
1034        ski = x509.SubjectKeyIdentifier(
1035            binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1036        )
1037        ski2 = x509.SubjectKeyIdentifier(
1038            binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1039        )
1040        assert ski == ski2
1041
1042    def test_ne(self):
1043        ski = x509.SubjectKeyIdentifier(
1044            binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1045        )
1046        ski2 = x509.SubjectKeyIdentifier(
1047            binascii.unhexlify(b"aa8098456f6ff7ff3ac9092384932230498bc980")
1048        )
1049        assert ski != ski2
1050        assert ski != object()
1051
1052    def test_hash(self):
1053        ski1 = x509.SubjectKeyIdentifier(
1054            binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1055        )
1056        ski2 = x509.SubjectKeyIdentifier(
1057            binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
1058        )
1059        ski3 = x509.SubjectKeyIdentifier(
1060            binascii.unhexlify(b"aa8098456f6ff7ff3ac9092384932230498bc980")
1061        )
1062        assert hash(ski1) == hash(ski2)
1063        assert hash(ski1) != hash(ski3)
1064
1065
1066class TestAuthorityKeyIdentifier(object):
1067    def test_authority_cert_issuer_not_generalname(self):
1068        with pytest.raises(TypeError):
1069            x509.AuthorityKeyIdentifier(b"identifier", ["notname"], 3)
1070
1071    def test_authority_cert_serial_number_not_integer(self):
1072        dirname = x509.DirectoryName(
1073            x509.Name([
1074                x509.NameAttribute(
1075                    x509.ObjectIdentifier('2.999.1'),
1076                    u'value1'
1077                ),
1078                x509.NameAttribute(
1079                    x509.ObjectIdentifier('2.999.2'),
1080                    u'value2'
1081                ),
1082            ])
1083        )
1084        with pytest.raises(TypeError):
1085            x509.AuthorityKeyIdentifier(b"identifier", [dirname], "notanint")
1086
1087    def test_authority_issuer_none_serial_not_none(self):
1088        with pytest.raises(ValueError):
1089            x509.AuthorityKeyIdentifier(b"identifier", None, 3)
1090
1091    def test_authority_issuer_not_none_serial_none(self):
1092        dirname = x509.DirectoryName(
1093            x509.Name([
1094                x509.NameAttribute(
1095                    x509.ObjectIdentifier('2.999.1'),
1096                    u'value1'
1097                ),
1098                x509.NameAttribute(
1099                    x509.ObjectIdentifier('2.999.2'),
1100                    u'value2'
1101                ),
1102            ])
1103        )
1104        with pytest.raises(ValueError):
1105            x509.AuthorityKeyIdentifier(b"identifier", [dirname], None)
1106
1107    def test_authority_cert_serial_and_issuer_none(self):
1108        aki = x509.AuthorityKeyIdentifier(b"id", None, None)
1109        assert aki.key_identifier == b"id"
1110        assert aki.authority_cert_issuer is None
1111        assert aki.authority_cert_serial_number is None
1112
1113    def test_authority_cert_serial_zero(self):
1114        dns = x509.DNSName(u"SomeIssuer")
1115        aki = x509.AuthorityKeyIdentifier(b"id", [dns], 0)
1116        assert aki.key_identifier == b"id"
1117        assert aki.authority_cert_issuer == [dns]
1118        assert aki.authority_cert_serial_number == 0
1119
1120    def test_iter_input(self):
1121        dirnames = [
1122            x509.DirectoryName(
1123                x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
1124            )
1125        ]
1126        aki = x509.AuthorityKeyIdentifier(b"digest", iter(dirnames), 1234)
1127        assert list(aki.authority_cert_issuer) == dirnames
1128
1129    def test_repr(self):
1130        dirname = x509.DirectoryName(
1131            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
1132        )
1133        aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
1134
1135        if not six.PY2:
1136            assert repr(aki) == (
1137                "<AuthorityKeyIdentifier(key_identifier=b'digest', authority_"
1138                "cert_issuer=[<DirectoryName(value=<Name(CN=myCN)>)>], author"
1139                "ity_cert_serial_number=1234)>"
1140            )
1141        else:
1142            assert repr(aki) == (
1143                "<AuthorityKeyIdentifier(key_identifier='digest', authority_"
1144                "cert_issuer=[<DirectoryName(value=<Name(CN=myCN)>)>], author"
1145                "ity_cert_serial_number=1234)>"
1146            )
1147
1148    def test_eq(self):
1149        dirname = x509.DirectoryName(
1150            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
1151        )
1152        aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
1153        dirname2 = x509.DirectoryName(
1154            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
1155        )
1156        aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname2], 1234)
1157        assert aki == aki2
1158
1159    def test_ne(self):
1160        dirname = x509.DirectoryName(
1161            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
1162        )
1163        dirname5 = x509.DirectoryName(
1164            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'aCN')])
1165        )
1166        aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
1167        aki2 = x509.AuthorityKeyIdentifier(b"diges", [dirname], 1234)
1168        aki3 = x509.AuthorityKeyIdentifier(b"digest", None, None)
1169        aki4 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 12345)
1170        aki5 = x509.AuthorityKeyIdentifier(b"digest", [dirname5], 12345)
1171        assert aki != aki2
1172        assert aki != aki3
1173        assert aki != aki4
1174        assert aki != aki5
1175        assert aki != object()
1176
1177    def test_hash(self):
1178        dirname = x509.DirectoryName(
1179            x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'myCN')])
1180        )
1181        aki1 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
1182        aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234)
1183        aki3 = x509.AuthorityKeyIdentifier(b"digest", None, None)
1184        assert hash(aki1) == hash(aki2)
1185        assert hash(aki1) != hash(aki3)
1186
1187
1188class TestBasicConstraints(object):
1189    def test_ca_not_boolean(self):
1190        with pytest.raises(TypeError):
1191            x509.BasicConstraints(ca="notbool", path_length=None)
1192
1193    def test_path_length_not_ca(self):
1194        with pytest.raises(ValueError):
1195            x509.BasicConstraints(ca=False, path_length=0)
1196
1197    def test_path_length_not_int(self):
1198        with pytest.raises(TypeError):
1199            x509.BasicConstraints(ca=True, path_length=1.1)
1200
1201        with pytest.raises(TypeError):
1202            x509.BasicConstraints(ca=True, path_length="notint")
1203
1204    def test_path_length_negative(self):
1205        with pytest.raises(TypeError):
1206            x509.BasicConstraints(ca=True, path_length=-1)
1207
1208    def test_repr(self):
1209        na = x509.BasicConstraints(ca=True, path_length=None)
1210        assert repr(na) == (
1211            "<BasicConstraints(ca=True, path_length=None)>"
1212        )
1213
1214    def test_hash(self):
1215        na = x509.BasicConstraints(ca=True, path_length=None)
1216        na2 = x509.BasicConstraints(ca=True, path_length=None)
1217        na3 = x509.BasicConstraints(ca=True, path_length=0)
1218        assert hash(na) == hash(na2)
1219        assert hash(na) != hash(na3)
1220
1221    def test_eq(self):
1222        na = x509.BasicConstraints(ca=True, path_length=None)
1223        na2 = x509.BasicConstraints(ca=True, path_length=None)
1224        assert na == na2
1225
1226    def test_ne(self):
1227        na = x509.BasicConstraints(ca=True, path_length=None)
1228        na2 = x509.BasicConstraints(ca=True, path_length=1)
1229        na3 = x509.BasicConstraints(ca=False, path_length=None)
1230        assert na != na2
1231        assert na != na3
1232        assert na != object()
1233
1234
1235class TestExtendedKeyUsage(object):
1236    def test_not_all_oids(self):
1237        with pytest.raises(TypeError):
1238            x509.ExtendedKeyUsage(["notoid"])
1239
1240    def test_iter_len(self):
1241        eku = x509.ExtendedKeyUsage([
1242            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
1243            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
1244        ])
1245        assert len(eku) == 2
1246        assert list(eku) == [
1247            ExtendedKeyUsageOID.SERVER_AUTH,
1248            ExtendedKeyUsageOID.CLIENT_AUTH
1249        ]
1250
1251    def test_iter_input(self):
1252        usages = [
1253            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
1254            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
1255        ]
1256        aia = x509.ExtendedKeyUsage(iter(usages))
1257        assert list(aia) == usages
1258
1259    def test_repr(self):
1260        eku = x509.ExtendedKeyUsage([
1261            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
1262            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
1263        ])
1264        assert repr(eku) == (
1265            "<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name="
1266            "serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clien"
1267            "tAuth)>])>"
1268        )
1269
1270    def test_eq(self):
1271        eku = x509.ExtendedKeyUsage([
1272            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
1273        ])
1274        eku2 = x509.ExtendedKeyUsage([
1275            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
1276        ])
1277        assert eku == eku2
1278
1279    def test_ne(self):
1280        eku = x509.ExtendedKeyUsage([x509.ObjectIdentifier("1.3.6")])
1281        eku2 = x509.ExtendedKeyUsage([x509.ObjectIdentifier("1.3.6.1")])
1282        assert eku != eku2
1283        assert eku != object()
1284
1285    def test_hash(self):
1286        eku = x509.ExtendedKeyUsage([
1287            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
1288        ])
1289        eku2 = x509.ExtendedKeyUsage([
1290            x509.ObjectIdentifier("1.3.6"), x509.ObjectIdentifier("1.3.7")
1291        ])
1292        eku3 = x509.ExtendedKeyUsage([x509.ObjectIdentifier("1.3.6")])
1293        assert hash(eku) == hash(eku2)
1294        assert hash(eku) != hash(eku3)
1295
1296
1297@pytest.mark.requires_backend_interface(interface=RSABackend)
1298@pytest.mark.requires_backend_interface(interface=X509Backend)
1299class TestExtensions(object):
1300    def test_no_extensions(self, backend):
1301        cert = _load_cert(
1302            os.path.join("x509", "verisign_md2_root.pem"),
1303            x509.load_pem_x509_certificate,
1304            backend
1305        )
1306        ext = cert.extensions
1307        assert len(ext) == 0
1308        assert list(ext) == []
1309        with pytest.raises(x509.ExtensionNotFound) as exc:
1310            ext.get_extension_for_oid(ExtensionOID.BASIC_CONSTRAINTS)
1311
1312        assert exc.value.oid == ExtensionOID.BASIC_CONSTRAINTS
1313
1314    def test_one_extension(self, backend):
1315        cert = _load_cert(
1316            os.path.join(
1317                "x509", "custom", "basic_constraints_not_critical.pem"
1318            ),
1319            x509.load_pem_x509_certificate,
1320            backend
1321        )
1322        extensions = cert.extensions
1323        ext = extensions.get_extension_for_oid(ExtensionOID.BASIC_CONSTRAINTS)
1324        assert ext is not None
1325        assert ext.value.ca is False
1326
1327    def test_duplicate_extension(self, backend):
1328        cert = _load_cert(
1329            os.path.join(
1330                "x509", "custom", "two_basic_constraints.pem"
1331            ),
1332            x509.load_pem_x509_certificate,
1333            backend
1334        )
1335        with pytest.raises(x509.DuplicateExtension) as exc:
1336            cert.extensions
1337
1338        assert exc.value.oid == ExtensionOID.BASIC_CONSTRAINTS
1339
1340    def test_unsupported_critical_extension(self, backend):
1341        cert = _load_cert(
1342            os.path.join(
1343                "x509", "custom", "unsupported_extension_critical.pem"
1344            ),
1345            x509.load_pem_x509_certificate,
1346            backend
1347        )
1348        ext = cert.extensions.get_extension_for_oid(
1349            x509.ObjectIdentifier("1.2.3.4")
1350        )
1351        assert ext.value.value == b"value"
1352
1353    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
1354    def test_unsupported_extension(self, backend):
1355        cert = _load_cert(
1356            os.path.join(
1357                "x509", "custom", "unsupported_extension_2.pem"
1358            ),
1359            x509.load_pem_x509_certificate,
1360            backend
1361        )
1362        extensions = cert.extensions
1363        assert len(extensions) == 2
1364        assert extensions[0].critical is False
1365        assert extensions[0].oid == x509.ObjectIdentifier(
1366            "1.3.6.1.4.1.41482.2"
1367        )
1368        assert extensions[0].value == x509.UnrecognizedExtension(
1369            x509.ObjectIdentifier("1.3.6.1.4.1.41482.2"),
1370            b"1.3.6.1.4.1.41482.1.2"
1371        )
1372        assert extensions[1].critical is False
1373        assert extensions[1].oid == x509.ObjectIdentifier(
1374            "1.3.6.1.4.1.45724.2.1.1"
1375        )
1376        assert extensions[1].value == x509.UnrecognizedExtension(
1377            x509.ObjectIdentifier("1.3.6.1.4.1.45724.2.1.1"),
1378            b"\x03\x02\x040"
1379        )
1380
1381    def test_no_extensions_get_for_class(self, backend):
1382        cert = _load_cert(
1383            os.path.join(
1384                "x509", "cryptography.io.pem"
1385            ),
1386            x509.load_pem_x509_certificate,
1387            backend
1388        )
1389        exts = cert.extensions
1390        with pytest.raises(x509.ExtensionNotFound) as exc:
1391            exts.get_extension_for_class(x509.IssuerAlternativeName)
1392        assert exc.value.oid == ExtensionOID.ISSUER_ALTERNATIVE_NAME
1393
1394    def test_unrecognized_extension_for_class(self):
1395        exts = x509.Extensions([])
1396        with pytest.raises(TypeError):
1397            exts.get_extension_for_class(x509.UnrecognizedExtension)
1398
1399    def test_indexing(self, backend):
1400        cert = _load_cert(
1401            os.path.join("x509", "cryptography.io.pem"),
1402            x509.load_pem_x509_certificate,
1403            backend
1404        )
1405        exts = cert.extensions
1406        assert exts[-1] == exts[7]
1407        assert exts[2:6:2] == [exts[2], exts[4]]
1408
1409    def test_one_extension_get_for_class(self, backend):
1410        cert = _load_cert(
1411            os.path.join(
1412                "x509", "custom", "basic_constraints_not_critical.pem"
1413            ),
1414            x509.load_pem_x509_certificate,
1415            backend
1416        )
1417        ext = cert.extensions.get_extension_for_class(x509.BasicConstraints)
1418        assert ext is not None
1419        assert isinstance(ext.value, x509.BasicConstraints)
1420
1421    def test_repr(self, backend):
1422        cert = _load_cert(
1423            os.path.join(
1424                "x509", "custom", "basic_constraints_not_critical.pem"
1425            ),
1426            x509.load_pem_x509_certificate,
1427            backend
1428        )
1429        assert repr(cert.extensions) == (
1430            "<Extensions([<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name"
1431            "=basicConstraints)>, critical=False, value=<BasicConstraints(ca=F"
1432            "alse, path_length=None)>)>])>"
1433        )
1434
1435
1436@pytest.mark.requires_backend_interface(interface=RSABackend)
1437@pytest.mark.requires_backend_interface(interface=X509Backend)
1438class TestBasicConstraintsExtension(object):
1439    def test_ca_true_pathlen_6(self, backend):
1440        cert = _load_cert(
1441            os.path.join(
1442                "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
1443            ),
1444            x509.load_der_x509_certificate,
1445            backend
1446        )
1447        ext = cert.extensions.get_extension_for_oid(
1448            ExtensionOID.BASIC_CONSTRAINTS
1449        )
1450        assert ext is not None
1451        assert ext.critical is True
1452        assert ext.value.ca is True
1453        assert ext.value.path_length == 6
1454
1455    def test_path_length_zero(self, backend):
1456        cert = _load_cert(
1457            os.path.join("x509", "custom", "bc_path_length_zero.pem"),
1458            x509.load_pem_x509_certificate,
1459            backend
1460        )
1461        ext = cert.extensions.get_extension_for_oid(
1462            ExtensionOID.BASIC_CONSTRAINTS
1463        )
1464        assert ext is not None
1465        assert ext.critical is True
1466        assert ext.value.ca is True
1467        assert ext.value.path_length == 0
1468
1469    def test_ca_true_no_pathlen(self, backend):
1470        cert = _load_cert(
1471            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1472            x509.load_der_x509_certificate,
1473            backend
1474        )
1475        ext = cert.extensions.get_extension_for_oid(
1476            ExtensionOID.BASIC_CONSTRAINTS
1477        )
1478        assert ext is not None
1479        assert ext.critical is True
1480        assert ext.value.ca is True
1481        assert ext.value.path_length is None
1482
1483    def test_ca_false(self, backend):
1484        cert = _load_cert(
1485            os.path.join("x509", "cryptography.io.pem"),
1486            x509.load_pem_x509_certificate,
1487            backend
1488        )
1489        ext = cert.extensions.get_extension_for_oid(
1490            ExtensionOID.BASIC_CONSTRAINTS
1491        )
1492        assert ext is not None
1493        assert ext.critical is True
1494        assert ext.value.ca is False
1495        assert ext.value.path_length is None
1496
1497    def test_no_basic_constraints(self, backend):
1498        cert = _load_cert(
1499            os.path.join(
1500                "x509",
1501                "PKITS_data",
1502                "certs",
1503                "ValidCertificatePathTest1EE.crt"
1504            ),
1505            x509.load_der_x509_certificate,
1506            backend
1507        )
1508        with pytest.raises(x509.ExtensionNotFound):
1509            cert.extensions.get_extension_for_oid(
1510                ExtensionOID.BASIC_CONSTRAINTS
1511            )
1512
1513    def test_basic_constraint_not_critical(self, backend):
1514        cert = _load_cert(
1515            os.path.join(
1516                "x509", "custom", "basic_constraints_not_critical.pem"
1517            ),
1518            x509.load_pem_x509_certificate,
1519            backend
1520        )
1521        ext = cert.extensions.get_extension_for_oid(
1522            ExtensionOID.BASIC_CONSTRAINTS
1523        )
1524        assert ext is not None
1525        assert ext.critical is False
1526        assert ext.value.ca is False
1527
1528
1529class TestSubjectKeyIdentifierExtension(object):
1530    @pytest.mark.requires_backend_interface(interface=RSABackend)
1531    @pytest.mark.requires_backend_interface(interface=X509Backend)
1532    def test_subject_key_identifier(self, backend):
1533        cert = _load_cert(
1534            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1535            x509.load_der_x509_certificate,
1536            backend
1537        )
1538        ext = cert.extensions.get_extension_for_oid(
1539            ExtensionOID.SUBJECT_KEY_IDENTIFIER
1540        )
1541        ski = ext.value
1542        assert ext is not None
1543        assert ext.critical is False
1544        assert ski.digest == binascii.unhexlify(
1545            b"580184241bbc2b52944a3da510721451f5af3ac9"
1546        )
1547
1548    @pytest.mark.requires_backend_interface(interface=RSABackend)
1549    @pytest.mark.requires_backend_interface(interface=X509Backend)
1550    def test_no_subject_key_identifier(self, backend):
1551        cert = _load_cert(
1552            os.path.join("x509", "custom", "bc_path_length_zero.pem"),
1553            x509.load_pem_x509_certificate,
1554            backend
1555        )
1556        with pytest.raises(x509.ExtensionNotFound):
1557            cert.extensions.get_extension_for_oid(
1558                ExtensionOID.SUBJECT_KEY_IDENTIFIER
1559            )
1560
1561    @pytest.mark.requires_backend_interface(interface=RSABackend)
1562    @pytest.mark.requires_backend_interface(interface=X509Backend)
1563    def test_from_rsa_public_key(self, backend):
1564        cert = _load_cert(
1565            os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
1566            x509.load_der_x509_certificate,
1567            backend
1568        )
1569        ext = cert.extensions.get_extension_for_oid(
1570            ExtensionOID.SUBJECT_KEY_IDENTIFIER
1571        )
1572        ski = x509.SubjectKeyIdentifier.from_public_key(
1573            cert.public_key()
1574        )
1575        assert ext.value == ski
1576
1577    @pytest.mark.requires_backend_interface(interface=DSABackend)
1578    @pytest.mark.requires_backend_interface(interface=X509Backend)
1579    def test_from_dsa_public_key(self, backend):
1580        cert = _load_cert(
1581            os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
1582            x509.load_pem_x509_certificate,
1583            backend
1584        )
1585
1586        ext = cert.extensions.get_extension_for_oid(
1587            ExtensionOID.SUBJECT_KEY_IDENTIFIER
1588        )
1589        ski = x509.SubjectKeyIdentifier.from_public_key(
1590            cert.public_key()
1591        )
1592        assert ext.value == ski
1593
1594    @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
1595    @pytest.mark.requires_backend_interface(interface=X509Backend)
1596    def test_from_ec_public_key(self, backend):
1597        _skip_curve_unsupported(backend, ec.SECP384R1())
1598        cert = _load_cert(
1599            os.path.join("x509", "ecdsa_root.pem"),
1600            x509.load_pem_x509_certificate,
1601            backend
1602        )
1603
1604        ext = cert.extensions.get_extension_for_oid(
1605            ExtensionOID.SUBJECT_KEY_IDENTIFIER
1606        )
1607        ski = x509.SubjectKeyIdentifier.from_public_key(
1608            cert.public_key()
1609        )
1610        assert ext.value == ski
1611
1612
1613@pytest.mark.requires_backend_interface(interface=RSABackend)
1614@pytest.mark.requires_backend_interface(interface=X509Backend)
1615class TestKeyUsageExtension(object):
1616    def test_no_key_usage(self, backend):
1617        cert = _load_cert(
1618            os.path.join("x509", "verisign_md2_root.pem"),
1619            x509.load_pem_x509_certificate,
1620            backend
1621        )
1622        ext = cert.extensions
1623        with pytest.raises(x509.ExtensionNotFound) as exc:
1624            ext.get_extension_for_oid(ExtensionOID.KEY_USAGE)
1625
1626        assert exc.value.oid == ExtensionOID.KEY_USAGE
1627
1628    def test_all_purposes(self, backend):
1629        cert = _load_cert(
1630            os.path.join(
1631                "x509", "custom", "all_key_usages.pem"
1632            ),
1633            x509.load_pem_x509_certificate,
1634            backend
1635        )
1636        extensions = cert.extensions
1637        ext = extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
1638        assert ext is not None
1639
1640        ku = ext.value
1641        assert ku.digital_signature is True
1642        assert ku.content_commitment is True
1643        assert ku.key_encipherment is True
1644        assert ku.data_encipherment is True
1645        assert ku.key_agreement is True
1646        assert ku.key_cert_sign is True
1647        assert ku.crl_sign is True
1648        assert ku.encipher_only is True
1649        assert ku.decipher_only is True
1650
1651    def test_key_cert_sign_crl_sign(self, backend):
1652        cert = _load_cert(
1653            os.path.join(
1654                "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
1655            ),
1656            x509.load_der_x509_certificate,
1657            backend
1658        )
1659        ext = cert.extensions.get_extension_for_oid(ExtensionOID.KEY_USAGE)
1660        assert ext is not None
1661        assert ext.critical is True
1662
1663        ku = ext.value
1664        assert ku.digital_signature is False
1665        assert ku.content_commitment is False
1666        assert ku.key_encipherment is False
1667        assert ku.data_encipherment is False
1668        assert ku.key_agreement is False
1669        assert ku.key_cert_sign is True
1670        assert ku.crl_sign is True
1671
1672
1673class TestDNSName(object):
1674    def test_init_deprecated(self):
1675        pytest.importorskip("idna")
1676        with pytest.warns(utils.DeprecatedIn21):
1677            name = x509.DNSName(u".\xf5\xe4\xf6\xfc.example.com")
1678        assert name.value == u".xn--4ca7aey.example.com"
1679
1680        with pytest.warns(utils.DeprecatedIn21):
1681            name = x509.DNSName(u"\xf5\xe4\xf6\xfc.example.com")
1682        assert name.value == u"xn--4ca7aey.example.com"
1683
1684    def test_init(self):
1685        name = x509.DNSName(u"*.xn--4ca7aey.example.com")
1686        assert name.value == u"*.xn--4ca7aey.example.com"
1687
1688        with pytest.raises(TypeError):
1689            x509.DNSName(1.3)
1690
1691        with pytest.raises(TypeError):
1692            x509.DNSName(b"bytes not allowed")
1693
1694    def test_ne(self):
1695        n1 = x509.DNSName(u"test1")
1696        n2 = x509.DNSName(u"test2")
1697        n3 = x509.DNSName(u"test2")
1698        assert n1 != n2
1699        assert not (n2 != n3)
1700
1701    def test_hash(self):
1702        n1 = x509.DNSName(u"test1")
1703        n2 = x509.DNSName(u"test2")
1704        n3 = x509.DNSName(u"test2")
1705        assert hash(n1) != hash(n2)
1706        assert hash(n2) == hash(n3)
1707
1708
1709class TestDirectoryName(object):
1710    def test_not_name(self):
1711        with pytest.raises(TypeError):
1712            x509.DirectoryName(b"notaname")
1713
1714        with pytest.raises(TypeError):
1715            x509.DirectoryName(1.3)
1716
1717    def test_repr(self):
1718        name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'value1')])
1719        gn = x509.DirectoryName(name)
1720        assert repr(gn) == "<DirectoryName(value=<Name(CN=value1)>)>"
1721
1722    def test_eq(self):
1723        name = x509.Name([
1724            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
1725        ])
1726        name2 = x509.Name([
1727            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
1728        ])
1729        gn = x509.DirectoryName(name)
1730        gn2 = x509.DirectoryName(name2)
1731        assert gn == gn2
1732
1733    def test_ne(self):
1734        name = x509.Name([
1735            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
1736        ])
1737        name2 = x509.Name([
1738            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
1739        ])
1740        gn = x509.DirectoryName(name)
1741        gn2 = x509.DirectoryName(name2)
1742        assert gn != gn2
1743        assert gn != object()
1744
1745    def test_hash(self):
1746        name = x509.Name([
1747            x509.NameAttribute(x509.ObjectIdentifier('2.999.1'), u'value1')
1748        ])
1749        name2 = x509.Name([
1750            x509.NameAttribute(x509.ObjectIdentifier('2.999.2'), u'value2')
1751        ])
1752        gn = x509.DirectoryName(name)
1753        gn2 = x509.DirectoryName(name)
1754        gn3 = x509.DirectoryName(name2)
1755        assert hash(gn) == hash(gn2)
1756        assert hash(gn) != hash(gn3)
1757
1758
1759class TestRFC822Name(object):
1760    def test_repr(self):
1761        gn = x509.RFC822Name(u"string")
1762        if not six.PY2:
1763            assert repr(gn) == "<RFC822Name(value='string')>"
1764        else:
1765            assert repr(gn) == "<RFC822Name(value=u'string')>"
1766
1767    def test_equality(self):
1768        gn = x509.RFC822Name(u"string")
1769        gn2 = x509.RFC822Name(u"string2")
1770        gn3 = x509.RFC822Name(u"string")
1771        assert gn != gn2
1772        assert gn != object()
1773        assert gn == gn3
1774
1775    def test_not_text(self):
1776        with pytest.raises(TypeError):
1777            x509.RFC822Name(1.3)
1778
1779        with pytest.raises(TypeError):
1780            x509.RFC822Name(b"bytes")
1781
1782    def test_invalid_email(self):
1783        with pytest.raises(ValueError):
1784            x509.RFC822Name(u"Name <email>")
1785
1786        with pytest.raises(ValueError):
1787            x509.RFC822Name(u"")
1788
1789    def test_single_label(self):
1790        gn = x509.RFC822Name(u"administrator")
1791        assert gn.value == u"administrator"
1792
1793    def test_idna(self):
1794        pytest.importorskip("idna")
1795        with pytest.warns(utils.DeprecatedIn21):
1796            gn = x509.RFC822Name(u"email@em\xe5\xefl.com")
1797
1798        assert gn.value == u"email@xn--eml-vla4c.com"
1799
1800        gn2 = x509.RFC822Name(u"email@xn--eml-vla4c.com")
1801        assert gn2.value == u"email@xn--eml-vla4c.com"
1802
1803    def test_hash(self):
1804        g1 = x509.RFC822Name(u"email@host.com")
1805        g2 = x509.RFC822Name(u"email@host.com")
1806        g3 = x509.RFC822Name(u"admin@host.com")
1807
1808        assert hash(g1) == hash(g2)
1809        assert hash(g1) != hash(g3)
1810
1811
1812class TestUniformResourceIdentifier(object):
1813    def test_equality(self):
1814        gn = x509.UniformResourceIdentifier(u"string")
1815        gn2 = x509.UniformResourceIdentifier(u"string2")
1816        gn3 = x509.UniformResourceIdentifier(u"string")
1817        assert gn != gn2
1818        assert gn != object()
1819        assert gn == gn3
1820
1821    def test_not_text(self):
1822        with pytest.raises(TypeError):
1823            x509.UniformResourceIdentifier(1.3)
1824
1825    def test_no_parsed_hostname(self):
1826        gn = x509.UniformResourceIdentifier(u"singlelabel")
1827        assert gn.value == u"singlelabel"
1828
1829    def test_with_port(self):
1830        gn = x509.UniformResourceIdentifier(u"singlelabel:443/test")
1831        assert gn.value == u"singlelabel:443/test"
1832
1833    def test_idna_no_port(self):
1834        pytest.importorskip("idna")
1835        with pytest.warns(utils.DeprecatedIn21):
1836            gn = x509.UniformResourceIdentifier(
1837                u"http://\u043f\u044b\u043a\u0430.cryptography"
1838            )
1839
1840        assert gn.value == u"http://xn--80ato2c.cryptography"
1841
1842    def test_idna_with_port(self):
1843        pytest.importorskip("idna")
1844        with pytest.warns(utils.DeprecatedIn21):
1845            gn = x509.UniformResourceIdentifier(
1846                u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/some/path"
1847            )
1848
1849        assert gn.value == (
1850            u"gopher://xn--80ato2c.cryptography:70/some/path"
1851        )
1852
1853    def test_empty_hostname(self):
1854        gn = x509.UniformResourceIdentifier(u"ldap:///some-nonsense")
1855        assert gn.value == "ldap:///some-nonsense"
1856
1857    def test_query_and_fragment(self):
1858        pytest.importorskip("idna")
1859        with pytest.warns(utils.DeprecatedIn21):
1860            gn = x509.UniformResourceIdentifier(
1861                u"ldap://\u043f\u044b\u043a\u0430.cryptography:90/path?query="
1862                u"true#somedata"
1863            )
1864        assert gn.value == (
1865            u"ldap://xn--80ato2c.cryptography:90/path?query=true#somedata"
1866        )
1867
1868    def test_hash(self):
1869        g1 = x509.UniformResourceIdentifier(u"http://host.com")
1870        g2 = x509.UniformResourceIdentifier(u"http://host.com")
1871        g3 = x509.UniformResourceIdentifier(u"http://other.com")
1872
1873        assert hash(g1) == hash(g2)
1874        assert hash(g1) != hash(g3)
1875
1876    def test_repr(self):
1877        gn = x509.UniformResourceIdentifier(u"string")
1878        if not six.PY2:
1879            assert repr(gn) == (
1880                "<UniformResourceIdentifier(value='string')>"
1881            )
1882        else:
1883            assert repr(gn) == (
1884                "<UniformResourceIdentifier(value=u'string')>"
1885            )
1886
1887
1888class TestRegisteredID(object):
1889    def test_not_oid(self):
1890        with pytest.raises(TypeError):
1891            x509.RegisteredID(b"notanoid")
1892
1893        with pytest.raises(TypeError):
1894            x509.RegisteredID(1.3)
1895
1896    def test_repr(self):
1897        gn = x509.RegisteredID(NameOID.COMMON_NAME)
1898        assert repr(gn) == (
1899            "<RegisteredID(value=<ObjectIdentifier(oid=2.5.4.3, name=commonNam"
1900            "e)>)>"
1901        )
1902
1903    def test_eq(self):
1904        gn = x509.RegisteredID(NameOID.COMMON_NAME)
1905        gn2 = x509.RegisteredID(NameOID.COMMON_NAME)
1906        assert gn == gn2
1907
1908    def test_ne(self):
1909        gn = x509.RegisteredID(NameOID.COMMON_NAME)
1910        gn2 = x509.RegisteredID(ExtensionOID.BASIC_CONSTRAINTS)
1911        assert gn != gn2
1912        assert gn != object()
1913
1914    def test_hash(self):
1915        gn = x509.RegisteredID(NameOID.COMMON_NAME)
1916        gn2 = x509.RegisteredID(NameOID.COMMON_NAME)
1917        gn3 = x509.RegisteredID(ExtensionOID.BASIC_CONSTRAINTS)
1918        assert hash(gn) == hash(gn2)
1919        assert hash(gn) != hash(gn3)
1920
1921
1922class TestIPAddress(object):
1923    def test_not_ipaddress(self):
1924        with pytest.raises(TypeError):
1925            x509.IPAddress(b"notanipaddress")
1926
1927        with pytest.raises(TypeError):
1928            x509.IPAddress(1.3)
1929
1930    def test_repr(self):
1931        gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
1932        assert repr(gn) == "<IPAddress(value=127.0.0.1)>"
1933
1934        gn2 = x509.IPAddress(ipaddress.IPv6Address(u"ff::"))
1935        assert repr(gn2) == "<IPAddress(value=ff::)>"
1936
1937        gn3 = x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24"))
1938        assert repr(gn3) == "<IPAddress(value=192.168.0.0/24)>"
1939
1940        gn4 = x509.IPAddress(ipaddress.IPv6Network(u"ff::/96"))
1941        assert repr(gn4) == "<IPAddress(value=ff::/96)>"
1942
1943    def test_eq(self):
1944        gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
1945        gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
1946        assert gn == gn2
1947
1948    def test_ne(self):
1949        gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
1950        gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.2"))
1951        assert gn != gn2
1952        assert gn != object()
1953
1954    def test_hash(self):
1955        gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
1956        gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
1957        gn3 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.2"))
1958        assert hash(gn) == hash(gn2)
1959        assert hash(gn) != hash(gn3)
1960
1961
1962class TestOtherName(object):
1963    def test_invalid_args(self):
1964        with pytest.raises(TypeError):
1965            x509.OtherName(b"notanobjectidentifier", b"derdata")
1966
1967        with pytest.raises(TypeError):
1968            x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), u"notderdata")
1969
1970    def test_repr(self):
1971        gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata")
1972        if not six.PY2:
1973            assert repr(gn) == (
1974                "<OtherName(type_id=<ObjectIdentifier(oid=1.2.3.4, "
1975                "name=Unknown OID)>, value=b'derdata')>"
1976            )
1977        else:
1978            assert repr(gn) == (
1979                "<OtherName(type_id=<ObjectIdentifier(oid=1.2.3.4, "
1980                "name=Unknown OID)>, value='derdata')>"
1981            )
1982
1983        gn = x509.OtherName(x509.ObjectIdentifier("2.5.4.65"), b"derdata")
1984        if not six.PY2:
1985            assert repr(gn) == (
1986                "<OtherName(type_id=<ObjectIdentifier(oid=2.5.4.65, "
1987                "name=pseudonym)>, value=b'derdata')>"
1988            )
1989        else:
1990            assert repr(gn) == (
1991                "<OtherName(type_id=<ObjectIdentifier(oid=2.5.4.65, "
1992                "name=pseudonym)>, value='derdata')>"
1993            )
1994
1995    def test_eq(self):
1996        gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata")
1997        gn2 = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata")
1998        assert gn == gn2
1999
2000    def test_ne(self):
2001        gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata")
2002        assert gn != object()
2003
2004        gn2 = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata2")
2005        assert gn != gn2
2006
2007        gn2 = x509.OtherName(x509.ObjectIdentifier("1.2.3.5"), b"derdata")
2008        assert gn != gn2
2009
2010    def test_hash(self):
2011        gn = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata")
2012        gn2 = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"), b"derdata")
2013        gn3 = x509.OtherName(x509.ObjectIdentifier("1.2.3.5"), b"derdata")
2014        assert hash(gn) == hash(gn2)
2015        assert hash(gn) != hash(gn3)
2016
2017
2018class TestGeneralNames(object):
2019    def test_get_values_for_type(self):
2020        gns = x509.GeneralNames(
2021            [x509.DNSName(u"cryptography.io")]
2022        )
2023        names = gns.get_values_for_type(x509.DNSName)
2024        assert names == [u"cryptography.io"]
2025
2026    def test_iter_names(self):
2027        gns = x509.GeneralNames([
2028            x509.DNSName(u"cryptography.io"),
2029            x509.DNSName(u"crypto.local"),
2030        ])
2031        assert len(gns) == 2
2032        assert list(gns) == [
2033            x509.DNSName(u"cryptography.io"),
2034            x509.DNSName(u"crypto.local"),
2035        ]
2036
2037    def test_iter_input(self):
2038        names = [
2039            x509.DNSName(u"cryptography.io"),
2040            x509.DNSName(u"crypto.local"),
2041        ]
2042        gns = x509.GeneralNames(iter(names))
2043        assert list(gns) == names
2044
2045    def test_indexing(self):
2046        gn = x509.GeneralNames([
2047            x509.DNSName(u"cryptography.io"),
2048            x509.DNSName(u"crypto.local"),
2049            x509.DNSName(u"another.local"),
2050            x509.RFC822Name(u"email@another.local"),
2051            x509.UniformResourceIdentifier(u"http://another.local"),
2052        ])
2053        assert gn[-1] == gn[4]
2054        assert gn[2:6:2] == [gn[2], gn[4]]
2055
2056    def test_invalid_general_names(self):
2057        with pytest.raises(TypeError):
2058            x509.GeneralNames(
2059                [x509.DNSName(u"cryptography.io"), "invalid"]
2060            )
2061
2062    def test_repr(self):
2063        gns = x509.GeneralNames(
2064            [
2065                x509.DNSName(u"cryptography.io")
2066            ]
2067        )
2068        if not six.PY2:
2069            assert repr(gns) == (
2070                "<GeneralNames([<DNSName(value='cryptography.io')>])>"
2071            )
2072        else:
2073            assert repr(gns) == (
2074                "<GeneralNames([<DNSName(value=u'cryptography.io')>])>"
2075            )
2076
2077    def test_eq(self):
2078        gns = x509.GeneralNames(
2079            [x509.DNSName(u"cryptography.io")]
2080        )
2081        gns2 = x509.GeneralNames(
2082            [x509.DNSName(u"cryptography.io")]
2083        )
2084        assert gns == gns2
2085
2086    def test_ne(self):
2087        gns = x509.GeneralNames(
2088            [x509.DNSName(u"cryptography.io")]
2089        )
2090        gns2 = x509.GeneralNames(
2091            [x509.RFC822Name(u"admin@cryptography.io")]
2092        )
2093        assert gns != gns2
2094        assert gns != object()
2095
2096    def test_hash(self):
2097        gns = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
2098        gns2 = x509.GeneralNames([x509.DNSName(u"cryptography.io")])
2099        gns3 = x509.GeneralNames([x509.RFC822Name(u"admin@cryptography.io")])
2100        assert hash(gns) == hash(gns2)
2101        assert hash(gns) != hash(gns3)
2102
2103
2104class TestIssuerAlternativeName(object):
2105    def test_get_values_for_type(self):
2106        san = x509.IssuerAlternativeName(
2107            [x509.DNSName(u"cryptography.io")]
2108        )
2109        names = san.get_values_for_type(x509.DNSName)
2110        assert names == [u"cryptography.io"]
2111
2112    def test_iter_names(self):
2113        san = x509.IssuerAlternativeName([
2114            x509.DNSName(u"cryptography.io"),
2115            x509.DNSName(u"crypto.local"),
2116        ])
2117        assert len(san) == 2
2118        assert list(san) == [
2119            x509.DNSName(u"cryptography.io"),
2120            x509.DNSName(u"crypto.local"),
2121        ]
2122
2123    def test_indexing(self):
2124        ian = x509.IssuerAlternativeName([
2125            x509.DNSName(u"cryptography.io"),
2126            x509.DNSName(u"crypto.local"),
2127            x509.DNSName(u"another.local"),
2128            x509.RFC822Name(u"email@another.local"),
2129            x509.UniformResourceIdentifier(u"http://another.local"),
2130        ])
2131        assert ian[-1] == ian[4]
2132        assert ian[2:6:2] == [ian[2], ian[4]]
2133
2134    def test_invalid_general_names(self):
2135        with pytest.raises(TypeError):
2136            x509.IssuerAlternativeName(
2137                [x509.DNSName(u"cryptography.io"), "invalid"]
2138            )
2139
2140    def test_repr(self):
2141        san = x509.IssuerAlternativeName(
2142            [
2143                x509.DNSName(u"cryptography.io")
2144            ]
2145        )
2146        if not six.PY2:
2147            assert repr(san) == (
2148                "<IssuerAlternativeName("
2149                "<GeneralNames([<DNSName(value='cryptography.io')>])>)>"
2150            )
2151        else:
2152            assert repr(san) == (
2153                "<IssuerAlternativeName("
2154                "<GeneralNames([<DNSName(value=u'cryptography.io')>])>)>"
2155            )
2156
2157    def test_eq(self):
2158        san = x509.IssuerAlternativeName(
2159            [x509.DNSName(u"cryptography.io")]
2160        )
2161        san2 = x509.IssuerAlternativeName(
2162            [x509.DNSName(u"cryptography.io")]
2163        )
2164        assert san == san2
2165
2166    def test_ne(self):
2167        san = x509.IssuerAlternativeName(
2168            [x509.DNSName(u"cryptography.io")]
2169        )
2170        san2 = x509.IssuerAlternativeName(
2171            [x509.RFC822Name(u"admin@cryptography.io")]
2172        )
2173        assert san != san2
2174        assert san != object()
2175
2176    def test_hash(self):
2177        ian = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
2178        ian2 = x509.IssuerAlternativeName([x509.DNSName(u"cryptography.io")])
2179        ian3 = x509.IssuerAlternativeName(
2180            [x509.RFC822Name(u"admin@cryptography.io")]
2181        )
2182        assert hash(ian) == hash(ian2)
2183        assert hash(ian) != hash(ian3)
2184
2185
2186@pytest.mark.requires_backend_interface(interface=RSABackend)
2187@pytest.mark.requires_backend_interface(interface=X509Backend)
2188class TestRSAIssuerAlternativeNameExtension(object):
2189    def test_uri(self, backend):
2190        cert = _load_cert(
2191            os.path.join("x509", "custom", "ian_uri.pem"),
2192            x509.load_pem_x509_certificate,
2193            backend,
2194        )
2195        ext = cert.extensions.get_extension_for_oid(
2196            ExtensionOID.ISSUER_ALTERNATIVE_NAME
2197        )
2198        assert list(ext.value) == [
2199            x509.UniformResourceIdentifier(u"http://path.to.root/root.crt"),
2200        ]
2201
2202
2203class TestCRLNumber(object):
2204    def test_eq(self):
2205        crl_number = x509.CRLNumber(15)
2206        assert crl_number == x509.CRLNumber(15)
2207
2208    def test_ne(self):
2209        crl_number = x509.CRLNumber(15)
2210        assert crl_number != x509.CRLNumber(14)
2211        assert crl_number != object()
2212
2213    def test_repr(self):
2214        crl_number = x509.CRLNumber(15)
2215        assert repr(crl_number) == "<CRLNumber(15)>"
2216
2217    def test_invalid_number(self):
2218        with pytest.raises(TypeError):
2219            x509.CRLNumber("notanumber")
2220
2221    def test_hash(self):
2222        c1 = x509.CRLNumber(1)
2223        c2 = x509.CRLNumber(1)
2224        c3 = x509.CRLNumber(2)
2225        assert hash(c1) == hash(c2)
2226        assert hash(c1) != hash(c3)
2227
2228
2229class TestSubjectAlternativeName(object):
2230    def test_get_values_for_type(self):
2231        san = x509.SubjectAlternativeName(
2232            [x509.DNSName(u"cryptography.io")]
2233        )
2234        names = san.get_values_for_type(x509.DNSName)
2235        assert names == [u"cryptography.io"]
2236
2237    def test_iter_names(self):
2238        san = x509.SubjectAlternativeName([
2239            x509.DNSName(u"cryptography.io"),
2240            x509.DNSName(u"crypto.local"),
2241        ])
2242        assert len(san) == 2
2243        assert list(san) == [
2244            x509.DNSName(u"cryptography.io"),
2245            x509.DNSName(u"crypto.local"),
2246        ]
2247
2248    def test_indexing(self):
2249        san = x509.SubjectAlternativeName([
2250            x509.DNSName(u"cryptography.io"),
2251            x509.DNSName(u"crypto.local"),
2252            x509.DNSName(u"another.local"),
2253            x509.RFC822Name(u"email@another.local"),
2254            x509.UniformResourceIdentifier(u"http://another.local"),
2255        ])
2256        assert san[-1] == san[4]
2257        assert san[2:6:2] == [san[2], san[4]]
2258
2259    def test_invalid_general_names(self):
2260        with pytest.raises(TypeError):
2261            x509.SubjectAlternativeName(
2262                [x509.DNSName(u"cryptography.io"), "invalid"]
2263            )
2264
2265    def test_repr(self):
2266        san = x509.SubjectAlternativeName(
2267            [
2268                x509.DNSName(u"cryptography.io")
2269            ]
2270        )
2271        if not six.PY2:
2272            assert repr(san) == (
2273                "<SubjectAlternativeName("
2274                "<GeneralNames([<DNSName(value='cryptography.io')>])>)>"
2275            )
2276        else:
2277            assert repr(san) == (
2278                "<SubjectAlternativeName("
2279                "<GeneralNames([<DNSName(value=u'cryptography.io')>])>)>"
2280            )
2281
2282    def test_eq(self):
2283        san = x509.SubjectAlternativeName(
2284            [x509.DNSName(u"cryptography.io")]
2285        )
2286        san2 = x509.SubjectAlternativeName(
2287            [x509.DNSName(u"cryptography.io")]
2288        )
2289        assert san == san2
2290
2291    def test_ne(self):
2292        san = x509.SubjectAlternativeName(
2293            [x509.DNSName(u"cryptography.io")]
2294        )
2295        san2 = x509.SubjectAlternativeName(
2296            [x509.RFC822Name(u"admin@cryptography.io")]
2297        )
2298        assert san != san2
2299        assert san != object()
2300
2301    def test_hash(self):
2302        san = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
2303        san2 = x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")])
2304        san3 = x509.SubjectAlternativeName(
2305            [x509.RFC822Name(u"admin@cryptography.io")]
2306        )
2307        assert hash(san) == hash(san2)
2308        assert hash(san) != hash(san3)
2309
2310
2311@pytest.mark.requires_backend_interface(interface=RSABackend)
2312@pytest.mark.requires_backend_interface(interface=X509Backend)
2313class TestRSASubjectAlternativeNameExtension(object):
2314    def test_dns_name(self, backend):
2315        cert = _load_cert(
2316            os.path.join("x509", "cryptography.io.pem"),
2317            x509.load_pem_x509_certificate,
2318            backend
2319        )
2320        ext = cert.extensions.get_extension_for_oid(
2321            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2322        )
2323        assert ext is not None
2324        assert ext.critical is False
2325
2326        san = ext.value
2327
2328        dns = san.get_values_for_type(x509.DNSName)
2329        assert dns == [u"www.cryptography.io", u"cryptography.io"]
2330
2331    def test_wildcard_dns_name(self, backend):
2332        cert = _load_cert(
2333            os.path.join("x509", "wildcard_san.pem"),
2334            x509.load_pem_x509_certificate,
2335            backend
2336        )
2337        ext = cert.extensions.get_extension_for_oid(
2338            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2339        )
2340
2341        dns = ext.value.get_values_for_type(x509.DNSName)
2342        assert dns == [
2343            u'*.langui.sh',
2344            u'langui.sh',
2345            u'*.saseliminator.com',
2346            u'saseliminator.com'
2347        ]
2348
2349    def test_san_empty_hostname(self, backend):
2350        cert = _load_cert(
2351            os.path.join(
2352                "x509", "custom", "san_empty_hostname.pem"
2353            ),
2354            x509.load_pem_x509_certificate,
2355            backend
2356        )
2357        san = cert.extensions.get_extension_for_oid(
2358            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2359        )
2360
2361        dns = san.value.get_values_for_type(x509.DNSName)
2362        assert dns == [u'']
2363
2364    def test_san_wildcard_idna_dns_name(self, backend):
2365        cert = _load_cert(
2366            os.path.join("x509", "custom", "san_wildcard_idna.pem"),
2367            x509.load_pem_x509_certificate,
2368            backend
2369        )
2370        ext = cert.extensions.get_extension_for_oid(
2371            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2372        )
2373
2374        dns = ext.value.get_values_for_type(x509.DNSName)
2375        assert dns == [u'*.xn--80ato2c.cryptography']
2376
2377    def test_unsupported_gn(self, backend):
2378        cert = _load_cert(
2379            os.path.join("x509", "san_x400address.der"),
2380            x509.load_der_x509_certificate,
2381            backend
2382        )
2383        with pytest.raises(x509.UnsupportedGeneralNameType) as exc:
2384            cert.extensions
2385
2386        assert exc.value.type == 3
2387
2388    def test_registered_id(self, backend):
2389        cert = _load_cert(
2390            os.path.join(
2391                "x509", "custom", "san_registered_id.pem"
2392            ),
2393            x509.load_pem_x509_certificate,
2394            backend
2395        )
2396        ext = cert.extensions.get_extension_for_oid(
2397            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2398        )
2399        assert ext is not None
2400        assert ext.critical is False
2401
2402        san = ext.value
2403        rid = san.get_values_for_type(x509.RegisteredID)
2404        assert rid == [x509.ObjectIdentifier("1.2.3.4")]
2405
2406    def test_uri(self, backend):
2407        cert = _load_cert(
2408            os.path.join(
2409                "x509", "custom", "san_uri_with_port.pem"
2410            ),
2411            x509.load_pem_x509_certificate,
2412            backend
2413        )
2414        ext = cert.extensions.get_extension_for_oid(
2415            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2416        )
2417        assert ext is not None
2418        uri = ext.value.get_values_for_type(
2419            x509.UniformResourceIdentifier
2420        )
2421        assert uri == [
2422            u"gopher://xn--80ato2c.cryptography:70/path?q=s#hel"
2423            u"lo",
2424            u"http://someregulardomain.com",
2425        ]
2426
2427    def test_ipaddress(self, backend):
2428        cert = _load_cert(
2429            os.path.join(
2430                "x509", "custom", "san_ipaddr.pem"
2431            ),
2432            x509.load_pem_x509_certificate,
2433            backend
2434        )
2435        ext = cert.extensions.get_extension_for_oid(
2436            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2437        )
2438        assert ext is not None
2439        assert ext.critical is False
2440
2441        san = ext.value
2442
2443        ip = san.get_values_for_type(x509.IPAddress)
2444        assert [
2445            ipaddress.ip_address(u"127.0.0.1"),
2446            ipaddress.ip_address(u"ff::")
2447        ] == ip
2448
2449    def test_dirname(self, backend):
2450        cert = _load_cert(
2451            os.path.join(
2452                "x509", "custom", "san_dirname.pem"
2453            ),
2454            x509.load_pem_x509_certificate,
2455            backend
2456        )
2457        ext = cert.extensions.get_extension_for_oid(
2458            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2459        )
2460        assert ext is not None
2461        assert ext.critical is False
2462
2463        san = ext.value
2464
2465        dirname = san.get_values_for_type(x509.DirectoryName)
2466        assert [
2467            x509.Name([
2468                x509.NameAttribute(NameOID.COMMON_NAME, u'test'),
2469                x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Org'),
2470                x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
2471            ])
2472        ] == dirname
2473
2474    def test_rfc822name(self, backend):
2475        cert = _load_cert(
2476            os.path.join(
2477                "x509", "custom", "san_rfc822_idna.pem"
2478            ),
2479            x509.load_pem_x509_certificate,
2480            backend
2481        )
2482        ext = cert.extensions.get_extension_for_oid(
2483            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2484        )
2485        assert ext is not None
2486        assert ext.critical is False
2487
2488        san = ext.value
2489
2490        rfc822name = san.get_values_for_type(x509.RFC822Name)
2491        assert [u"email@xn--eml-vla4c.com"] == rfc822name
2492
2493    def test_idna2003_invalid(self, backend):
2494        cert = _load_cert(
2495            os.path.join(
2496                "x509", "custom", "san_idna2003_dnsname.pem"
2497            ),
2498            x509.load_pem_x509_certificate,
2499            backend
2500        )
2501        san = cert.extensions.get_extension_for_class(
2502            x509.SubjectAlternativeName
2503        ).value
2504
2505        assert len(san) == 1
2506        [name] = san
2507        assert name.value == u"xn--k4h.ws"
2508
2509    def test_unicode_rfc822_name_dns_name_uri(self, backend):
2510        cert = _load_cert(
2511            os.path.join(
2512                "x509", "custom", "san_idna_names.pem"
2513            ),
2514            x509.load_pem_x509_certificate,
2515            backend
2516        )
2517        ext = cert.extensions.get_extension_for_oid(
2518            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2519        )
2520        assert ext is not None
2521        rfc822_name = ext.value.get_values_for_type(x509.RFC822Name)
2522        dns_name = ext.value.get_values_for_type(x509.DNSName)
2523        uri = ext.value.get_values_for_type(x509.UniformResourceIdentifier)
2524        assert rfc822_name == [u"email@xn--80ato2c.cryptography"]
2525        assert dns_name == [u"xn--80ato2c.cryptography"]
2526        assert uri == [u"https://www.xn--80ato2c.cryptography"]
2527
2528    def test_rfc822name_dnsname_ipaddress_directoryname_uri(self, backend):
2529        cert = _load_cert(
2530            os.path.join(
2531                "x509", "custom", "san_email_dns_ip_dirname_uri.pem"
2532            ),
2533            x509.load_pem_x509_certificate,
2534            backend
2535        )
2536        ext = cert.extensions.get_extension_for_oid(
2537            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2538        )
2539        assert ext is not None
2540        assert ext.critical is False
2541
2542        san = ext.value
2543
2544        rfc822_name = san.get_values_for_type(x509.RFC822Name)
2545        uri = san.get_values_for_type(x509.UniformResourceIdentifier)
2546        dns = san.get_values_for_type(x509.DNSName)
2547        ip = san.get_values_for_type(x509.IPAddress)
2548        dirname = san.get_values_for_type(x509.DirectoryName)
2549        assert [u"user@cryptography.io"] == rfc822_name
2550        assert [u"https://cryptography.io"] == uri
2551        assert [u"cryptography.io"] == dns
2552        assert [
2553            x509.Name([
2554                x509.NameAttribute(NameOID.COMMON_NAME, u'dirCN'),
2555                x509.NameAttribute(
2556                    NameOID.ORGANIZATION_NAME, u'Cryptographic Authority'
2557                ),
2558            ])
2559        ] == dirname
2560        assert [
2561            ipaddress.ip_address(u"127.0.0.1"),
2562            ipaddress.ip_address(u"ff::")
2563        ] == ip
2564
2565    def test_invalid_rfc822name(self, backend):
2566        cert = _load_cert(
2567            os.path.join(
2568                "x509", "custom", "san_rfc822_names.pem"
2569            ),
2570            x509.load_pem_x509_certificate,
2571            backend
2572        )
2573        san = cert.extensions.get_extension_for_class(
2574            x509.SubjectAlternativeName
2575        ).value
2576        values = san.get_values_for_type(x509.RFC822Name)
2577        assert values == [
2578            u'email', u'email <email>', u'email <email@email>',
2579            u'email <email@xn--eml-vla4c.com>', u'myemail:'
2580        ]
2581
2582    def test_other_name(self, backend):
2583        cert = _load_cert(
2584            os.path.join(
2585                "x509", "custom", "san_other_name.pem"
2586            ),
2587            x509.load_pem_x509_certificate,
2588            backend
2589        )
2590
2591        ext = cert.extensions.get_extension_for_oid(
2592            ExtensionOID.SUBJECT_ALTERNATIVE_NAME
2593        )
2594        assert ext is not None
2595        assert ext.critical is False
2596
2597        expected = x509.OtherName(x509.ObjectIdentifier("1.2.3.4"),
2598                                  b'\x16\x0bHello World')
2599        assert len(ext.value) == 1
2600        assert list(ext.value)[0] == expected
2601
2602        othernames = ext.value.get_values_for_type(x509.OtherName)
2603        assert othernames == [expected]
2604
2605    def test_certbuilder(self, backend):
2606        sans = [u'*.example.org', u'*.xn--4ca7aey.example.com',
2607                u'foobar.example.net']
2608        private_key = RSA_KEY_2048.private_key(backend)
2609        builder = _make_certbuilder(private_key)
2610        builder = builder.add_extension(
2611            SubjectAlternativeName(list(map(DNSName, sans))), True)
2612
2613        cert = builder.sign(private_key, hashes.SHA1(), backend)
2614        result = [
2615            x.value
2616            for x in cert.extensions.get_extension_for_class(
2617                SubjectAlternativeName
2618            ).value
2619        ]
2620        assert result == sans
2621
2622
2623@pytest.mark.requires_backend_interface(interface=RSABackend)
2624@pytest.mark.requires_backend_interface(interface=X509Backend)
2625class TestExtendedKeyUsageExtension(object):
2626    def test_eku(self, backend):
2627        cert = _load_cert(
2628            os.path.join(
2629                "x509", "custom", "extended_key_usage.pem"
2630            ),
2631            x509.load_pem_x509_certificate,
2632            backend
2633        )
2634        ext = cert.extensions.get_extension_for_oid(
2635            ExtensionOID.EXTENDED_KEY_USAGE
2636        )
2637        assert ext is not None
2638        assert ext.critical is False
2639
2640        assert [
2641            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
2642            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
2643            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.3"),
2644            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.4"),
2645            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.9"),
2646            x509.ObjectIdentifier("1.3.6.1.5.5.7.3.8"),
2647            x509.ObjectIdentifier("2.5.29.37.0"),
2648            x509.ObjectIdentifier("2.16.840.1.113730.4.1"),
2649        ] == list(ext.value)
2650
2651
2652class TestAccessDescription(object):
2653    def test_invalid_access_method(self):
2654        with pytest.raises(TypeError):
2655            x509.AccessDescription("notanoid", x509.DNSName(u"test"))
2656
2657    def test_invalid_access_location(self):
2658        with pytest.raises(TypeError):
2659            x509.AccessDescription(
2660                AuthorityInformationAccessOID.CA_ISSUERS, "invalid"
2661            )
2662
2663    def test_valid_nonstandard_method(self):
2664        ad = x509.AccessDescription(
2665            ObjectIdentifier("2.999.1"),
2666            x509.UniformResourceIdentifier(u"http://example.com")
2667        )
2668        assert ad is not None
2669
2670    def test_repr(self):
2671        ad = x509.AccessDescription(
2672            AuthorityInformationAccessOID.OCSP,
2673            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2674        )
2675        if not six.PY2:
2676            assert repr(ad) == (
2677                "<AccessDescription(access_method=<ObjectIdentifier(oid=1.3.6"
2678                ".1.5.5.7.48.1, name=OCSP)>, access_location=<UniformResource"
2679                "Identifier(value='http://ocsp.domain.com')>)>"
2680            )
2681        else:
2682            assert repr(ad) == (
2683                "<AccessDescription(access_method=<ObjectIdentifier(oid=1.3.6"
2684                ".1.5.5.7.48.1, name=OCSP)>, access_location=<UniformResource"
2685                "Identifier(value=u'http://ocsp.domain.com')>)>"
2686            )
2687
2688    def test_eq(self):
2689        ad = x509.AccessDescription(
2690            AuthorityInformationAccessOID.OCSP,
2691            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2692        )
2693        ad2 = x509.AccessDescription(
2694            AuthorityInformationAccessOID.OCSP,
2695            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2696        )
2697        assert ad == ad2
2698
2699    def test_ne(self):
2700        ad = x509.AccessDescription(
2701            AuthorityInformationAccessOID.OCSP,
2702            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2703        )
2704        ad2 = x509.AccessDescription(
2705            AuthorityInformationAccessOID.CA_ISSUERS,
2706            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2707        )
2708        ad3 = x509.AccessDescription(
2709            AuthorityInformationAccessOID.OCSP,
2710            x509.UniformResourceIdentifier(u"http://notthesame")
2711        )
2712        assert ad != ad2
2713        assert ad != ad3
2714        assert ad != object()
2715
2716    def test_hash(self):
2717        ad = x509.AccessDescription(
2718            AuthorityInformationAccessOID.OCSP,
2719            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2720        )
2721        ad2 = x509.AccessDescription(
2722            AuthorityInformationAccessOID.OCSP,
2723            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2724        )
2725        ad3 = x509.AccessDescription(
2726            AuthorityInformationAccessOID.CA_ISSUERS,
2727            x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2728        )
2729        assert hash(ad) == hash(ad2)
2730        assert hash(ad) != hash(ad3)
2731
2732
2733class TestPolicyConstraints(object):
2734    def test_invalid_explicit_policy(self):
2735        with pytest.raises(TypeError):
2736            x509.PolicyConstraints("invalid", None)
2737
2738    def test_invalid_inhibit_policy(self):
2739        with pytest.raises(TypeError):
2740            x509.PolicyConstraints(None, "invalid")
2741
2742    def test_both_none(self):
2743        with pytest.raises(ValueError):
2744            x509.PolicyConstraints(None, None)
2745
2746    def test_repr(self):
2747        pc = x509.PolicyConstraints(0, None)
2748
2749        assert repr(pc) == (
2750            u"<PolicyConstraints(require_explicit_policy=0, inhibit_policy_ma"
2751            u"pping=None)>"
2752        )
2753
2754    def test_eq(self):
2755        pc = x509.PolicyConstraints(2, 1)
2756        pc2 = x509.PolicyConstraints(2, 1)
2757        assert pc == pc2
2758
2759    def test_ne(self):
2760        pc = x509.PolicyConstraints(2, 1)
2761        pc2 = x509.PolicyConstraints(2, 2)
2762        pc3 = x509.PolicyConstraints(3, 1)
2763        assert pc != pc2
2764        assert pc != pc3
2765        assert pc != object()
2766
2767    def test_hash(self):
2768        pc = x509.PolicyConstraints(2, 1)
2769        pc2 = x509.PolicyConstraints(2, 1)
2770        pc3 = x509.PolicyConstraints(2, None)
2771        assert hash(pc) == hash(pc2)
2772        assert hash(pc) != hash(pc3)
2773
2774
2775@pytest.mark.requires_backend_interface(interface=RSABackend)
2776@pytest.mark.requires_backend_interface(interface=X509Backend)
2777class TestPolicyConstraintsExtension(object):
2778    def test_inhibit_policy_mapping(self, backend):
2779        cert = _load_cert(
2780            os.path.join("x509", "department-of-state-root.pem"),
2781            x509.load_pem_x509_certificate,
2782            backend
2783        )
2784        ext = cert.extensions.get_extension_for_oid(
2785            ExtensionOID.POLICY_CONSTRAINTS,
2786        )
2787        assert ext.critical is True
2788
2789        assert ext.value == x509.PolicyConstraints(
2790            require_explicit_policy=None, inhibit_policy_mapping=0,
2791        )
2792
2793    def test_require_explicit_policy(self, backend):
2794        cert = _load_cert(
2795            os.path.join("x509", "custom", "policy_constraints_explicit.pem"),
2796            x509.load_pem_x509_certificate,
2797            backend
2798        )
2799        ext = cert.extensions.get_extension_for_oid(
2800            ExtensionOID.POLICY_CONSTRAINTS
2801        )
2802        assert ext.critical is True
2803        assert ext.value == x509.PolicyConstraints(
2804            require_explicit_policy=1, inhibit_policy_mapping=None,
2805        )
2806
2807
2808class TestAuthorityInformationAccess(object):
2809    def test_invalid_descriptions(self):
2810        with pytest.raises(TypeError):
2811            x509.AuthorityInformationAccess(["notanAccessDescription"])
2812
2813    def test_iter_len(self):
2814        aia = x509.AuthorityInformationAccess([
2815            x509.AccessDescription(
2816                AuthorityInformationAccessOID.OCSP,
2817                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2818            ),
2819            x509.AccessDescription(
2820                AuthorityInformationAccessOID.CA_ISSUERS,
2821                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2822            )
2823        ])
2824        assert len(aia) == 2
2825        assert list(aia) == [
2826            x509.AccessDescription(
2827                AuthorityInformationAccessOID.OCSP,
2828                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2829            ),
2830            x509.AccessDescription(
2831                AuthorityInformationAccessOID.CA_ISSUERS,
2832                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2833            )
2834        ]
2835
2836    def test_iter_input(self):
2837        desc = [
2838            x509.AccessDescription(
2839                AuthorityInformationAccessOID.OCSP,
2840                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2841            )
2842        ]
2843        aia = x509.AuthorityInformationAccess(iter(desc))
2844        assert list(aia) == desc
2845
2846    def test_repr(self):
2847        aia = x509.AuthorityInformationAccess([
2848            x509.AccessDescription(
2849                AuthorityInformationAccessOID.OCSP,
2850                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2851            ),
2852            x509.AccessDescription(
2853                AuthorityInformationAccessOID.CA_ISSUERS,
2854                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2855            )
2856        ])
2857        if not six.PY2:
2858            assert repr(aia) == (
2859                "<AuthorityInformationAccess([<AccessDescription(access_method"
2860                "=<ObjectIdentifier(oid=1.3.6.1.5.5.7.48.1, name=OCSP)>, acces"
2861                "s_location=<UniformResourceIdentifier(value='http://oc"
2862                "sp.domain.com')>)>, <AccessDescription(access_method=<ObjectI"
2863                "dentifier(oid=1.3.6.1.5.5.7.48.2, name=caIssuers)>, access_lo"
2864                "cation=<UniformResourceIdentifier(value='http://domain"
2865                ".com/ca.crt')>)>])>"
2866            )
2867        else:
2868            assert repr(aia) == (
2869                "<AuthorityInformationAccess([<AccessDescription(access_method"
2870                "=<ObjectIdentifier(oid=1.3.6.1.5.5.7.48.1, name=OCSP)>, acces"
2871                "s_location=<UniformResourceIdentifier(value=u'http://oc"
2872                "sp.domain.com')>)>, <AccessDescription(access_method=<ObjectI"
2873                "dentifier(oid=1.3.6.1.5.5.7.48.2, name=caIssuers)>, access_lo"
2874                "cation=<UniformResourceIdentifier(value=u'http://domain"
2875                ".com/ca.crt')>)>])>"
2876            )
2877
2878    def test_eq(self):
2879        aia = x509.AuthorityInformationAccess([
2880            x509.AccessDescription(
2881                AuthorityInformationAccessOID.OCSP,
2882                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2883            ),
2884            x509.AccessDescription(
2885                AuthorityInformationAccessOID.CA_ISSUERS,
2886                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2887            )
2888        ])
2889        aia2 = x509.AuthorityInformationAccess([
2890            x509.AccessDescription(
2891                AuthorityInformationAccessOID.OCSP,
2892                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2893            ),
2894            x509.AccessDescription(
2895                AuthorityInformationAccessOID.CA_ISSUERS,
2896                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2897            )
2898        ])
2899        assert aia == aia2
2900
2901    def test_ne(self):
2902        aia = x509.AuthorityInformationAccess([
2903            x509.AccessDescription(
2904                AuthorityInformationAccessOID.OCSP,
2905                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2906            ),
2907            x509.AccessDescription(
2908                AuthorityInformationAccessOID.CA_ISSUERS,
2909                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2910            )
2911        ])
2912        aia2 = x509.AuthorityInformationAccess([
2913            x509.AccessDescription(
2914                AuthorityInformationAccessOID.OCSP,
2915                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2916            ),
2917        ])
2918
2919        assert aia != aia2
2920        assert aia != object()
2921
2922    def test_indexing(self):
2923        aia = x509.AuthorityInformationAccess([
2924            x509.AccessDescription(
2925                AuthorityInformationAccessOID.OCSP,
2926                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2927            ),
2928            x509.AccessDescription(
2929                AuthorityInformationAccessOID.CA_ISSUERS,
2930                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2931            ),
2932            x509.AccessDescription(
2933                AuthorityInformationAccessOID.OCSP,
2934                x509.UniformResourceIdentifier(u"http://ocsp2.domain.com")
2935            ),
2936            x509.AccessDescription(
2937                AuthorityInformationAccessOID.OCSP,
2938                x509.UniformResourceIdentifier(u"http://ocsp3.domain.com")
2939            ),
2940            x509.AccessDescription(
2941                AuthorityInformationAccessOID.OCSP,
2942                x509.UniformResourceIdentifier(u"http://ocsp4.domain.com")
2943            ),
2944        ])
2945        assert aia[-1] == aia[4]
2946        assert aia[2:6:2] == [aia[2], aia[4]]
2947
2948    def test_hash(self):
2949        aia = x509.AuthorityInformationAccess([
2950            x509.AccessDescription(
2951                AuthorityInformationAccessOID.OCSP,
2952                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2953            ),
2954            x509.AccessDescription(
2955                AuthorityInformationAccessOID.CA_ISSUERS,
2956                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2957            )
2958        ])
2959        aia2 = x509.AuthorityInformationAccess([
2960            x509.AccessDescription(
2961                AuthorityInformationAccessOID.OCSP,
2962                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
2963            ),
2964            x509.AccessDescription(
2965                AuthorityInformationAccessOID.CA_ISSUERS,
2966                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2967            )
2968        ])
2969        aia3 = x509.AuthorityInformationAccess([
2970            x509.AccessDescription(
2971                AuthorityInformationAccessOID.OCSP,
2972                x509.UniformResourceIdentifier(u"http://ocsp.other.com")
2973            ),
2974            x509.AccessDescription(
2975                AuthorityInformationAccessOID.CA_ISSUERS,
2976                x509.UniformResourceIdentifier(u"http://domain.com/ca.crt")
2977            )
2978        ])
2979        assert hash(aia) == hash(aia2)
2980        assert hash(aia) != hash(aia3)
2981
2982
2983@pytest.mark.requires_backend_interface(interface=RSABackend)
2984@pytest.mark.requires_backend_interface(interface=X509Backend)
2985class TestAuthorityInformationAccessExtension(object):
2986    def test_aia_ocsp_ca_issuers(self, backend):
2987        cert = _load_cert(
2988            os.path.join("x509", "cryptography.io.pem"),
2989            x509.load_pem_x509_certificate,
2990            backend
2991        )
2992        ext = cert.extensions.get_extension_for_oid(
2993            ExtensionOID.AUTHORITY_INFORMATION_ACCESS
2994        )
2995        assert ext is not None
2996        assert ext.critical is False
2997
2998        assert ext.value == x509.AuthorityInformationAccess([
2999            x509.AccessDescription(
3000                AuthorityInformationAccessOID.OCSP,
3001                x509.UniformResourceIdentifier(u"http://gv.symcd.com")
3002            ),
3003            x509.AccessDescription(
3004                AuthorityInformationAccessOID.CA_ISSUERS,
3005                x509.UniformResourceIdentifier(u"http://gv.symcb.com/gv.crt")
3006            ),
3007        ])
3008
3009    def test_aia_multiple_ocsp_ca_issuers(self, backend):
3010        cert = _load_cert(
3011            os.path.join("x509", "custom", "aia_ocsp_ca_issuers.pem"),
3012            x509.load_pem_x509_certificate,
3013            backend
3014        )
3015        ext = cert.extensions.get_extension_for_oid(
3016            ExtensionOID.AUTHORITY_INFORMATION_ACCESS
3017        )
3018        assert ext is not None
3019        assert ext.critical is False
3020
3021        assert ext.value == x509.AuthorityInformationAccess([
3022            x509.AccessDescription(
3023                AuthorityInformationAccessOID.OCSP,
3024                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
3025            ),
3026            x509.AccessDescription(
3027                AuthorityInformationAccessOID.OCSP,
3028                x509.UniformResourceIdentifier(u"http://ocsp2.domain.com")
3029            ),
3030            x509.AccessDescription(
3031                AuthorityInformationAccessOID.CA_ISSUERS,
3032                x509.DirectoryName(x509.Name([
3033                    x509.NameAttribute(NameOID.COMMON_NAME, u"myCN"),
3034                    x509.NameAttribute(NameOID.ORGANIZATION_NAME,
3035                                       u"some Org"),
3036                ]))
3037            ),
3038        ])
3039
3040    def test_aia_ocsp_only(self, backend):
3041        cert = _load_cert(
3042            os.path.join("x509", "custom", "aia_ocsp.pem"),
3043            x509.load_pem_x509_certificate,
3044            backend
3045        )
3046        ext = cert.extensions.get_extension_for_oid(
3047            ExtensionOID.AUTHORITY_INFORMATION_ACCESS
3048        )
3049        assert ext is not None
3050        assert ext.critical is False
3051
3052        assert ext.value == x509.AuthorityInformationAccess([
3053            x509.AccessDescription(
3054                AuthorityInformationAccessOID.OCSP,
3055                x509.UniformResourceIdentifier(u"http://ocsp.domain.com")
3056            ),
3057        ])
3058
3059    def test_aia_ca_issuers_only(self, backend):
3060        cert = _load_cert(
3061            os.path.join("x509", "custom", "aia_ca_issuers.pem"),
3062            x509.load_pem_x509_certificate,
3063            backend
3064        )
3065        ext = cert.extensions.get_extension_for_oid(
3066            ExtensionOID.AUTHORITY_INFORMATION_ACCESS
3067        )
3068        assert ext is not None
3069        assert ext.critical is False
3070
3071        assert ext.value == x509.AuthorityInformationAccess([
3072            x509.AccessDescription(
3073                AuthorityInformationAccessOID.CA_ISSUERS,
3074                x509.DirectoryName(x509.Name([
3075                    x509.NameAttribute(NameOID.COMMON_NAME, u"myCN"),
3076                    x509.NameAttribute(NameOID.ORGANIZATION_NAME,
3077                                       u"some Org"),
3078                ]))
3079            ),
3080        ])
3081
3082
3083@pytest.mark.requires_backend_interface(interface=RSABackend)
3084@pytest.mark.requires_backend_interface(interface=X509Backend)
3085class TestAuthorityKeyIdentifierExtension(object):
3086    def test_aki_keyid(self, backend):
3087        cert = _load_cert(
3088            os.path.join(
3089                "x509", "cryptography.io.pem"
3090            ),
3091            x509.load_pem_x509_certificate,
3092            backend
3093        )
3094        ext = cert.extensions.get_extension_for_oid(
3095            ExtensionOID.AUTHORITY_KEY_IDENTIFIER
3096        )
3097        assert ext is not None
3098        assert ext.critical is False
3099
3100        assert ext.value.key_identifier == (
3101            b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08\xcbY"
3102        )
3103        assert ext.value.authority_cert_issuer is None
3104        assert ext.value.authority_cert_serial_number is None
3105
3106    def test_aki_all_fields(self, backend):
3107        cert = _load_cert(
3108            os.path.join(
3109                "x509", "custom", "authority_key_identifier.pem"
3110            ),
3111            x509.load_pem_x509_certificate,
3112            backend
3113        )
3114        ext = cert.extensions.get_extension_for_oid(
3115            ExtensionOID.AUTHORITY_KEY_IDENTIFIER
3116        )
3117        assert ext is not None
3118        assert ext.critical is False
3119
3120        assert ext.value.key_identifier == (
3121            b"9E>\xca=b\x1d\xea\x86I\xf6Z\xab@\xb7\xa4p\x98\xf1\xec"
3122        )
3123        assert ext.value.authority_cert_issuer == [
3124            x509.DirectoryName(
3125                x509.Name([
3126                    x509.NameAttribute(
3127                        NameOID.ORGANIZATION_NAME, u"PyCA"
3128                    ),
3129                    x509.NameAttribute(
3130                        NameOID.COMMON_NAME, u"cryptography.io"
3131                    )
3132                ])
3133            )
3134        ]
3135        assert ext.value.authority_cert_serial_number == 3
3136
3137    def test_aki_no_keyid(self, backend):
3138        cert = _load_cert(
3139            os.path.join(
3140                "x509", "custom", "authority_key_identifier_no_keyid.pem"
3141            ),
3142            x509.load_pem_x509_certificate,
3143            backend
3144        )
3145        ext = cert.extensions.get_extension_for_oid(
3146            ExtensionOID.AUTHORITY_KEY_IDENTIFIER
3147        )
3148        assert ext is not None
3149        assert ext.critical is False
3150
3151        assert ext.value.key_identifier is None
3152        assert ext.value.authority_cert_issuer == [
3153            x509.DirectoryName(
3154                x509.Name([
3155                    x509.NameAttribute(
3156                        NameOID.ORGANIZATION_NAME, u"PyCA"
3157                    ),
3158                    x509.NameAttribute(
3159                        NameOID.COMMON_NAME, u"cryptography.io"
3160                    )
3161                ])
3162            )
3163        ]
3164        assert ext.value.authority_cert_serial_number == 3
3165
3166    def test_from_certificate(self, backend):
3167        issuer_cert = _load_cert(
3168            os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
3169            x509.load_pem_x509_certificate,
3170            backend
3171        )
3172        cert = _load_cert(
3173            os.path.join("x509", "cryptography.io.pem"),
3174            x509.load_pem_x509_certificate,
3175            backend
3176        )
3177        ext = cert.extensions.get_extension_for_oid(
3178            ExtensionOID.AUTHORITY_KEY_IDENTIFIER
3179        )
3180        aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(
3181            issuer_cert.public_key()
3182        )
3183        assert ext.value == aki
3184
3185    def test_from_issuer_subject_key_identifier(self, backend):
3186        issuer_cert = _load_cert(
3187            os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
3188            x509.load_pem_x509_certificate,
3189            backend
3190        )
3191        cert = _load_cert(
3192            os.path.join("x509", "cryptography.io.pem"),
3193            x509.load_pem_x509_certificate,
3194            backend
3195        )
3196        ext = cert.extensions.get_extension_for_oid(
3197            ExtensionOID.AUTHORITY_KEY_IDENTIFIER
3198        )
3199        ski = issuer_cert.extensions.get_extension_for_class(
3200            x509.SubjectKeyIdentifier
3201        )
3202        aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
3203            ski
3204        )
3205        assert ext.value == aki
3206
3207
3208class TestNameConstraints(object):
3209    def test_ipaddress_wrong_type(self):
3210        with pytest.raises(TypeError):
3211            x509.NameConstraints(
3212                permitted_subtrees=[
3213                    x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
3214                ],
3215                excluded_subtrees=None
3216            )
3217
3218        with pytest.raises(TypeError):
3219            x509.NameConstraints(
3220                permitted_subtrees=None,
3221                excluded_subtrees=[
3222                    x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1"))
3223                ]
3224            )
3225
3226    def test_ipaddress_allowed_type(self):
3227        permitted = [x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/29"))]
3228        excluded = [x509.IPAddress(ipaddress.IPv4Network(u"10.10.0.0/24"))]
3229        nc = x509.NameConstraints(
3230            permitted_subtrees=permitted,
3231            excluded_subtrees=excluded
3232        )
3233        assert nc.permitted_subtrees == permitted
3234        assert nc.excluded_subtrees == excluded
3235
3236    def test_invalid_permitted_subtrees(self):
3237        with pytest.raises(TypeError):
3238            x509.NameConstraints("badpermitted", None)
3239
3240    def test_invalid_excluded_subtrees(self):
3241        with pytest.raises(TypeError):
3242            x509.NameConstraints(None, "badexcluded")
3243
3244    def test_no_subtrees(self):
3245        with pytest.raises(ValueError):
3246            x509.NameConstraints(None, None)
3247
3248    def test_permitted_none(self):
3249        excluded = [x509.DNSName(u"name.local")]
3250        nc = x509.NameConstraints(
3251            permitted_subtrees=None, excluded_subtrees=excluded
3252        )
3253        assert nc.permitted_subtrees is None
3254        assert nc.excluded_subtrees is not None
3255
3256    def test_excluded_none(self):
3257        permitted = [x509.DNSName(u"name.local")]
3258        nc = x509.NameConstraints(
3259            permitted_subtrees=permitted, excluded_subtrees=None
3260        )
3261        assert nc.permitted_subtrees is not None
3262        assert nc.excluded_subtrees is None
3263
3264    def test_iter_input(self):
3265        subtrees = [x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24"))]
3266        nc = x509.NameConstraints(iter(subtrees), iter(subtrees))
3267        assert list(nc.permitted_subtrees) == subtrees
3268        assert list(nc.excluded_subtrees) == subtrees
3269
3270    def test_repr(self):
3271        permitted = [x509.DNSName(u"name.local"), x509.DNSName(u"name2.local")]
3272        nc = x509.NameConstraints(
3273            permitted_subtrees=permitted,
3274            excluded_subtrees=None
3275        )
3276        if not six.PY2:
3277            assert repr(nc) == (
3278                "<NameConstraints(permitted_subtrees=[<DNSName("
3279                "value='name.local')>, <DNSName(value="
3280                "'name2.local')>], excluded_subtrees=None)>"
3281            )
3282        else:
3283            assert repr(nc) == (
3284                "<NameConstraints(permitted_subtrees=[<DNSName("
3285                "value=u'name.local')>, <DNSName(value="
3286                "u'name2.local')>], excluded_subtrees=None)>"
3287            )
3288
3289    def test_eq(self):
3290        nc = x509.NameConstraints(
3291            permitted_subtrees=[x509.DNSName(u"name.local")],
3292            excluded_subtrees=[x509.DNSName(u"name2.local")]
3293        )
3294        nc2 = x509.NameConstraints(
3295            permitted_subtrees=[x509.DNSName(u"name.local")],
3296            excluded_subtrees=[x509.DNSName(u"name2.local")]
3297        )
3298        assert nc == nc2
3299
3300    def test_ne(self):
3301        nc = x509.NameConstraints(
3302            permitted_subtrees=[x509.DNSName(u"name.local")],
3303            excluded_subtrees=[x509.DNSName(u"name2.local")]
3304        )
3305        nc2 = x509.NameConstraints(
3306            permitted_subtrees=[x509.DNSName(u"name.local")],
3307            excluded_subtrees=None
3308        )
3309        nc3 = x509.NameConstraints(
3310            permitted_subtrees=None,
3311            excluded_subtrees=[x509.DNSName(u"name2.local")]
3312        )
3313
3314        assert nc != nc2
3315        assert nc != nc3
3316        assert nc != object()
3317
3318    def test_hash(self):
3319        nc = x509.NameConstraints(
3320            permitted_subtrees=[x509.DNSName(u"name.local")],
3321            excluded_subtrees=[x509.DNSName(u"name2.local")]
3322        )
3323        nc2 = x509.NameConstraints(
3324            permitted_subtrees=[x509.DNSName(u"name.local")],
3325            excluded_subtrees=[x509.DNSName(u"name2.local")]
3326        )
3327        nc3 = x509.NameConstraints(
3328            permitted_subtrees=[x509.DNSName(u"name.local")],
3329            excluded_subtrees=None
3330        )
3331        nc4 = x509.NameConstraints(
3332            permitted_subtrees=None,
3333            excluded_subtrees=[x509.DNSName(u"name.local")]
3334        )
3335        assert hash(nc) == hash(nc2)
3336        assert hash(nc) != hash(nc3)
3337        assert hash(nc3) != hash(nc4)
3338
3339
3340@pytest.mark.requires_backend_interface(interface=RSABackend)
3341@pytest.mark.requires_backend_interface(interface=X509Backend)
3342class TestNameConstraintsExtension(object):
3343    def test_permitted_excluded(self, backend):
3344        cert = _load_cert(
3345            os.path.join(
3346                "x509", "custom", "nc_permitted_excluded_2.pem"
3347            ),
3348            x509.load_pem_x509_certificate,
3349            backend
3350        )
3351        nc = cert.extensions.get_extension_for_oid(
3352            ExtensionOID.NAME_CONSTRAINTS
3353        ).value
3354        assert nc == x509.NameConstraints(
3355            permitted_subtrees=[
3356                x509.DNSName(u"zombo.local"),
3357            ],
3358            excluded_subtrees=[
3359                x509.DirectoryName(x509.Name([
3360                    x509.NameAttribute(NameOID.COMMON_NAME, u"zombo")
3361                ]))
3362            ]
3363        )
3364
3365    def test_permitted(self, backend):
3366        cert = _load_cert(
3367            os.path.join(
3368                "x509", "custom", "nc_permitted_2.pem"
3369            ),
3370            x509.load_pem_x509_certificate,
3371            backend
3372        )
3373        nc = cert.extensions.get_extension_for_oid(
3374            ExtensionOID.NAME_CONSTRAINTS
3375        ).value
3376        assert nc == x509.NameConstraints(
3377            permitted_subtrees=[
3378                x509.DNSName(u"zombo.local"),
3379            ],
3380            excluded_subtrees=None
3381        )
3382
3383    def test_permitted_with_leading_period(self, backend):
3384        cert = _load_cert(
3385            os.path.join(
3386                "x509", "custom", "nc_permitted.pem"
3387            ),
3388            x509.load_pem_x509_certificate,
3389            backend
3390        )
3391        nc = cert.extensions.get_extension_for_oid(
3392            ExtensionOID.NAME_CONSTRAINTS
3393        ).value
3394        assert nc == x509.NameConstraints(
3395            permitted_subtrees=[
3396                x509.DNSName(u".cryptography.io"),
3397                x509.UniformResourceIdentifier(u"ftp://cryptography.test")
3398            ],
3399            excluded_subtrees=None
3400        )
3401
3402    def test_excluded_with_leading_period(self, backend):
3403        cert = _load_cert(
3404            os.path.join(
3405                "x509", "custom", "nc_excluded.pem"
3406            ),
3407            x509.load_pem_x509_certificate,
3408            backend
3409        )
3410        nc = cert.extensions.get_extension_for_oid(
3411            ExtensionOID.NAME_CONSTRAINTS
3412        ).value
3413        assert nc == x509.NameConstraints(
3414            permitted_subtrees=None,
3415            excluded_subtrees=[
3416                x509.DNSName(u".cryptography.io"),
3417                x509.UniformResourceIdentifier(u"gopher://cryptography.test")
3418            ]
3419        )
3420
3421    def test_permitted_excluded_with_ips(self, backend):
3422        cert = _load_cert(
3423            os.path.join(
3424                "x509", "custom", "nc_permitted_excluded.pem"
3425            ),
3426            x509.load_pem_x509_certificate,
3427            backend
3428        )
3429        nc = cert.extensions.get_extension_for_oid(
3430            ExtensionOID.NAME_CONSTRAINTS
3431        ).value
3432        assert nc == x509.NameConstraints(
3433            permitted_subtrees=[
3434                x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")),
3435                x509.IPAddress(ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/96")),
3436            ],
3437            excluded_subtrees=[
3438                x509.DNSName(u".domain.com"),
3439                x509.UniformResourceIdentifier(u"http://test.local"),
3440            ]
3441        )
3442
3443    def test_single_ip_netmask(self, backend):
3444        cert = _load_cert(
3445            os.path.join(
3446                "x509", "custom", "nc_single_ip_netmask.pem"
3447            ),
3448            x509.load_pem_x509_certificate,
3449            backend
3450        )
3451        nc = cert.extensions.get_extension_for_oid(
3452            ExtensionOID.NAME_CONSTRAINTS
3453        ).value
3454        assert nc == x509.NameConstraints(
3455            permitted_subtrees=[
3456                x509.IPAddress(ipaddress.IPv6Network(u"FF:0:0:0:0:0:0:0/128")),
3457                x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.1/32")),
3458            ],
3459            excluded_subtrees=None
3460        )
3461
3462    def test_invalid_netmask(self, backend):
3463        cert = _load_cert(
3464            os.path.join(
3465                "x509", "custom", "nc_invalid_ip_netmask.pem"
3466            ),
3467            x509.load_pem_x509_certificate,
3468            backend
3469        )
3470        with pytest.raises(ValueError):
3471            cert.extensions.get_extension_for_oid(
3472                ExtensionOID.NAME_CONSTRAINTS
3473            )
3474
3475    def test_certbuilder(self, backend):
3476        permitted = [u'.example.org', u'.xn--4ca7aey.example.com',
3477                     u'foobar.example.net']
3478        private_key = RSA_KEY_2048.private_key(backend)
3479        builder = _make_certbuilder(private_key)
3480        builder = builder.add_extension(
3481            NameConstraints(permitted_subtrees=list(map(DNSName, permitted)),
3482                            excluded_subtrees=[]), True)
3483
3484        cert = builder.sign(private_key, hashes.SHA1(), backend)
3485        result = [
3486            x.value
3487            for x in cert.extensions.get_extension_for_class(
3488                NameConstraints
3489            ).value.permitted_subtrees
3490        ]
3491        assert result == permitted
3492
3493
3494class TestDistributionPoint(object):
3495    def test_distribution_point_full_name_not_general_names(self):
3496        with pytest.raises(TypeError):
3497            x509.DistributionPoint(["notgn"], None, None, None)
3498
3499    def test_distribution_point_relative_name_not_name(self):
3500        with pytest.raises(TypeError):
3501            x509.DistributionPoint(None, "notname", None, None)
3502
3503    def test_distribution_point_full_and_relative_not_none(self):
3504        with pytest.raises(ValueError):
3505            x509.DistributionPoint("data", "notname", None, None)
3506
3507    def test_crl_issuer_not_general_names(self):
3508        with pytest.raises(TypeError):
3509            x509.DistributionPoint(None, None, None, ["notgn"])
3510
3511    def test_reason_not_reasonflags(self):
3512        with pytest.raises(TypeError):
3513            x509.DistributionPoint(
3514                [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3515                None,
3516                frozenset(["notreasonflags"]),
3517                None
3518            )
3519
3520    def test_reason_not_frozenset(self):
3521        with pytest.raises(TypeError):
3522            x509.DistributionPoint(
3523                [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3524                None,
3525                [x509.ReasonFlags.ca_compromise],
3526                None
3527            )
3528
3529    def test_disallowed_reasons(self):
3530        with pytest.raises(ValueError):
3531            x509.DistributionPoint(
3532                [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3533                None,
3534                frozenset([x509.ReasonFlags.unspecified]),
3535                None
3536            )
3537
3538        with pytest.raises(ValueError):
3539            x509.DistributionPoint(
3540                [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3541                None,
3542                frozenset([x509.ReasonFlags.remove_from_crl]),
3543                None
3544            )
3545
3546    def test_reason_only(self):
3547        with pytest.raises(ValueError):
3548            x509.DistributionPoint(
3549                None,
3550                None,
3551                frozenset([x509.ReasonFlags.aa_compromise]),
3552                None
3553            )
3554
3555    def test_eq(self):
3556        dp = x509.DistributionPoint(
3557            [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3558            None,
3559            frozenset([x509.ReasonFlags.superseded]),
3560            [
3561                x509.DirectoryName(
3562                    x509.Name([
3563                        x509.NameAttribute(
3564                            NameOID.COMMON_NAME, u"Important CA"
3565                        )
3566                    ])
3567                )
3568            ],
3569        )
3570        dp2 = x509.DistributionPoint(
3571            [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3572            None,
3573            frozenset([x509.ReasonFlags.superseded]),
3574            [
3575                x509.DirectoryName(
3576                    x509.Name([
3577                        x509.NameAttribute(
3578                            NameOID.COMMON_NAME, u"Important CA"
3579                        )
3580                    ])
3581                )
3582            ],
3583        )
3584        assert dp == dp2
3585
3586    def test_ne(self):
3587        dp = x509.DistributionPoint(
3588            [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3589            None,
3590            frozenset([x509.ReasonFlags.superseded]),
3591            [
3592                x509.DirectoryName(
3593                    x509.Name([
3594                        x509.NameAttribute(
3595                            NameOID.COMMON_NAME, u"Important CA"
3596                        )
3597                    ])
3598                )
3599            ],
3600        )
3601        dp2 = x509.DistributionPoint(
3602            [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3603            None,
3604            None,
3605            None
3606        )
3607        assert dp != dp2
3608        assert dp != object()
3609
3610    def test_iter_input(self):
3611        name = [x509.UniformResourceIdentifier(u"http://crypt.og/crl")]
3612        issuer = [
3613            x509.DirectoryName(
3614                x509.Name([
3615                    x509.NameAttribute(NameOID.COMMON_NAME, u"Important CA")
3616                ])
3617            )
3618        ]
3619        dp = x509.DistributionPoint(
3620            iter(name),
3621            None,
3622            frozenset([x509.ReasonFlags.ca_compromise]),
3623            iter(issuer),
3624        )
3625        assert list(dp.full_name) == name
3626        assert list(dp.crl_issuer) == issuer
3627
3628    def test_repr(self):
3629        dp = x509.DistributionPoint(
3630            None,
3631            x509.RelativeDistinguishedName([
3632                x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
3633            ]),
3634            frozenset([x509.ReasonFlags.ca_compromise]),
3635            [
3636                x509.DirectoryName(
3637                    x509.Name([
3638                        x509.NameAttribute(
3639                            NameOID.COMMON_NAME, u"Important CA"
3640                        )
3641                    ])
3642                )
3643            ],
3644        )
3645        if not six.PY2:
3646            assert repr(dp) == (
3647                "<DistributionPoint(full_name=None, relative_name=<RelativeDis"
3648                "tinguishedName(CN=myCN)>, reasons=frozenset({<ReasonFlags.ca_"
3649                "compromise: 'cACompromise'>}), crl_issuer=[<DirectoryName(val"
3650                "ue=<Name(CN=Important CA)>)>])>"
3651            )
3652        else:
3653            assert repr(dp) == (
3654                "<DistributionPoint(full_name=None, relative_name=<RelativeDis"
3655                "tinguishedName(CN=myCN)>, reasons=frozenset([<ReasonFlags.ca_"
3656                "compromise: 'cACompromise'>]), crl_issuer=[<DirectoryName(val"
3657                "ue=<Name(CN=Important CA)>)>])>"
3658            )
3659
3660    def test_hash(self):
3661        dp = x509.DistributionPoint(
3662            [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3663            None,
3664            frozenset([x509.ReasonFlags.superseded]),
3665            [
3666                x509.DirectoryName(
3667                    x509.Name([
3668                        x509.NameAttribute(
3669                            NameOID.COMMON_NAME, u"Important CA"
3670                        )
3671                    ])
3672                )
3673            ],
3674        )
3675        dp2 = x509.DistributionPoint(
3676            [x509.UniformResourceIdentifier(u"http://crypt.og/crl")],
3677            None,
3678            frozenset([x509.ReasonFlags.superseded]),
3679            [
3680                x509.DirectoryName(
3681                    x509.Name([
3682                        x509.NameAttribute(
3683                            NameOID.COMMON_NAME, u"Important CA"
3684                        )
3685                    ])
3686                )
3687            ],
3688        )
3689        dp3 = x509.DistributionPoint(
3690            None,
3691            x509.RelativeDistinguishedName([
3692                x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
3693            ]),
3694            None,
3695            None,
3696        )
3697        assert hash(dp) == hash(dp2)
3698        assert hash(dp) != hash(dp3)
3699
3700
3701class TestFreshestCRL(object):
3702    def test_invalid_distribution_points(self):
3703        with pytest.raises(TypeError):
3704            x509.FreshestCRL(["notadistributionpoint"])
3705
3706    def test_iter_len(self):
3707        fcrl = x509.FreshestCRL([
3708            x509.DistributionPoint(
3709                [x509.UniformResourceIdentifier(u"http://domain")],
3710                None, None, None
3711            ),
3712        ])
3713        assert len(fcrl) == 1
3714        assert list(fcrl) == [
3715            x509.DistributionPoint(
3716                [x509.UniformResourceIdentifier(u"http://domain")],
3717                None, None, None
3718            ),
3719        ]
3720
3721    def test_iter_input(self):
3722        points = [
3723            x509.DistributionPoint(
3724                [x509.UniformResourceIdentifier(u"http://domain")],
3725                None, None, None
3726            ),
3727        ]
3728        fcrl = x509.FreshestCRL(iter(points))
3729        assert list(fcrl) == points
3730
3731    def test_repr(self):
3732        fcrl = x509.FreshestCRL([
3733            x509.DistributionPoint(
3734                [x509.UniformResourceIdentifier(u"ftp://domain")],
3735                None,
3736                frozenset([x509.ReasonFlags.key_compromise]),
3737                None
3738            ),
3739        ])
3740        if not six.PY2:
3741            assert repr(fcrl) == (
3742                "<FreshestCRL([<DistributionPoint(full_name=[<Unifo"
3743                "rmResourceIdentifier(value='ftp://domain')>], relative"
3744                "_name=None, reasons=frozenset({<ReasonFlags.key_compromise: "
3745                "'keyCompromise'>}), crl_issuer=None)>])>"
3746            )
3747        else:
3748            assert repr(fcrl) == (
3749                "<FreshestCRL([<DistributionPoint(full_name=[<Unifo"
3750                "rmResourceIdentifier(value=u'ftp://domain')>], relative"
3751                "_name=None, reasons=frozenset([<ReasonFlags.key_compromise: "
3752                "'keyCompromise'>]), crl_issuer=None)>])>"
3753            )
3754
3755    def test_eq(self):
3756        fcrl = x509.FreshestCRL([
3757            x509.DistributionPoint(
3758                [x509.UniformResourceIdentifier(u"ftp://domain")],
3759                None,
3760                frozenset([
3761                    x509.ReasonFlags.key_compromise,
3762                    x509.ReasonFlags.ca_compromise,
3763                ]),
3764                [x509.UniformResourceIdentifier(u"uri://thing")],
3765            ),
3766        ])
3767        fcrl2 = x509.FreshestCRL([
3768            x509.DistributionPoint(
3769                [x509.UniformResourceIdentifier(u"ftp://domain")],
3770                None,
3771                frozenset([
3772                    x509.ReasonFlags.key_compromise,
3773                    x509.ReasonFlags.ca_compromise,
3774                ]),
3775                [x509.UniformResourceIdentifier(u"uri://thing")],
3776            ),
3777        ])
3778        assert fcrl == fcrl2
3779
3780    def test_ne(self):
3781        fcrl = x509.FreshestCRL([
3782            x509.DistributionPoint(
3783                [x509.UniformResourceIdentifier(u"ftp://domain")],
3784                None,
3785                frozenset([
3786                    x509.ReasonFlags.key_compromise,
3787                    x509.ReasonFlags.ca_compromise,
3788                ]),
3789                [x509.UniformResourceIdentifier(u"uri://thing")],
3790            ),
3791        ])
3792        fcrl2 = x509.FreshestCRL([
3793            x509.DistributionPoint(
3794                [x509.UniformResourceIdentifier(u"ftp://domain2")],
3795                None,
3796                frozenset([
3797                    x509.ReasonFlags.key_compromise,
3798                    x509.ReasonFlags.ca_compromise,
3799                ]),
3800                [x509.UniformResourceIdentifier(u"uri://thing")],
3801            ),
3802        ])
3803        fcrl3 = x509.FreshestCRL([
3804            x509.DistributionPoint(
3805                [x509.UniformResourceIdentifier(u"ftp://domain")],
3806                None,
3807                frozenset([x509.ReasonFlags.key_compromise]),
3808                [x509.UniformResourceIdentifier(u"uri://thing")],
3809            ),
3810        ])
3811        fcrl4 = x509.FreshestCRL([
3812            x509.DistributionPoint(
3813                [x509.UniformResourceIdentifier(u"ftp://domain")],
3814                None,
3815                frozenset([
3816                    x509.ReasonFlags.key_compromise,
3817                    x509.ReasonFlags.ca_compromise,
3818                ]),
3819                [x509.UniformResourceIdentifier(u"uri://thing2")],
3820            ),
3821        ])
3822        assert fcrl != fcrl2
3823        assert fcrl != fcrl3
3824        assert fcrl != fcrl4
3825        assert fcrl != object()
3826
3827    def test_hash(self):
3828        fcrl = x509.FreshestCRL([
3829            x509.DistributionPoint(
3830                [x509.UniformResourceIdentifier(u"ftp://domain")],
3831                None,
3832                frozenset([
3833                    x509.ReasonFlags.key_compromise,
3834                    x509.ReasonFlags.ca_compromise,
3835                ]),
3836                [x509.UniformResourceIdentifier(u"uri://thing")],
3837            ),
3838        ])
3839        fcrl2 = x509.FreshestCRL([
3840            x509.DistributionPoint(
3841                [x509.UniformResourceIdentifier(u"ftp://domain")],
3842                None,
3843                frozenset([
3844                    x509.ReasonFlags.key_compromise,
3845                    x509.ReasonFlags.ca_compromise,
3846                ]),
3847                [x509.UniformResourceIdentifier(u"uri://thing")],
3848            ),
3849        ])
3850        fcrl3 = x509.FreshestCRL([
3851            x509.DistributionPoint(
3852                [x509.UniformResourceIdentifier(u"ftp://domain")],
3853                None,
3854                frozenset([x509.ReasonFlags.key_compromise]),
3855                [x509.UniformResourceIdentifier(u"uri://thing")],
3856            ),
3857        ])
3858        assert hash(fcrl) == hash(fcrl2)
3859        assert hash(fcrl) != hash(fcrl3)
3860
3861    def test_indexing(self):
3862        fcrl = x509.FreshestCRL([
3863            x509.DistributionPoint(
3864                None, None, None,
3865                [x509.UniformResourceIdentifier(u"uri://thing")],
3866            ),
3867            x509.DistributionPoint(
3868                None, None, None,
3869                [x509.UniformResourceIdentifier(u"uri://thing2")],
3870            ),
3871            x509.DistributionPoint(
3872                None, None, None,
3873                [x509.UniformResourceIdentifier(u"uri://thing3")],
3874            ),
3875            x509.DistributionPoint(
3876                None, None, None,
3877                [x509.UniformResourceIdentifier(u"uri://thing4")],
3878            ),
3879            x509.DistributionPoint(
3880                None, None, None,
3881                [x509.UniformResourceIdentifier(u"uri://thing5")],
3882            ),
3883        ])
3884        assert fcrl[-1] == fcrl[4]
3885        assert fcrl[2:6:2] == [fcrl[2], fcrl[4]]
3886
3887
3888class TestCRLDistributionPoints(object):
3889    def test_invalid_distribution_points(self):
3890        with pytest.raises(TypeError):
3891            x509.CRLDistributionPoints(["notadistributionpoint"])
3892
3893    def test_iter_len(self):
3894        cdp = x509.CRLDistributionPoints([
3895            x509.DistributionPoint(
3896                [x509.UniformResourceIdentifier(u"http://domain")],
3897                None,
3898                None,
3899                None
3900            ),
3901            x509.DistributionPoint(
3902                [x509.UniformResourceIdentifier(u"ftp://domain")],
3903                None,
3904                frozenset([
3905                    x509.ReasonFlags.key_compromise,
3906                    x509.ReasonFlags.ca_compromise,
3907                ]),
3908                None
3909            ),
3910        ])
3911        assert len(cdp) == 2
3912        assert list(cdp) == [
3913            x509.DistributionPoint(
3914                [x509.UniformResourceIdentifier(u"http://domain")],
3915                None,
3916                None,
3917                None
3918            ),
3919            x509.DistributionPoint(
3920                [x509.UniformResourceIdentifier(u"ftp://domain")],
3921                None,
3922                frozenset([
3923                    x509.ReasonFlags.key_compromise,
3924                    x509.ReasonFlags.ca_compromise,
3925                ]),
3926                None
3927            ),
3928        ]
3929
3930    def test_iter_input(self):
3931        points = [
3932            x509.DistributionPoint(
3933                [x509.UniformResourceIdentifier(u"http://domain")],
3934                None,
3935                None,
3936                None
3937            ),
3938        ]
3939        cdp = x509.CRLDistributionPoints(iter(points))
3940        assert list(cdp) == points
3941
3942    def test_repr(self):
3943        cdp = x509.CRLDistributionPoints([
3944            x509.DistributionPoint(
3945                [x509.UniformResourceIdentifier(u"ftp://domain")],
3946                None,
3947                frozenset([x509.ReasonFlags.key_compromise]),
3948                None
3949            ),
3950        ])
3951        if not six.PY2:
3952            assert repr(cdp) == (
3953                "<CRLDistributionPoints([<DistributionPoint(full_name=[<Unifo"
3954                "rmResourceIdentifier(value='ftp://domain')>], relative"
3955                "_name=None, reasons=frozenset({<ReasonFlags.key_compromise: "
3956                "'keyCompromise'>}), crl_issuer=None)>])>"
3957            )
3958        else:
3959            assert repr(cdp) == (
3960                "<CRLDistributionPoints([<DistributionPoint(full_name=[<Unifo"
3961                "rmResourceIdentifier(value=u'ftp://domain')>], relative"
3962                "_name=None, reasons=frozenset([<ReasonFlags.key_compromise: "
3963                "'keyCompromise'>]), crl_issuer=None)>])>"
3964            )
3965
3966    def test_eq(self):
3967        cdp = x509.CRLDistributionPoints([
3968            x509.DistributionPoint(
3969                [x509.UniformResourceIdentifier(u"ftp://domain")],
3970                None,
3971                frozenset([
3972                    x509.ReasonFlags.key_compromise,
3973                    x509.ReasonFlags.ca_compromise,
3974                ]),
3975                [x509.UniformResourceIdentifier(u"uri://thing")],
3976            ),
3977        ])
3978        cdp2 = x509.CRLDistributionPoints([
3979            x509.DistributionPoint(
3980                [x509.UniformResourceIdentifier(u"ftp://domain")],
3981                None,
3982                frozenset([
3983                    x509.ReasonFlags.key_compromise,
3984                    x509.ReasonFlags.ca_compromise,
3985                ]),
3986                [x509.UniformResourceIdentifier(u"uri://thing")],
3987            ),
3988        ])
3989        assert cdp == cdp2
3990
3991    def test_ne(self):
3992        cdp = x509.CRLDistributionPoints([
3993            x509.DistributionPoint(
3994                [x509.UniformResourceIdentifier(u"ftp://domain")],
3995                None,
3996                frozenset([
3997                    x509.ReasonFlags.key_compromise,
3998                    x509.ReasonFlags.ca_compromise,
3999                ]),
4000                [x509.UniformResourceIdentifier(u"uri://thing")],
4001            ),
4002        ])
4003        cdp2 = x509.CRLDistributionPoints([
4004            x509.DistributionPoint(
4005                [x509.UniformResourceIdentifier(u"ftp://domain2")],
4006                None,
4007                frozenset([
4008                    x509.ReasonFlags.key_compromise,
4009                    x509.ReasonFlags.ca_compromise,
4010                ]),
4011                [x509.UniformResourceIdentifier(u"uri://thing")],
4012            ),
4013        ])
4014        cdp3 = x509.CRLDistributionPoints([
4015            x509.DistributionPoint(
4016                [x509.UniformResourceIdentifier(u"ftp://domain")],
4017                None,
4018                frozenset([x509.ReasonFlags.key_compromise]),
4019                [x509.UniformResourceIdentifier(u"uri://thing")],
4020            ),
4021        ])
4022        cdp4 = x509.CRLDistributionPoints([
4023            x509.DistributionPoint(
4024                [x509.UniformResourceIdentifier(u"ftp://domain")],
4025                None,
4026                frozenset([
4027                    x509.ReasonFlags.key_compromise,
4028                    x509.ReasonFlags.ca_compromise,
4029                ]),
4030                [x509.UniformResourceIdentifier(u"uri://thing2")],
4031            ),
4032        ])
4033        assert cdp != cdp2
4034        assert cdp != cdp3
4035        assert cdp != cdp4
4036        assert cdp != object()
4037
4038    def test_hash(self):
4039        cdp = x509.CRLDistributionPoints([
4040            x509.DistributionPoint(
4041                [x509.UniformResourceIdentifier(u"ftp://domain")],
4042                None,
4043                frozenset([
4044                    x509.ReasonFlags.key_compromise,
4045                    x509.ReasonFlags.ca_compromise,
4046                ]),
4047                [x509.UniformResourceIdentifier(u"uri://thing")],
4048            ),
4049        ])
4050        cdp2 = x509.CRLDistributionPoints([
4051            x509.DistributionPoint(
4052                [x509.UniformResourceIdentifier(u"ftp://domain")],
4053                None,
4054                frozenset([
4055                    x509.ReasonFlags.key_compromise,
4056                    x509.ReasonFlags.ca_compromise,
4057                ]),
4058                [x509.UniformResourceIdentifier(u"uri://thing")],
4059            ),
4060        ])
4061        cdp3 = x509.CRLDistributionPoints([
4062            x509.DistributionPoint(
4063                [x509.UniformResourceIdentifier(u"ftp://domain")],
4064                None,
4065                frozenset([x509.ReasonFlags.key_compromise]),
4066                [x509.UniformResourceIdentifier(u"uri://thing")],
4067            ),
4068        ])
4069        assert hash(cdp) == hash(cdp2)
4070        assert hash(cdp) != hash(cdp3)
4071
4072    def test_indexing(self):
4073        ci = x509.CRLDistributionPoints([
4074            x509.DistributionPoint(
4075                None, None, None,
4076                [x509.UniformResourceIdentifier(u"uri://thing")],
4077            ),
4078            x509.DistributionPoint(
4079                None, None, None,
4080                [x509.UniformResourceIdentifier(u"uri://thing2")],
4081            ),
4082            x509.DistributionPoint(
4083                None, None, None,
4084                [x509.UniformResourceIdentifier(u"uri://thing3")],
4085            ),
4086            x509.DistributionPoint(
4087                None, None, None,
4088                [x509.UniformResourceIdentifier(u"uri://thing4")],
4089            ),
4090            x509.DistributionPoint(
4091                None, None, None,
4092                [x509.UniformResourceIdentifier(u"uri://thing5")],
4093            ),
4094        ])
4095        assert ci[-1] == ci[4]
4096        assert ci[2:6:2] == [ci[2], ci[4]]
4097
4098
4099@pytest.mark.requires_backend_interface(interface=RSABackend)
4100@pytest.mark.requires_backend_interface(interface=X509Backend)
4101class TestCRLDistributionPointsExtension(object):
4102    def test_fullname_and_crl_issuer(self, backend):
4103        cert = _load_cert(
4104            os.path.join(
4105                "x509", "PKITS_data", "certs", "ValidcRLIssuerTest28EE.crt"
4106            ),
4107            x509.load_der_x509_certificate,
4108            backend
4109        )
4110
4111        cdps = cert.extensions.get_extension_for_oid(
4112            ExtensionOID.CRL_DISTRIBUTION_POINTS
4113        ).value
4114
4115        assert cdps == x509.CRLDistributionPoints([
4116            x509.DistributionPoint(
4117                full_name=[x509.DirectoryName(
4118                    x509.Name([
4119                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4120                        x509.NameAttribute(
4121                            NameOID.ORGANIZATION_NAME,
4122                            u"Test Certificates 2011"
4123                        ),
4124                        x509.NameAttribute(
4125                            NameOID.ORGANIZATIONAL_UNIT_NAME,
4126                            u"indirectCRL CA3 cRLIssuer"
4127                        ),
4128                        x509.NameAttribute(
4129                            NameOID.COMMON_NAME,
4130                            u"indirect CRL for indirectCRL CA3"
4131                        ),
4132                    ])
4133                )],
4134                relative_name=None,
4135                reasons=None,
4136                crl_issuer=[x509.DirectoryName(
4137                    x509.Name([
4138                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4139                        x509.NameAttribute(
4140                            NameOID.ORGANIZATION_NAME,
4141                            u"Test Certificates 2011"
4142                        ),
4143                        x509.NameAttribute(
4144                            NameOID.ORGANIZATIONAL_UNIT_NAME,
4145                            u"indirectCRL CA3 cRLIssuer"
4146                        ),
4147                    ])
4148                )],
4149            )
4150        ])
4151
4152    def test_relativename_and_crl_issuer(self, backend):
4153        cert = _load_cert(
4154            os.path.join(
4155                "x509", "PKITS_data", "certs", "ValidcRLIssuerTest29EE.crt"
4156            ),
4157            x509.load_der_x509_certificate,
4158            backend
4159        )
4160
4161        cdps = cert.extensions.get_extension_for_oid(
4162            ExtensionOID.CRL_DISTRIBUTION_POINTS
4163        ).value
4164
4165        assert cdps == x509.CRLDistributionPoints([
4166            x509.DistributionPoint(
4167                full_name=None,
4168                relative_name=x509.RelativeDistinguishedName([
4169                    x509.NameAttribute(
4170                        NameOID.COMMON_NAME,
4171                        u"indirect CRL for indirectCRL CA3"
4172                    ),
4173                ]),
4174                reasons=None,
4175                crl_issuer=[x509.DirectoryName(
4176                    x509.Name([
4177                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4178                        x509.NameAttribute(
4179                            NameOID.ORGANIZATION_NAME,
4180                            u"Test Certificates 2011"
4181                        ),
4182                        x509.NameAttribute(
4183                            NameOID.ORGANIZATIONAL_UNIT_NAME,
4184                            u"indirectCRL CA3 cRLIssuer"
4185                        ),
4186                    ])
4187                )],
4188            )
4189        ])
4190
4191    def test_fullname_crl_issuer_reasons(self, backend):
4192        cert = _load_cert(
4193            os.path.join(
4194                "x509", "custom", "cdp_fullname_reasons_crl_issuer.pem"
4195            ),
4196            x509.load_pem_x509_certificate,
4197            backend
4198        )
4199
4200        cdps = cert.extensions.get_extension_for_oid(
4201            ExtensionOID.CRL_DISTRIBUTION_POINTS
4202        ).value
4203
4204        assert cdps == x509.CRLDistributionPoints([
4205            x509.DistributionPoint(
4206                full_name=[x509.UniformResourceIdentifier(
4207                    u"http://myhost.com/myca.crl"
4208                )],
4209                relative_name=None,
4210                reasons=frozenset([
4211                    x509.ReasonFlags.key_compromise,
4212                    x509.ReasonFlags.ca_compromise
4213                ]),
4214                crl_issuer=[x509.DirectoryName(
4215                    x509.Name([
4216                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4217                        x509.NameAttribute(
4218                            NameOID.ORGANIZATION_NAME, u"PyCA"
4219                        ),
4220                        x509.NameAttribute(
4221                            NameOID.COMMON_NAME, u"cryptography CA"
4222                        ),
4223                    ])
4224                )],
4225            )
4226        ])
4227
4228    def test_all_reasons(self, backend):
4229        cert = _load_cert(
4230            os.path.join(
4231                "x509", "custom", "cdp_all_reasons.pem"
4232            ),
4233            x509.load_pem_x509_certificate,
4234            backend
4235        )
4236
4237        cdps = cert.extensions.get_extension_for_oid(
4238            ExtensionOID.CRL_DISTRIBUTION_POINTS
4239        ).value
4240
4241        assert cdps == x509.CRLDistributionPoints([
4242            x509.DistributionPoint(
4243                full_name=[x509.UniformResourceIdentifier(
4244                    u"http://domain.com/some.crl"
4245                )],
4246                relative_name=None,
4247                reasons=frozenset([
4248                    x509.ReasonFlags.key_compromise,
4249                    x509.ReasonFlags.ca_compromise,
4250                    x509.ReasonFlags.affiliation_changed,
4251                    x509.ReasonFlags.superseded,
4252                    x509.ReasonFlags.privilege_withdrawn,
4253                    x509.ReasonFlags.cessation_of_operation,
4254                    x509.ReasonFlags.aa_compromise,
4255                    x509.ReasonFlags.certificate_hold,
4256                ]),
4257                crl_issuer=None
4258            )
4259        ])
4260
4261    def test_single_reason(self, backend):
4262        cert = _load_cert(
4263            os.path.join(
4264                "x509", "custom", "cdp_reason_aa_compromise.pem"
4265            ),
4266            x509.load_pem_x509_certificate,
4267            backend
4268        )
4269
4270        cdps = cert.extensions.get_extension_for_oid(
4271            ExtensionOID.CRL_DISTRIBUTION_POINTS
4272        ).value
4273
4274        assert cdps == x509.CRLDistributionPoints([
4275            x509.DistributionPoint(
4276                full_name=[x509.UniformResourceIdentifier(
4277                    u"http://domain.com/some.crl"
4278                )],
4279                relative_name=None,
4280                reasons=frozenset([x509.ReasonFlags.aa_compromise]),
4281                crl_issuer=None
4282            )
4283        ])
4284
4285    def test_crl_issuer_only(self, backend):
4286        cert = _load_cert(
4287            os.path.join(
4288                "x509", "custom", "cdp_crl_issuer.pem"
4289            ),
4290            x509.load_pem_x509_certificate,
4291            backend
4292        )
4293
4294        cdps = cert.extensions.get_extension_for_oid(
4295            ExtensionOID.CRL_DISTRIBUTION_POINTS
4296        ).value
4297
4298        assert cdps == x509.CRLDistributionPoints([
4299            x509.DistributionPoint(
4300                full_name=None,
4301                relative_name=None,
4302                reasons=None,
4303                crl_issuer=[x509.DirectoryName(
4304                    x509.Name([
4305                        x509.NameAttribute(
4306                            NameOID.COMMON_NAME, u"cryptography CA"
4307                        ),
4308                    ])
4309                )],
4310            )
4311        ])
4312
4313    def test_crl_empty_hostname(self, backend):
4314        cert = _load_cert(
4315            os.path.join(
4316                "x509", "custom", "cdp_empty_hostname.pem"
4317            ),
4318            x509.load_pem_x509_certificate,
4319            backend
4320        )
4321
4322        cdps = cert.extensions.get_extension_for_oid(
4323            ExtensionOID.CRL_DISTRIBUTION_POINTS
4324        ).value
4325
4326        assert cdps == x509.CRLDistributionPoints([
4327            x509.DistributionPoint(
4328                full_name=[x509.UniformResourceIdentifier(
4329                    u"ldap:///CN=A,OU=B,dc=C,DC=D?E?F?G?H=I"
4330                )],
4331                relative_name=None,
4332                reasons=None,
4333                crl_issuer=None
4334            )
4335        ])
4336
4337
4338@pytest.mark.requires_backend_interface(interface=RSABackend)
4339@pytest.mark.requires_backend_interface(interface=X509Backend)
4340class TestFreshestCRLExtension(object):
4341    def test_vector(self, backend):
4342        cert = _load_cert(
4343            os.path.join(
4344                "x509", "custom", "freshestcrl.pem"
4345            ),
4346            x509.load_pem_x509_certificate,
4347            backend
4348        )
4349
4350        fcrl = cert.extensions.get_extension_for_class(x509.FreshestCRL).value
4351        assert fcrl == x509.FreshestCRL([
4352            x509.DistributionPoint(
4353                full_name=[
4354                    x509.UniformResourceIdentifier(
4355                        u'http://myhost.com/myca.crl'
4356                    ),
4357                    x509.UniformResourceIdentifier(
4358                        u'http://backup.myhost.com/myca.crl'
4359                    )
4360                ],
4361                relative_name=None,
4362                reasons=frozenset([
4363                    x509.ReasonFlags.ca_compromise,
4364                    x509.ReasonFlags.key_compromise
4365                ]),
4366                crl_issuer=[x509.DirectoryName(
4367                    x509.Name([
4368                        x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
4369                        x509.NameAttribute(
4370                            NameOID.COMMON_NAME, u"cryptography CA"
4371                        ),
4372                    ])
4373                )]
4374            )
4375        ])
4376
4377
4378@pytest.mark.requires_backend_interface(interface=RSABackend)
4379@pytest.mark.requires_backend_interface(interface=X509Backend)
4380class TestOCSPNoCheckExtension(object):
4381    def test_nocheck(self, backend):
4382        cert = _load_cert(
4383            os.path.join(
4384                "x509", "custom", "ocsp_nocheck.pem"
4385            ),
4386            x509.load_pem_x509_certificate,
4387            backend
4388        )
4389        ext = cert.extensions.get_extension_for_oid(
4390            ExtensionOID.OCSP_NO_CHECK
4391        )
4392        assert isinstance(ext.value, x509.OCSPNoCheck)
4393
4394
4395class TestInhibitAnyPolicy(object):
4396    def test_not_int(self):
4397        with pytest.raises(TypeError):
4398            x509.InhibitAnyPolicy("notint")
4399
4400    def test_negative_int(self):
4401        with pytest.raises(ValueError):
4402            x509.InhibitAnyPolicy(-1)
4403
4404    def test_repr(self):
4405        iap = x509.InhibitAnyPolicy(0)
4406        assert repr(iap) == "<InhibitAnyPolicy(skip_certs=0)>"
4407
4408    def test_eq(self):
4409        iap = x509.InhibitAnyPolicy(1)
4410        iap2 = x509.InhibitAnyPolicy(1)
4411        assert iap == iap2
4412
4413    def test_ne(self):
4414        iap = x509.InhibitAnyPolicy(1)
4415        iap2 = x509.InhibitAnyPolicy(4)
4416        assert iap != iap2
4417        assert iap != object()
4418
4419    def test_hash(self):
4420        iap = x509.InhibitAnyPolicy(1)
4421        iap2 = x509.InhibitAnyPolicy(1)
4422        iap3 = x509.InhibitAnyPolicy(4)
4423        assert hash(iap) == hash(iap2)
4424        assert hash(iap) != hash(iap3)
4425
4426
4427@pytest.mark.requires_backend_interface(interface=RSABackend)
4428@pytest.mark.requires_backend_interface(interface=X509Backend)
4429class TestInhibitAnyPolicyExtension(object):
4430    def test_inhibit_any_policy(self, backend):
4431        cert = _load_cert(
4432            os.path.join(
4433                "x509", "custom", "inhibit_any_policy_5.pem"
4434            ),
4435            x509.load_pem_x509_certificate,
4436            backend
4437        )
4438        iap = cert.extensions.get_extension_for_oid(
4439            ExtensionOID.INHIBIT_ANY_POLICY
4440        ).value
4441        assert iap.skip_certs == 5
4442
4443
4444class TestIssuingDistributionPointExtension(object):
4445    @pytest.mark.parametrize(
4446        ("filename", "expected"),
4447        [
4448            (
4449                "crl_idp_fullname_indirect_crl.pem",
4450                x509.IssuingDistributionPoint(
4451                    full_name=[
4452                        x509.UniformResourceIdentifier(
4453                            u"http://myhost.com/myca.crl")
4454                    ],
4455                    relative_name=None,
4456                    only_contains_user_certs=False,
4457                    only_contains_ca_certs=False,
4458                    only_some_reasons=None,
4459                    indirect_crl=True,
4460                    only_contains_attribute_certs=False,
4461                )
4462            ),
4463            (
4464                "crl_idp_fullname_only.pem",
4465                x509.IssuingDistributionPoint(
4466                    full_name=[
4467                        x509.UniformResourceIdentifier(
4468                            u"http://myhost.com/myca.crl")
4469                    ],
4470                    relative_name=None,
4471                    only_contains_user_certs=False,
4472                    only_contains_ca_certs=False,
4473                    only_some_reasons=None,
4474                    indirect_crl=False,
4475                    only_contains_attribute_certs=False,
4476                )
4477            ),
4478            (
4479                "crl_idp_fullname_only_aa.pem",
4480                x509.IssuingDistributionPoint(
4481                    full_name=[
4482                        x509.UniformResourceIdentifier(
4483                            u"http://myhost.com/myca.crl")
4484                    ],
4485                    relative_name=None,
4486                    only_contains_user_certs=False,
4487                    only_contains_ca_certs=False,
4488                    only_some_reasons=None,
4489                    indirect_crl=False,
4490                    only_contains_attribute_certs=True,
4491                )
4492            ),
4493            (
4494                "crl_idp_fullname_only_user.pem",
4495                x509.IssuingDistributionPoint(
4496                    full_name=[
4497                        x509.UniformResourceIdentifier(
4498                            u"http://myhost.com/myca.crl")
4499                    ],
4500                    relative_name=None,
4501                    only_contains_user_certs=True,
4502                    only_contains_ca_certs=False,
4503                    only_some_reasons=None,
4504                    indirect_crl=False,
4505                    only_contains_attribute_certs=False,
4506                )
4507            ),
4508            (
4509                "crl_idp_only_ca.pem",
4510                x509.IssuingDistributionPoint(
4511                    full_name=None,
4512                    relative_name=x509.RelativeDistinguishedName([
4513                        x509.NameAttribute(
4514                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
4515                        )
4516                    ]),
4517                    only_contains_user_certs=False,
4518                    only_contains_ca_certs=True,
4519                    only_some_reasons=None,
4520                    indirect_crl=False,
4521                    only_contains_attribute_certs=False,
4522                )
4523            ),
4524            (
4525                "crl_idp_reasons_only.pem",
4526                x509.IssuingDistributionPoint(
4527                    full_name=None,
4528                    relative_name=None,
4529                    only_contains_user_certs=False,
4530                    only_contains_ca_certs=False,
4531                    only_some_reasons=frozenset([
4532                        x509.ReasonFlags.key_compromise
4533                    ]),
4534                    indirect_crl=False,
4535                    only_contains_attribute_certs=False,
4536                )
4537            ),
4538            (
4539                "crl_idp_relative_user_all_reasons.pem",
4540                x509.IssuingDistributionPoint(
4541                    full_name=None,
4542                    relative_name=x509.RelativeDistinguishedName([
4543                        x509.NameAttribute(
4544                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
4545                        )
4546                    ]),
4547                    only_contains_user_certs=True,
4548                    only_contains_ca_certs=False,
4549                    only_some_reasons=frozenset([
4550                        x509.ReasonFlags.key_compromise,
4551                        x509.ReasonFlags.ca_compromise,
4552                        x509.ReasonFlags.affiliation_changed,
4553                        x509.ReasonFlags.superseded,
4554                        x509.ReasonFlags.cessation_of_operation,
4555                        x509.ReasonFlags.certificate_hold,
4556                        x509.ReasonFlags.privilege_withdrawn,
4557                        x509.ReasonFlags.aa_compromise,
4558                    ]),
4559                    indirect_crl=False,
4560                    only_contains_attribute_certs=False,
4561                )
4562            ),
4563            (
4564                "crl_idp_relativename_only.pem",
4565                x509.IssuingDistributionPoint(
4566                    full_name=None,
4567                    relative_name=x509.RelativeDistinguishedName([
4568                        x509.NameAttribute(
4569                            oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
4570                        )
4571                    ]),
4572                    only_contains_user_certs=False,
4573                    only_contains_ca_certs=False,
4574                    only_some_reasons=None,
4575                    indirect_crl=False,
4576                    only_contains_attribute_certs=False,
4577                )
4578            ),
4579        ]
4580    )
4581    @pytest.mark.requires_backend_interface(interface=RSABackend)
4582    @pytest.mark.requires_backend_interface(interface=X509Backend)
4583    def test_vectors(self, filename, expected, backend):
4584        crl = _load_cert(
4585            os.path.join("x509", "custom", filename),
4586            x509.load_pem_x509_crl, backend
4587        )
4588        idp = crl.extensions.get_extension_for_class(
4589            x509.IssuingDistributionPoint
4590        ).value
4591        assert idp == expected
4592
4593    @pytest.mark.parametrize(
4594        (
4595            "error", "only_contains_user_certs", "only_contains_ca_certs",
4596            "indirect_crl", "only_contains_attribute_certs",
4597            "only_some_reasons", "full_name", "relative_name"
4598        ),
4599        [
4600            (
4601                TypeError, False, False, False, False, 'notafrozenset', None,
4602                None
4603            ),
4604            (
4605                TypeError, False, False, False, False, frozenset(['bad']),
4606                None, None
4607            ),
4608            (
4609                ValueError, False, False, False, False,
4610                frozenset([x509.ReasonFlags.unspecified]), None, None
4611            ),
4612            (
4613                ValueError, False, False, False, False,
4614                frozenset([x509.ReasonFlags.remove_from_crl]), None, None
4615            ),
4616            (TypeError, 'notabool', False, False, False, None, None, None),
4617            (TypeError, False, 'notabool', False, False, None, None, None),
4618            (TypeError, False, False, 'notabool', False, None, None, None),
4619            (TypeError, False, False, False, 'notabool', None, None, None),
4620            (ValueError, True, True, False, False, None, None, None),
4621            (ValueError, False, False, True, True, None, None, None),
4622            (ValueError, False, False, False, False, None, None, None),
4623        ]
4624    )
4625    def test_invalid_init(self, error, only_contains_user_certs,
4626                          only_contains_ca_certs, indirect_crl,
4627                          only_contains_attribute_certs, only_some_reasons,
4628                          full_name, relative_name):
4629        with pytest.raises(error):
4630            x509.IssuingDistributionPoint(
4631                full_name, relative_name, only_contains_user_certs,
4632                only_contains_ca_certs, only_some_reasons, indirect_crl,
4633                only_contains_attribute_certs
4634            )
4635
4636    def test_repr(self):
4637        idp = x509.IssuingDistributionPoint(
4638            None, None, False, False,
4639            frozenset([x509.ReasonFlags.key_compromise]), False, False
4640        )
4641        if not six.PY2:
4642            assert repr(idp) == (
4643                "<IssuingDistributionPoint(full_name=None, relative_name=None,"
4644                " only_contains_user_certs=False, only_contains_ca_certs=False"
4645                ", only_some_reasons=frozenset({<ReasonFlags.key_compromise: '"
4646                "keyCompromise'>}), indirect_crl=False, only_contains_attribut"
4647                "e_certs=False)>"
4648            )
4649        else:
4650            assert repr(idp) == (
4651                "<IssuingDistributionPoint(full_name=None, relative_name=None,"
4652                " only_contains_user_certs=False, only_contains_ca_certs=False"
4653                ", only_some_reasons=frozenset([<ReasonFlags.key_compromise: '"
4654                "keyCompromise'>]), indirect_crl=False, only_contains_attribut"
4655                "e_certs=False)>"
4656            )
4657
4658    def test_eq(self):
4659        idp1 = x509.IssuingDistributionPoint(
4660            only_contains_user_certs=False,
4661            only_contains_ca_certs=False,
4662            indirect_crl=False,
4663            only_contains_attribute_certs=False,
4664            only_some_reasons=None,
4665            full_name=None,
4666            relative_name=x509.RelativeDistinguishedName([
4667                x509.NameAttribute(
4668                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
4669            ])
4670        )
4671        idp2 = x509.IssuingDistributionPoint(
4672            only_contains_user_certs=False,
4673            only_contains_ca_certs=False,
4674            indirect_crl=False,
4675            only_contains_attribute_certs=False,
4676            only_some_reasons=None,
4677            full_name=None,
4678            relative_name=x509.RelativeDistinguishedName([
4679                x509.NameAttribute(
4680                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
4681            ])
4682        )
4683        assert idp1 == idp2
4684
4685    def test_ne(self):
4686        idp1 = x509.IssuingDistributionPoint(
4687            only_contains_user_certs=False,
4688            only_contains_ca_certs=False,
4689            indirect_crl=False,
4690            only_contains_attribute_certs=False,
4691            only_some_reasons=None,
4692            full_name=None,
4693            relative_name=x509.RelativeDistinguishedName([
4694                x509.NameAttribute(
4695                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
4696            ])
4697        )
4698        idp2 = x509.IssuingDistributionPoint(
4699            only_contains_user_certs=True,
4700            only_contains_ca_certs=False,
4701            indirect_crl=False,
4702            only_contains_attribute_certs=False,
4703            only_some_reasons=None,
4704            full_name=None,
4705            relative_name=x509.RelativeDistinguishedName([
4706                x509.NameAttribute(
4707                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
4708            ])
4709        )
4710        assert idp1 != idp2
4711        assert idp1 != object()
4712
4713    def test_hash(self):
4714        idp1 = x509.IssuingDistributionPoint(
4715            None, None, True, False, None, False, False
4716        )
4717        idp2 = x509.IssuingDistributionPoint(
4718            None, None, True, False, None, False, False
4719        )
4720        idp3 = x509.IssuingDistributionPoint(
4721            None,
4722            x509.RelativeDistinguishedName([
4723                x509.NameAttribute(
4724                    oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA")
4725            ]),
4726            True, False, None, False, False
4727        )
4728        assert hash(idp1) == hash(idp2)
4729        assert hash(idp1) != hash(idp3)
4730
4731    @pytest.mark.requires_backend_interface(interface=RSABackend)
4732    @pytest.mark.requires_backend_interface(interface=X509Backend)
4733    @pytest.mark.parametrize(
4734        "idp",
4735        [
4736            x509.IssuingDistributionPoint(
4737                full_name=[
4738                    x509.UniformResourceIdentifier(
4739                        u"http://myhost.com/myca.crl"
4740                    )
4741                ],
4742                relative_name=None,
4743                only_contains_user_certs=False,
4744                only_contains_ca_certs=False,
4745                only_some_reasons=None,
4746                indirect_crl=True,
4747                only_contains_attribute_certs=False,
4748            ),
4749            x509.IssuingDistributionPoint(
4750                full_name=[
4751                    x509.UniformResourceIdentifier(
4752                        u"http://myhost.com/myca.crl"
4753                    )
4754                ],
4755                relative_name=None,
4756                only_contains_user_certs=False,
4757                only_contains_ca_certs=False,
4758                only_some_reasons=None,
4759                indirect_crl=False,
4760                only_contains_attribute_certs=False,
4761            ),
4762            x509.IssuingDistributionPoint(
4763                full_name=[
4764                    x509.UniformResourceIdentifier(
4765                        u"http://myhost.com/myca.crl"
4766                    )
4767                ],
4768                relative_name=None,
4769                only_contains_user_certs=False,
4770                only_contains_ca_certs=False,
4771                only_some_reasons=None,
4772                indirect_crl=False,
4773                only_contains_attribute_certs=True,
4774            ),
4775            x509.IssuingDistributionPoint(
4776                full_name=[
4777                    x509.UniformResourceIdentifier(
4778                        u"http://myhost.com/myca.crl"
4779                    )
4780                ],
4781                relative_name=None,
4782                only_contains_user_certs=True,
4783                only_contains_ca_certs=False,
4784                only_some_reasons=None,
4785                indirect_crl=False,
4786                only_contains_attribute_certs=False,
4787            ),
4788            x509.IssuingDistributionPoint(
4789                full_name=None,
4790                relative_name=x509.RelativeDistinguishedName([
4791                    x509.NameAttribute(
4792                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
4793                    )
4794                ]),
4795                only_contains_user_certs=False,
4796                only_contains_ca_certs=True,
4797                only_some_reasons=None,
4798                indirect_crl=False,
4799                only_contains_attribute_certs=False,
4800            ),
4801            x509.IssuingDistributionPoint(
4802                full_name=None,
4803                relative_name=None,
4804                only_contains_user_certs=False,
4805                only_contains_ca_certs=True,
4806                only_some_reasons=frozenset([x509.ReasonFlags.key_compromise]),
4807                indirect_crl=False,
4808                only_contains_attribute_certs=False,
4809            ),
4810            x509.IssuingDistributionPoint(
4811                full_name=None,
4812                relative_name=x509.RelativeDistinguishedName([
4813                    x509.NameAttribute(
4814                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"),
4815                    x509.NameAttribute(
4816                        oid=x509.NameOID.COMMON_NAME, value=u"cryptography")
4817                ]),
4818                only_contains_user_certs=True,
4819                only_contains_ca_certs=False,
4820                only_some_reasons=frozenset([
4821                    x509.ReasonFlags.key_compromise,
4822                    x509.ReasonFlags.ca_compromise,
4823                    x509.ReasonFlags.affiliation_changed,
4824                    x509.ReasonFlags.privilege_withdrawn,
4825                    x509.ReasonFlags.aa_compromise,
4826                ]),
4827                indirect_crl=False,
4828                only_contains_attribute_certs=False,
4829            ),
4830            x509.IssuingDistributionPoint(
4831                full_name=None,
4832                relative_name=x509.RelativeDistinguishedName([
4833                    x509.NameAttribute(
4834                        oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"
4835                    )
4836                ]),
4837                only_contains_user_certs=False,
4838                only_contains_ca_certs=False,
4839                only_some_reasons=None,
4840                indirect_crl=False,
4841                only_contains_attribute_certs=False,
4842            ),
4843        ]
4844    )
4845    def test_generate(self, idp, backend):
4846        key = RSA_KEY_2048.private_key(backend)
4847        last_update = datetime.datetime(2002, 1, 1, 12, 1)
4848        next_update = datetime.datetime(2030, 1, 1, 12, 1)
4849        builder = x509.CertificateRevocationListBuilder().issuer_name(
4850            x509.Name([
4851                x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
4852            ])
4853        ).last_update(
4854            last_update
4855        ).next_update(
4856            next_update
4857        ).add_extension(
4858            idp, True
4859        )
4860
4861        crl = builder.sign(key, hashes.SHA256(), backend)
4862        ext = crl.extensions.get_extension_for_class(
4863            x509.IssuingDistributionPoint
4864        )
4865        assert ext.critical is True
4866        assert ext.value == idp
4867
4868
4869@pytest.mark.requires_backend_interface(interface=RSABackend)
4870@pytest.mark.requires_backend_interface(interface=X509Backend)
4871class TestPrecertPoisonExtension(object):
4872    def test_load(self, backend):
4873        cert = _load_cert(
4874            os.path.join("x509", "cryptography.io.precert.pem"),
4875            x509.load_pem_x509_certificate,
4876            backend
4877        )
4878        poison = cert.extensions.get_extension_for_oid(
4879            ExtensionOID.PRECERT_POISON
4880        ).value
4881        assert isinstance(poison, x509.PrecertPoison)
4882        poison = cert.extensions.get_extension_for_class(
4883            x509.PrecertPoison
4884        ).value
4885        assert isinstance(poison, x509.PrecertPoison)
4886
4887    def test_generate(self, backend):
4888        private_key = RSA_KEY_2048.private_key(backend)
4889        cert = _make_certbuilder(private_key).add_extension(
4890            x509.PrecertPoison(), critical=True
4891        ).sign(private_key, hashes.SHA256(), backend)
4892        poison = cert.extensions.get_extension_for_oid(
4893            ExtensionOID.PRECERT_POISON
4894        ).value
4895        assert isinstance(poison, x509.PrecertPoison)
4896
4897
4898@pytest.mark.requires_backend_interface(interface=RSABackend)
4899@pytest.mark.requires_backend_interface(interface=X509Backend)
4900class TestSignedCertificateTimestamps(object):
4901    @pytest.mark.supported(
4902        only_if=lambda backend: (
4903            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
4904        skip_message="Requires OpenSSL 1.1.0f+",
4905    )
4906    def test_eq(self, backend):
4907        sct = _load_cert(
4908            os.path.join("x509", "badssl-sct.pem"),
4909            x509.load_pem_x509_certificate,
4910            backend
4911        ).extensions.get_extension_for_class(
4912            x509.PrecertificateSignedCertificateTimestamps
4913        ).value[0]
4914        sct2 = _load_cert(
4915            os.path.join("x509", "badssl-sct.pem"),
4916            x509.load_pem_x509_certificate,
4917            backend
4918        ).extensions.get_extension_for_class(
4919            x509.PrecertificateSignedCertificateTimestamps
4920        ).value[0]
4921        assert sct == sct2
4922
4923    @pytest.mark.supported(
4924        only_if=lambda backend: (
4925            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
4926        skip_message="Requires OpenSSL 1.1.0f+",
4927    )
4928    def test_ne(self, backend):
4929        sct = _load_cert(
4930            os.path.join("x509", "badssl-sct.pem"),
4931            x509.load_pem_x509_certificate,
4932            backend
4933        ).extensions.get_extension_for_class(
4934            x509.PrecertificateSignedCertificateTimestamps
4935        ).value[0]
4936        sct2 = _load_cert(
4937            os.path.join("x509", "cryptography-scts.pem"),
4938            x509.load_pem_x509_certificate,
4939            backend
4940        ).extensions.get_extension_for_class(
4941            x509.PrecertificateSignedCertificateTimestamps
4942        ).value[0]
4943        assert sct != sct2
4944        assert sct != object()
4945
4946    @pytest.mark.supported(
4947        only_if=lambda backend: (
4948            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
4949        skip_message="Requires OpenSSL 1.1.0f+",
4950    )
4951    def test_hash(self, backend):
4952        sct = _load_cert(
4953            os.path.join("x509", "badssl-sct.pem"),
4954            x509.load_pem_x509_certificate,
4955            backend
4956        ).extensions.get_extension_for_class(
4957            x509.PrecertificateSignedCertificateTimestamps
4958        ).value[0]
4959        sct2 = _load_cert(
4960            os.path.join("x509", "badssl-sct.pem"),
4961            x509.load_pem_x509_certificate,
4962            backend
4963        ).extensions.get_extension_for_class(
4964            x509.PrecertificateSignedCertificateTimestamps
4965        ).value[0]
4966        sct3 = _load_cert(
4967            os.path.join("x509", "cryptography-scts.pem"),
4968            x509.load_pem_x509_certificate,
4969            backend
4970        ).extensions.get_extension_for_class(
4971            x509.PrecertificateSignedCertificateTimestamps
4972        ).value[0]
4973        assert hash(sct) == hash(sct2)
4974        assert hash(sct) != hash(sct3)
4975
4976
4977@pytest.mark.requires_backend_interface(interface=RSABackend)
4978@pytest.mark.requires_backend_interface(interface=X509Backend)
4979class TestPrecertificateSignedCertificateTimestampsExtension(object):
4980    def test_init(self):
4981        with pytest.raises(TypeError):
4982            x509.PrecertificateSignedCertificateTimestamps([object()])
4983
4984    def test_repr(self):
4985        assert repr(x509.PrecertificateSignedCertificateTimestamps([])) == (
4986            "<PrecertificateSignedCertificateTimestamps([])>"
4987        )
4988
4989    @pytest.mark.supported(
4990        only_if=lambda backend: (
4991            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
4992        skip_message="Requires OpenSSL 1.1.0f+",
4993    )
4994    def test_eq(self, backend):
4995        psct1 = _load_cert(
4996            os.path.join("x509", "badssl-sct.pem"),
4997            x509.load_pem_x509_certificate,
4998            backend
4999        ).extensions.get_extension_for_class(
5000            x509.PrecertificateSignedCertificateTimestamps
5001        ).value
5002        psct2 = _load_cert(
5003            os.path.join("x509", "badssl-sct.pem"),
5004            x509.load_pem_x509_certificate,
5005            backend
5006        ).extensions.get_extension_for_class(
5007            x509.PrecertificateSignedCertificateTimestamps
5008        ).value
5009        assert psct1 == psct2
5010
5011    @pytest.mark.supported(
5012        only_if=lambda backend: (
5013            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
5014        skip_message="Requires OpenSSL 1.1.0f+",
5015    )
5016    def test_ne(self, backend):
5017        psct1 = _load_cert(
5018            os.path.join("x509", "cryptography-scts.pem"),
5019            x509.load_pem_x509_certificate,
5020            backend
5021        ).extensions.get_extension_for_class(
5022            x509.PrecertificateSignedCertificateTimestamps
5023        ).value
5024        psct2 = _load_cert(
5025            os.path.join("x509", "badssl-sct.pem"),
5026            x509.load_pem_x509_certificate,
5027            backend
5028        ).extensions.get_extension_for_class(
5029            x509.PrecertificateSignedCertificateTimestamps
5030        ).value
5031        assert psct1 != psct2
5032        assert psct1 != object()
5033
5034    @pytest.mark.supported(
5035        only_if=lambda backend: (
5036            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
5037        skip_message="Requires OpenSSL 1.1.0f+",
5038    )
5039    def test_hash(self, backend):
5040        psct1 = _load_cert(
5041            os.path.join("x509", "badssl-sct.pem"),
5042            x509.load_pem_x509_certificate,
5043            backend
5044        ).extensions.get_extension_for_class(
5045            x509.PrecertificateSignedCertificateTimestamps
5046        ).value
5047        psct2 = _load_cert(
5048            os.path.join("x509", "badssl-sct.pem"),
5049            x509.load_pem_x509_certificate,
5050            backend
5051        ).extensions.get_extension_for_class(
5052            x509.PrecertificateSignedCertificateTimestamps
5053        ).value
5054        psct3 = _load_cert(
5055            os.path.join("x509", "cryptography-scts.pem"),
5056            x509.load_pem_x509_certificate,
5057            backend
5058        ).extensions.get_extension_for_class(
5059            x509.PrecertificateSignedCertificateTimestamps
5060        ).value
5061        assert hash(psct1) == hash(psct2)
5062        assert hash(psct1) != hash(psct3)
5063
5064    @pytest.mark.supported(
5065        only_if=lambda backend: (
5066            backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER),
5067        skip_message="Requires OpenSSL 1.1.0f+",
5068    )
5069    def test_simple(self, backend):
5070        cert = _load_cert(
5071            os.path.join("x509", "badssl-sct.pem"),
5072            x509.load_pem_x509_certificate,
5073            backend
5074        )
5075        scts = cert.extensions.get_extension_for_class(
5076            x509.PrecertificateSignedCertificateTimestamps
5077        ).value
5078        assert len(scts) == 1
5079        [sct] = scts
5080        assert scts[0] == sct
5081        assert sct.version == x509.certificate_transparency.Version.v1
5082        assert sct.log_id == (
5083            b"\xa7\xceJNb\x07\xe0\xad\xde\xe5\xfd\xaaK\x1f\x86v\x87g\xb5\xd0"
5084            b"\x02\xa5]G1\x0e~g\n\x95\xea\xb2"
5085        )
5086        assert sct.timestamp == datetime.datetime(
5087            2016, 11, 17, 1, 56, 25, 396000
5088        )
5089        assert (
5090            sct.entry_type ==
5091            x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE
5092        )
5093
5094    @pytest.mark.supported(
5095        only_if=lambda backend: (
5096            not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER),
5097        skip_message="Requires OpenSSL < 1.1.0",
5098    )
5099    def test_skips_scts_if_unsupported(self, backend):
5100        cert = _load_cert(
5101            os.path.join("x509", "badssl-sct.pem"),
5102            x509.load_pem_x509_certificate,
5103            backend
5104        )
5105        assert len(cert.extensions) == 10
5106        with pytest.raises(x509.ExtensionNotFound):
5107            cert.extensions.get_extension_for_class(
5108                x509.PrecertificateSignedCertificateTimestamps
5109            )
5110
5111        ext = cert.extensions.get_extension_for_oid(
5112            x509.ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
5113        )
5114        assert isinstance(ext.value, x509.UnrecognizedExtension)
5115
5116
5117@pytest.mark.requires_backend_interface(interface=RSABackend)
5118@pytest.mark.requires_backend_interface(interface=X509Backend)
5119class TestInvalidExtension(object):
5120    def test_invalid_certificate_policies_data(self, backend):
5121        cert = _load_cert(
5122            os.path.join(
5123                "x509", "custom", "cp_invalid.pem"
5124            ),
5125            x509.load_pem_x509_certificate,
5126            backend
5127        )
5128        with pytest.raises(ValueError):
5129            cert.extensions
5130
5131
5132class TestOCSPNonce(object):
5133    def test_non_bytes(self):
5134        with pytest.raises(TypeError):
5135            x509.OCSPNonce(38)
5136
5137    def test_eq(self):
5138        nonce1 = x509.OCSPNonce(b"0" * 5)
5139        nonce2 = x509.OCSPNonce(b"0" * 5)
5140        assert nonce1 == nonce2
5141
5142    def test_ne(self):
5143        nonce1 = x509.OCSPNonce(b"0" * 5)
5144        nonce2 = x509.OCSPNonce(b"0" * 6)
5145        assert nonce1 != nonce2
5146        assert nonce1 != object()
5147
5148    def test_repr(self):
5149        nonce1 = x509.OCSPNonce(b"nonce")
5150        if not six.PY2:
5151            assert repr(nonce1) == "<OCSPNonce(nonce=b'nonce')>"
5152        else:
5153            assert repr(nonce1) == "<OCSPNonce(nonce='nonce')>"
5154
5155    def test_hash(self):
5156        nonce1 = x509.OCSPNonce(b"0" * 5)
5157        nonce2 = x509.OCSPNonce(b"0" * 5)
5158        nonce3 = x509.OCSPNonce(b"1" * 5)
5159        assert hash(nonce1) == hash(nonce2)
5160        assert hash(nonce1) != hash(nonce3)
5161