diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/hazmat/primitives/test_dh.py | 15 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_ec.py | 15 | ||||
-rw-r--r-- | tests/test_x509.py | 232 | ||||
-rw-r--r-- | tests/test_x509_ext.py | 1036 |
4 files changed, 1280 insertions, 18 deletions
diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 115f3d8c..d8869de9 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -1,15 +1,6 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. from __future__ import absolute_import, division, print_function diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 3273fe63..82b5b3a1 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -305,10 +305,17 @@ class TestECDSAVectors(object): @pytest.mark.parametrize( "vector", - load_vectors_from_file( - os.path.join( - "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt"), - load_fips_ecdsa_signing_vectors + itertools.chain( + load_vectors_from_file( + os.path.join( + "asymmetric", "ECDSA", "FIPS_186-3", "SigGen.txt"), + load_fips_ecdsa_signing_vectors + ), + load_vectors_from_file( + os.path.join( + "asymmetric", "ECDSA", "SECP256K1", "SigGen.txt"), + load_fips_ecdsa_signing_vectors + ), ) ) def test_signatures(self, backend, vector): diff --git a/tests/test_x509.py b/tests/test_x509.py index 8561f1f4..a3bed85f 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -15,7 +15,7 @@ from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.interfaces import ( DSABackend, EllipticCurveBackend, RSABackend, X509Backend ) -from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa from .hazmat.primitives.test_ec import _skip_curve_unsupported @@ -368,6 +368,90 @@ class TestRSACertificate(object): with pytest.raises(UnsupportedAlgorithm): cert.signature_hash_algorithm + def test_public_bytes_pem(self, backend): + # Load an existing certificate. + cert = _load_cert( + os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"), + x509.load_der_x509_certificate, + backend + ) + + # Encode it to PEM and load it back. + cert = x509.load_pem_x509_certificate(cert.public_bytes( + encoding=serialization.Encoding.PEM, + ), backend) + + # We should recover what we had to start with. + assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30) + assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30) + assert cert.serial == 2 + public_key = cert.public_key() + assert isinstance(public_key, rsa.RSAPublicKey) + assert cert.version is x509.Version.v3 + fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1())) + assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d" + + def test_public_bytes_der(self, backend): + # Load an existing certificate. + cert = _load_cert( + os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"), + x509.load_der_x509_certificate, + backend + ) + + # Encode it to DER and load it back. + cert = x509.load_der_x509_certificate(cert.public_bytes( + encoding=serialization.Encoding.DER, + ), backend) + + # We should recover what we had to start with. + assert cert.not_valid_before == datetime.datetime(2010, 1, 1, 8, 30) + assert cert.not_valid_after == datetime.datetime(2030, 12, 31, 8, 30) + assert cert.serial == 2 + public_key = cert.public_key() + assert isinstance(public_key, rsa.RSAPublicKey) + assert cert.version is x509.Version.v3 + fingerprint = binascii.hexlify(cert.fingerprint(hashes.SHA1())) + assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d" + + def test_public_bytes_invalid_encoding(self, backend): + cert = _load_cert( + os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"), + x509.load_der_x509_certificate, + backend + ) + + with pytest.raises(TypeError): + cert.public_bytes('NotAnEncoding') + + @pytest.mark.parametrize( + ("cert_path", "loader_func", "encoding"), + [ + ( + os.path.join("x509", "v1_cert.pem"), + x509.load_pem_x509_certificate, + serialization.Encoding.PEM, + ), + ( + os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"), + x509.load_der_x509_certificate, + serialization.Encoding.DER, + ), + ] + ) + def test_public_bytes_match(self, cert_path, loader_func, encoding, + backend): + cert_bytes = load_vectors_from_file( + cert_path, lambda pemfile: pemfile.read(), mode="rb" + ) + cert = loader_func(cert_bytes, backend) + serialized = cert.public_bytes(encoding) + assert serialized == cert_bytes + + +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) +class TestRSACertificateRequest(object): @pytest.mark.parametrize( ("path", "loader_func"), [ @@ -395,6 +479,9 @@ class TestRSACertificate(object): x509.NameAttribute(x509.OID_ORGANIZATION_NAME, 'PyCA'), x509.NameAttribute(x509.OID_COMMON_NAME, 'cryptography.io'), ] + extensions = request.extensions + assert isinstance(extensions, x509.Extensions) + assert list(extensions) == [] @pytest.mark.parametrize( "loader_func", @@ -413,6 +500,149 @@ class TestRSACertificate(object): with pytest.raises(UnsupportedAlgorithm): request.signature_hash_algorithm + def test_duplicate_extension(self, backend): + request = _load_cert( + os.path.join( + "x509", "requests", "two_basic_constraints.pem" + ), + x509.load_pem_x509_csr, + backend + ) + with pytest.raises(x509.DuplicateExtension) as exc: + request.extensions + + assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS + + def test_unsupported_critical_extension(self, backend): + request = _load_cert( + os.path.join( + "x509", "requests", "unsupported_extension_critical.pem" + ), + x509.load_pem_x509_csr, + backend + ) + with pytest.raises(x509.UnsupportedExtension) as exc: + request.extensions + + assert exc.value.oid == x509.ObjectIdentifier('1.2.3.4') + + def test_unsupported_extension(self, backend): + request = _load_cert( + os.path.join( + "x509", "requests", "unsupported_extension.pem" + ), + x509.load_pem_x509_csr, + backend + ) + extensions = request.extensions + assert len(extensions) == 0 + + def test_request_basic_constraints(self, backend): + request = _load_cert( + os.path.join( + "x509", "requests", "basic_constraints.pem" + ), + x509.load_pem_x509_csr, + backend + ) + extensions = request.extensions + assert isinstance(extensions, x509.Extensions) + assert list(extensions) == [ + x509.Extension( + x509.OID_BASIC_CONSTRAINTS, + True, + x509.BasicConstraints(True, 1), + ), + ] + + def test_public_bytes_pem(self, backend): + # Load an existing CSR. + request = _load_cert( + os.path.join("x509", "requests", "rsa_sha1.pem"), + x509.load_pem_x509_csr, + backend + ) + + # Encode it to PEM and load it back. + request = x509.load_pem_x509_csr(request.public_bytes( + encoding=serialization.Encoding.PEM, + ), backend) + + # We should recover what we had to start with. + assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + public_key = request.public_key() + assert isinstance(public_key, rsa.RSAPublicKey) + subject = request.subject + assert isinstance(subject, x509.Name) + assert list(subject) == [ + x509.NameAttribute(x509.OID_COUNTRY_NAME, 'US'), + x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, 'Texas'), + x509.NameAttribute(x509.OID_LOCALITY_NAME, 'Austin'), + x509.NameAttribute(x509.OID_ORGANIZATION_NAME, 'PyCA'), + x509.NameAttribute(x509.OID_COMMON_NAME, 'cryptography.io'), + ] + + def test_public_bytes_der(self, backend): + # Load an existing CSR. + request = _load_cert( + os.path.join("x509", "requests", "rsa_sha1.pem"), + x509.load_pem_x509_csr, + backend + ) + + # Encode it to DER and load it back. + request = x509.load_der_x509_csr(request.public_bytes( + encoding=serialization.Encoding.DER, + ), backend) + + # We should recover what we had to start with. + assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + public_key = request.public_key() + assert isinstance(public_key, rsa.RSAPublicKey) + subject = request.subject + assert isinstance(subject, x509.Name) + assert list(subject) == [ + x509.NameAttribute(x509.OID_COUNTRY_NAME, 'US'), + x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, 'Texas'), + x509.NameAttribute(x509.OID_LOCALITY_NAME, 'Austin'), + x509.NameAttribute(x509.OID_ORGANIZATION_NAME, 'PyCA'), + x509.NameAttribute(x509.OID_COMMON_NAME, 'cryptography.io'), + ] + + def test_public_bytes_invalid_encoding(self, backend): + request = _load_cert( + os.path.join("x509", "requests", "rsa_sha1.pem"), + x509.load_pem_x509_csr, + backend + ) + + with pytest.raises(TypeError): + request.public_bytes('NotAnEncoding') + + @pytest.mark.parametrize( + ("request_path", "loader_func", "encoding"), + [ + ( + os.path.join("x509", "requests", "rsa_sha1.pem"), + x509.load_pem_x509_csr, + serialization.Encoding.PEM, + ), + ( + os.path.join("x509", "requests", "rsa_sha1.der"), + x509.load_der_x509_csr, + serialization.Encoding.DER, + ), + ] + ) + def test_public_bytes_match(self, request_path, loader_func, encoding, + backend): + request_bytes = load_vectors_from_file( + request_path, lambda pemfile: pemfile.read(), mode="rb" + ) + request = loader_func(request_bytes, backend) + serialized = request.public_bytes(encoding) + assert serialized == request_bytes + @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 8a227953..f16db337 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -38,6 +38,323 @@ class TestExtension(object): "_length=None)>)>" ) + def test_eq(self): + ext1 = x509.Extension( + x509.ObjectIdentifier('1.2.3.4'), False, 'value' + ) + ext2 = x509.Extension( + x509.ObjectIdentifier('1.2.3.4'), False, 'value' + ) + assert ext1 == ext2 + + def test_ne(self): + ext1 = x509.Extension( + x509.ObjectIdentifier('1.2.3.4'), False, 'value' + ) + ext2 = x509.Extension( + x509.ObjectIdentifier('1.2.3.5'), False, 'value' + ) + ext3 = x509.Extension( + x509.ObjectIdentifier('1.2.3.4'), True, 'value' + ) + ext4 = x509.Extension( + x509.ObjectIdentifier('1.2.3.4'), False, 'value4' + ) + assert ext1 != ext2 + assert ext1 != ext3 + assert ext1 != ext4 + assert ext1 != object() + + +class TestNoticeReference(object): + def test_notice_numbers_not_all_int(self): + with pytest.raises(TypeError): + x509.NoticeReference("org", [1, 2, "three"]) + + def test_notice_numbers_none(self): + with pytest.raises(TypeError): + x509.NoticeReference("org", None) + + def test_repr(self): + nr = x509.NoticeReference(u"org", [1, 3, 4]) + + if six.PY3: + assert repr(nr) == ( + "<NoticeReference(organization='org', notice_numbers=[1, 3, 4" + "])>" + ) + else: + assert repr(nr) == ( + "<NoticeReference(organization=u'org', notice_numbers=[1, 3, " + "4])>" + ) + + def test_eq(self): + nr = x509.NoticeReference("org", [1, 2]) + nr2 = x509.NoticeReference("org", [1, 2]) + assert nr == nr2 + + def test_ne(self): + nr = x509.NoticeReference("org", [1, 2]) + nr2 = x509.NoticeReference("org", [1]) + nr3 = x509.NoticeReference(None, [1, 2]) + assert nr != nr2 + assert nr != nr3 + assert nr != object() + + +class TestUserNotice(object): + def test_notice_reference_invalid(self): + with pytest.raises(TypeError): + x509.UserNotice("invalid", None) + + def test_notice_reference_none(self): + un = x509.UserNotice(None, "text") + assert un.notice_reference is None + assert un.explicit_text == "text" + + def test_repr(self): + un = x509.UserNotice(x509.NoticeReference(u"org", [1]), u"text") + if six.PY3: + assert repr(un) == ( + "<UserNotice(notice_reference=<NoticeReference(organization='" + "org', notice_numbers=[1])>, explicit_text='text')>" + ) + else: + assert repr(un) == ( + "<UserNotice(notice_reference=<NoticeReference(organization=u" + "'org', notice_numbers=[1])>, explicit_text=u'text')>" + ) + + def test_eq(self): + nr = x509.NoticeReference("org", [1, 2]) + nr2 = x509.NoticeReference("org", [1, 2]) + un = x509.UserNotice(nr, "text") + un2 = x509.UserNotice(nr2, "text") + assert un == un2 + + def test_ne(self): + nr = x509.NoticeReference("org", [1, 2]) + nr2 = x509.NoticeReference("org", [1]) + un = x509.UserNotice(nr, "text") + un2 = x509.UserNotice(nr2, "text") + un3 = x509.UserNotice(nr, "text3") + assert un != un2 + assert un != un3 + assert un != object() + + +class TestPolicyInformation(object): + def test_invalid_policy_identifier(self): + with pytest.raises(TypeError): + x509.PolicyInformation("notanoid", None) + + def test_none_policy_qualifiers(self): + pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), None) + assert pi.policy_identifier == x509.ObjectIdentifier("1.2.3") + assert pi.policy_qualifiers is None + + def test_policy_qualifiers(self): + pq = [u"string"] + pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) + assert pi.policy_identifier == x509.ObjectIdentifier("1.2.3") + assert pi.policy_qualifiers == pq + + def test_invalid_policy_identifiers(self): + with pytest.raises(TypeError): + x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), [1, 2]) + + def test_repr(self): + pq = [u"string", x509.UserNotice(None, u"hi")] + pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) + if six.PY3: + assert repr(pi) == ( + "<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=1." + "2.3, name=Unknown OID)>, policy_qualifiers=['string', <UserNo" + "tice(notice_reference=None, explicit_text='hi')>])>" + ) + else: + assert repr(pi) == ( + "<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=1." + "2.3, name=Unknown OID)>, policy_qualifiers=[u'string', <UserN" + "otice(notice_reference=None, explicit_text=u'hi')>])>" + ) + + def test_eq(self): + pi = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), + [u"string", x509.UserNotice(None, u"hi")] + ) + pi2 = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), + [u"string", x509.UserNotice(None, u"hi")] + ) + assert pi == pi2 + + def test_ne(self): + pi = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), [u"string"] + ) + pi2 = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), [u"string2"] + ) + pi3 = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3.4"), [u"string"] + ) + assert pi != pi2 + assert pi != pi3 + assert pi != object() + + +class TestCertificatePolicies(object): + def test_invalid_policies(self): + pq = [u"string"] + pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) + with pytest.raises(TypeError): + x509.CertificatePolicies([1, pi]) + + def test_iter_len(self): + pq = [u"string"] + pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) + cp = x509.CertificatePolicies([pi]) + assert len(cp) == 1 + for policyinfo in cp: + assert policyinfo == pi + + def test_repr(self): + pq = [u"string"] + pi = x509.PolicyInformation(x509.ObjectIdentifier("1.2.3"), pq) + cp = x509.CertificatePolicies([pi]) + if six.PY3: + assert repr(cp) == ( + "<CertificatePolicies([<PolicyInformation(policy_identifier=<O" + "bjectIdentifier(oid=1.2.3, name=Unknown OID)>, policy_qualifi" + "ers=['string'])>])>" + ) + else: + assert repr(cp) == ( + "<CertificatePolicies([<PolicyInformation(policy_identifier=<O" + "bjectIdentifier(oid=1.2.3, name=Unknown OID)>, policy_qualifi" + "ers=[u'string'])>])>" + ) + + def test_eq(self): + pi = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), [u"string"] + ) + cp = x509.CertificatePolicies([pi]) + pi2 = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), [u"string"] + ) + cp2 = x509.CertificatePolicies([pi2]) + assert cp == cp2 + + def test_ne(self): + pi = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), [u"string"] + ) + cp = x509.CertificatePolicies([pi]) + pi2 = x509.PolicyInformation( + x509.ObjectIdentifier("1.2.3"), [u"string2"] + ) + cp2 = x509.CertificatePolicies([pi2]) + assert cp != cp2 + assert cp != object() + + +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) +class TestCertificatePoliciesExtension(object): + def test_cps_uri_policy_qualifier(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "cp_cps_uri.pem"), + x509.load_pem_x509_certificate, + backend + ) + + cp = cert.extensions.get_extension_for_oid( + x509.OID_CERTIFICATE_POLICIES + ).value + + assert cp == x509.CertificatePolicies([ + x509.PolicyInformation( + x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), + [u"http://other.com/cps"] + ) + ]) + + def test_user_notice_with_notice_reference(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cp_user_notice_with_notice_reference.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cp = cert.extensions.get_extension_for_oid( + x509.OID_CERTIFICATE_POLICIES + ).value + + assert cp == x509.CertificatePolicies([ + x509.PolicyInformation( + x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), + [ + u"http://example.com/cps", + u"http://other.com/cps", + x509.UserNotice( + x509.NoticeReference(u"my org", [1, 2, 3, 4]), + u"thing" + ) + ] + ) + ]) + + def test_user_notice_with_explicit_text(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cp_user_notice_with_explicit_text.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cp = cert.extensions.get_extension_for_oid( + x509.OID_CERTIFICATE_POLICIES + ).value + + assert cp == x509.CertificatePolicies([ + x509.PolicyInformation( + x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), + [x509.UserNotice(None, u"thing")] + ) + ]) + + def test_user_notice_no_explicit_text(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cp_user_notice_no_explicit_text.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cp = cert.extensions.get_extension_for_oid( + x509.OID_CERTIFICATE_POLICIES + ).value + + assert cp == x509.CertificatePolicies([ + x509.PolicyInformation( + x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"), + [ + x509.UserNotice( + x509.NoticeReference(u"my org", [1, 2, 3, 4]), + None + ) + ] + ) + ]) + class TestKeyUsage(object): def test_key_agreement_false_encipher_decipher_true(self): @@ -173,6 +490,57 @@ class TestKeyUsage(object): "only=False)>" ) + def test_eq(self): + ku = x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=True, + key_cert_sign=False, + crl_sign=False, + encipher_only=False, + decipher_only=True + ) + ku2 = x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=True, + key_cert_sign=False, + crl_sign=False, + encipher_only=False, + decipher_only=True + ) + assert ku == ku2 + + def test_ne(self): + ku = x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=True, + key_cert_sign=False, + crl_sign=False, + encipher_only=False, + decipher_only=True + ) + ku2 = x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=False, + key_cert_sign=False, + crl_sign=False, + encipher_only=False, + decipher_only=False + ) + assert ku != ku2 + assert ku != object() + class TestSubjectKeyIdentifier(object): def test_properties(self): @@ -276,6 +644,35 @@ class TestAuthorityKeyIdentifier(object): "])>)>], authority_cert_serial_number=1234)>" ) + def test_eq(self): + dirname = x509.DirectoryName( + x509.Name([x509.NameAttribute(x509.OID_COMMON_NAME, 'myCN')]) + ) + aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234) + dirname2 = x509.DirectoryName( + x509.Name([x509.NameAttribute(x509.OID_COMMON_NAME, 'myCN')]) + ) + aki2 = x509.AuthorityKeyIdentifier(b"digest", [dirname2], 1234) + assert aki == aki2 + + def test_ne(self): + dirname = x509.DirectoryName( + x509.Name([x509.NameAttribute(x509.OID_COMMON_NAME, 'myCN')]) + ) + dirname5 = x509.DirectoryName( + x509.Name([x509.NameAttribute(x509.OID_COMMON_NAME, 'aCN')]) + ) + aki = x509.AuthorityKeyIdentifier(b"digest", [dirname], 1234) + aki2 = x509.AuthorityKeyIdentifier(b"diges", [dirname], 1234) + aki3 = x509.AuthorityKeyIdentifier(b"digest", None, None) + aki4 = x509.AuthorityKeyIdentifier(b"digest", [dirname], 12345) + aki5 = x509.AuthorityKeyIdentifier(b"digest", [dirname5], 12345) + assert aki != aki2 + assert aki != aki3 + assert aki != aki4 + assert aki != aki5 + assert aki != object() + class TestBasicConstraints(object): def test_ca_not_boolean(self): @@ -303,6 +700,19 @@ class TestBasicConstraints(object): "<BasicConstraints(ca=True, path_length=None)>" ) + def test_eq(self): + na = x509.BasicConstraints(ca=True, path_length=None) + na2 = x509.BasicConstraints(ca=True, path_length=None) + assert na == na2 + + def test_ne(self): + na = x509.BasicConstraints(ca=True, path_length=None) + na2 = x509.BasicConstraints(ca=True, path_length=1) + na3 = x509.BasicConstraints(ca=False, path_length=None) + assert na != na2 + assert na != na3 + assert na != object() + class TestExtendedKeyUsage(object): def test_not_all_oids(self): @@ -711,6 +1121,12 @@ class TestIPAddress(object): gn2 = x509.IPAddress(ipaddress.IPv6Address(u"ff::")) assert repr(gn2) == "<IPAddress(value=ff::)>" + gn3 = x509.IPAddress(ipaddress.IPv4Network(u"192.168.0.0/24")) + assert repr(gn3) == "<IPAddress(value=192.168.0.0/24)>" + + gn4 = x509.IPAddress(ipaddress.IPv6Network(u"ff::/96")) + assert repr(gn4) == "<IPAddress(value=ff::/96)>" + def test_eq(self): gn = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) gn2 = x509.IPAddress(ipaddress.IPv4Address(u"127.0.0.1")) @@ -723,6 +1139,61 @@ class TestIPAddress(object): assert gn != object() +class TestGeneralNames(object): + def test_get_values_for_type(self): + gns = x509.GeneralNames( + [x509.DNSName(u"cryptography.io")] + ) + names = gns.get_values_for_type(x509.DNSName) + assert names == [u"cryptography.io"] + + def test_iter_names(self): + gns = x509.GeneralNames([ + x509.DNSName(u"cryptography.io"), + x509.DNSName(u"crypto.local"), + ]) + assert len(gns) == 2 + assert list(gns) == [ + x509.DNSName(u"cryptography.io"), + x509.DNSName(u"crypto.local"), + ] + + def test_invalid_general_names(self): + with pytest.raises(TypeError): + x509.GeneralNames( + [x509.DNSName(u"cryptography.io"), "invalid"] + ) + + def test_repr(self): + gns = x509.GeneralNames( + [ + x509.DNSName(u"cryptography.io") + ] + ) + assert repr(gns) == ( + "<GeneralNames([<DNSName(value=cryptography.io)>])>" + ) + + def test_eq(self): + gns = x509.GeneralNames( + [x509.DNSName(u"cryptography.io")] + ) + gns2 = x509.GeneralNames( + [x509.DNSName(u"cryptography.io")] + ) + assert gns == gns2 + + def test_ne(self): + gns = x509.GeneralNames( + [x509.DNSName(u"cryptography.io")] + ) + gns2 = x509.GeneralNames( + [x509.RFC822Name(u"admin@cryptography.io")] + ) + assert gns != gns2 + assert gns != object() + + class TestSubjectAlternativeName(object): def test_get_values_for_type(self): san = x509.SubjectAlternativeName( @@ -755,9 +1226,29 @@ class TestSubjectAlternativeName(object): ] ) assert repr(san) == ( - "<SubjectAlternativeName([<DNSName(value=cryptography.io)>])>" + "<SubjectAlternativeName(" + "<GeneralNames([<DNSName(value=cryptography.io)>])>)>" ) + def test_eq(self): + san = x509.SubjectAlternativeName( + [x509.DNSName(u"cryptography.io")] + ) + san2 = x509.SubjectAlternativeName( + [x509.DNSName(u"cryptography.io")] + ) + assert san == san2 + + def test_ne(self): + san = x509.SubjectAlternativeName( + [x509.DNSName(u"cryptography.io")] + ) + san2 = x509.SubjectAlternativeName( + [x509.RFC822Name(u"admin@cryptography.io")] + ) + assert san != san2 + assert san != object() + @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) @@ -897,6 +1388,17 @@ class TestRSASubjectAlternativeNameExtension(object): rfc822name = san.get_values_for_type(x509.RFC822Name) assert [u"email@em\xe5\xefl.com"] == rfc822name + def test_idna2003_invalid(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "san_idna2003_dnsname.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + with pytest.raises(UnicodeError): + cert.extensions + def test_unicode_rfc822_name_dns_name_uri(self, backend): cert = _load_cert( os.path.join( @@ -1318,3 +1820,535 @@ class TestAuthorityKeyIdentifierExtension(object): ) ] assert ext.value.authority_cert_serial_number == 3 + + +class TestDistributionPoint(object): + def test_distribution_point_full_name_not_general_names(self): + with pytest.raises(TypeError): + x509.DistributionPoint(["notgn"], None, None, None) + + def test_distribution_point_relative_name_not_name(self): + with pytest.raises(TypeError): + x509.DistributionPoint(None, "notname", None, None) + + def test_distribution_point_full_and_relative_not_none(self): + with pytest.raises(ValueError): + x509.DistributionPoint("data", "notname", None, None) + + def test_crl_issuer_not_general_names(self): + with pytest.raises(TypeError): + x509.DistributionPoint(None, None, None, ["notgn"]) + + def test_reason_not_reasonflags(self): + with pytest.raises(TypeError): + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + frozenset(["notreasonflags"]), + None + ) + + def test_reason_not_frozenset(self): + with pytest.raises(TypeError): + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + [x509.ReasonFlags.ca_compromise], + None + ) + + def test_disallowed_reasons(self): + with pytest.raises(ValueError): + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + frozenset([x509.ReasonFlags.unspecified]), + None + ) + + with pytest.raises(ValueError): + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + frozenset([x509.ReasonFlags.remove_from_crl]), + None + ) + + def test_reason_only(self): + with pytest.raises(ValueError): + x509.DistributionPoint( + None, + None, + frozenset([x509.ReasonFlags.aa_compromise]), + None + ) + + def test_eq(self): + dp = x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + frozenset([x509.ReasonFlags.superseded]), + [ + x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_COMMON_NAME, "Important CA" + ) + ]) + ) + ], + ) + dp2 = x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + frozenset([x509.ReasonFlags.superseded]), + [ + x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_COMMON_NAME, "Important CA" + ) + ]) + ) + ], + ) + assert dp == dp2 + + def test_ne(self): + dp = x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + frozenset([x509.ReasonFlags.superseded]), + [ + x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_COMMON_NAME, "Important CA" + ) + ]) + ) + ], + ) + dp2 = x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://crypt.og/crl")], + None, + None, + None + ) + assert dp != dp2 + assert dp != object() + + def test_repr(self): + dp = x509.DistributionPoint( + None, + x509.Name([ + x509.NameAttribute(x509.OID_COMMON_NAME, "myCN") + ]), + frozenset([x509.ReasonFlags.ca_compromise]), + [ + x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_COMMON_NAME, "Important CA" + ) + ]) + ) + ], + ) + if six.PY3: + assert repr(dp) == ( + "<DistributionPoint(full_name=None, relative_name=<Name([<Name" + "Attribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)" + ">, value='myCN')>])>, reasons=frozenset({<ReasonFlags.ca_comp" + "romise: 'cACompromise'>}), crl_issuer=[<DirectoryName(value=<" + "Name([<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=" + "commonName)>, value='Important CA')>])>)>])>" + ) + else: + assert repr(dp) == ( + "<DistributionPoint(full_name=None, relative_name=<Name([<Name" + "Attribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)" + ">, value='myCN')>])>, reasons=frozenset([<ReasonFlags.ca_comp" + "romise: 'cACompromise'>]), crl_issuer=[<DirectoryName(value=<" + "Name([<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=" + "commonName)>, value='Important CA')>])>)>])>" + ) + + +class TestCRLDistributionPoints(object): + def test_invalid_distribution_points(self): + with pytest.raises(TypeError): + x509.CRLDistributionPoints(["notadistributionpoint"]) + + def test_iter_len(self): + cdp = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://domain")], + None, + None, + None + ), + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + None + ), + ]) + assert len(cdp) == 2 + assert list(cdp) == [ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"http://domain")], + None, + None, + None + ), + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + None + ), + ] + + def test_repr(self): + cdp = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([x509.ReasonFlags.key_compromise]), + None + ), + ]) + if six.PY3: + assert repr(cdp) == ( + "<CRLDistributionPoints([<DistributionPoint(full_name=[<Unifo" + "rmResourceIdentifier(value=ftp://domain)>], relative_name=No" + "ne, reasons=frozenset({<ReasonFlags.key_compromise: 'keyComp" + "romise'>}), crl_issuer=None)>])>" + ) + else: + assert repr(cdp) == ( + "<CRLDistributionPoints([<DistributionPoint(full_name=[<Unifo" + "rmResourceIdentifier(value=ftp://domain)>], relative_name=No" + "ne, reasons=frozenset([<ReasonFlags.key_compromise: 'keyComp" + "romise'>]), crl_issuer=None)>])>" + ) + + def test_eq(self): + cdp = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + [x509.UniformResourceIdentifier(u"uri://thing")], + ), + ]) + cdp2 = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + [x509.UniformResourceIdentifier(u"uri://thing")], + ), + ]) + assert cdp == cdp2 + + def test_ne(self): + cdp = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + [x509.UniformResourceIdentifier(u"uri://thing")], + ), + ]) + cdp2 = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain2")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + [x509.UniformResourceIdentifier(u"uri://thing")], + ), + ]) + cdp3 = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([x509.ReasonFlags.key_compromise]), + [x509.UniformResourceIdentifier(u"uri://thing")], + ), + ]) + cdp4 = x509.CRLDistributionPoints([ + x509.DistributionPoint( + [x509.UniformResourceIdentifier(u"ftp://domain")], + None, + frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + ]), + [x509.UniformResourceIdentifier(u"uri://thing2")], + ), + ]) + assert cdp != cdp2 + assert cdp != cdp3 + assert cdp != cdp4 + assert cdp != object() + + +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) +class TestCRLDistributionPointsExtension(object): + def test_fullname_and_crl_issuer(self, backend): + cert = _load_cert( + os.path.join( + "x509", "PKITS_data", "certs", "ValidcRLIssuerTest28EE.crt" + ), + x509.load_der_x509_certificate, + backend + ) + + cdps = cert.extensions.get_extension_for_oid( + x509.OID_CRL_DISTRIBUTION_POINTS + ).value + + assert cdps == x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.DirectoryName( + x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"), + x509.NameAttribute( + x509.OID_ORGANIZATION_NAME, + "Test Certificates 2011" + ), + x509.NameAttribute( + x509.OID_ORGANIZATIONAL_UNIT_NAME, + "indirectCRL CA3 cRLIssuer" + ), + x509.NameAttribute( + x509.OID_COMMON_NAME, + "indirect CRL for indirectCRL CA3" + ), + ]) + )], + relative_name=None, + reasons=None, + crl_issuer=[x509.DirectoryName( + x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"), + x509.NameAttribute( + x509.OID_ORGANIZATION_NAME, + "Test Certificates 2011" + ), + x509.NameAttribute( + x509.OID_ORGANIZATIONAL_UNIT_NAME, + "indirectCRL CA3 cRLIssuer" + ), + ]) + )], + ) + ]) + + def test_relativename_and_crl_issuer(self, backend): + cert = _load_cert( + os.path.join( + "x509", "PKITS_data", "certs", "ValidcRLIssuerTest29EE.crt" + ), + x509.load_der_x509_certificate, + backend + ) + + cdps = cert.extensions.get_extension_for_oid( + x509.OID_CRL_DISTRIBUTION_POINTS + ).value + + assert cdps == x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=None, + relative_name=x509.Name([ + x509.NameAttribute( + x509.OID_COMMON_NAME, + "indirect CRL for indirectCRL CA3" + ), + ]), + reasons=None, + crl_issuer=[x509.DirectoryName( + x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"), + x509.NameAttribute( + x509.OID_ORGANIZATION_NAME, + "Test Certificates 2011" + ), + x509.NameAttribute( + x509.OID_ORGANIZATIONAL_UNIT_NAME, + "indirectCRL CA3 cRLIssuer" + ), + ]) + )], + ) + ]) + + def test_fullname_crl_issuer_reasons(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cdp_fullname_reasons_crl_issuer.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cdps = cert.extensions.get_extension_for_oid( + x509.OID_CRL_DISTRIBUTION_POINTS + ).value + + assert cdps == x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.UniformResourceIdentifier( + u"http://myhost.com/myca.crl" + )], + relative_name=None, + reasons=frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise + ]), + crl_issuer=[x509.DirectoryName( + x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"), + x509.NameAttribute( + x509.OID_ORGANIZATION_NAME, "PyCA" + ), + x509.NameAttribute( + x509.OID_COMMON_NAME, "cryptography CA" + ), + ]) + )], + ) + ]) + + def test_all_reasons(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cdp_all_reasons.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cdps = cert.extensions.get_extension_for_oid( + x509.OID_CRL_DISTRIBUTION_POINTS + ).value + + assert cdps == x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.UniformResourceIdentifier( + u"http://domain.com/some.crl" + )], + relative_name=None, + reasons=frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + x509.ReasonFlags.affiliation_changed, + x509.ReasonFlags.superseded, + x509.ReasonFlags.privilege_withdrawn, + x509.ReasonFlags.cessation_of_operation, + x509.ReasonFlags.aa_compromise, + x509.ReasonFlags.certificate_hold, + ]), + crl_issuer=None + ) + ]) + + def test_single_reason(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cdp_reason_aa_compromise.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cdps = cert.extensions.get_extension_for_oid( + x509.OID_CRL_DISTRIBUTION_POINTS + ).value + + assert cdps == x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.UniformResourceIdentifier( + u"http://domain.com/some.crl" + )], + relative_name=None, + reasons=frozenset([x509.ReasonFlags.aa_compromise]), + crl_issuer=None + ) + ]) + + def test_crl_issuer_only(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cdp_crl_issuer.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + + cdps = cert.extensions.get_extension_for_oid( + x509.OID_CRL_DISTRIBUTION_POINTS + ).value + + assert cdps == x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=None, + relative_name=None, + reasons=None, + crl_issuer=[x509.DirectoryName( + x509.Name([ + x509.NameAttribute( + x509.OID_COMMON_NAME, "cryptography CA" + ), + ]) + )], + ) + ]) + + +class TestInhibitAnyPolicy(object): + def test_not_int(self): + with pytest.raises(TypeError): + x509.InhibitAnyPolicy("notint") + + def test_negative_int(self): + with pytest.raises(ValueError): + x509.InhibitAnyPolicy(-1) + + def test_repr(self): + iap = x509.InhibitAnyPolicy(0) + assert repr(iap) == "<InhibitAnyPolicy(skip_certs=0)>" + + def test_eq(self): + iap = x509.InhibitAnyPolicy(1) + iap2 = x509.InhibitAnyPolicy(1) + assert iap == iap2 + + def test_ne(self): + iap = x509.InhibitAnyPolicy(1) + iap2 = x509.InhibitAnyPolicy(4) + assert iap != iap2 + assert iap != object() |