diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-10-19 23:45:59 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-10-20 11:13:07 -0500 |
commit | 5a2bb54bbb7b68a7407ab5d62c828c329166bd81 (patch) | |
tree | c2de009d37d9f1603dd66914bf9f6f3a4f12aa4a | |
parent | 08801cd1bacf08aa4d4a833ff235574f4da15a20 (diff) | |
download | cryptography-5a2bb54bbb7b68a7407ab5d62c828c329166bd81.tar.gz cryptography-5a2bb54bbb7b68a7407ab5d62c828c329166bd81.tar.bz2 cryptography-5a2bb54bbb7b68a7407ab5d62c828c329166bd81.zip |
encode countryName with PrintableString
This commit adds a dependency on asn1crypto for testing purposes to
parse the certificate and confirm that countryName is encoded with
PrintableString while other fields are UTF8String. This is a test
only dep.
-rw-r--r-- | dev-requirements.txt | 1 | ||||
-rw-r--r-- | setup.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 14 | ||||
-rw-r--r-- | tests/test_x509.py | 39 | ||||
-rw-r--r-- | tox.ini | 1 |
5 files changed, 50 insertions, 6 deletions
diff --git a/dev-requirements.txt b/dev-requirements.txt index d82c13b6..2c0ca18c 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,3 +1,4 @@ +asn1crypto coverage flake8 flake8-import-order @@ -63,6 +63,7 @@ test_requirements = [ "pretend", "iso8601", "hypothesis", + "asn1crypto", ] # If there's no vectors locally that probably means we are in a tarball and diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index f86c3aa1..db7022e5 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -52,7 +52,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import ( from cryptography.hazmat.primitives.ciphers.modes import ( CBC, CFB, CFB8, CTR, ECB, GCM, OFB ) -from cryptography.x509.oid import ExtensionOID +from cryptography.x509.oid import ExtensionOID, NameOID _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) @@ -119,12 +119,14 @@ def _encode_name(backend, attributes): for attribute in attributes: value = attribute.value.encode('utf8') obj = _txt2obj_gc(backend, attribute.oid.dotted_string) + if attribute.oid == NameOID.COUNTRY_NAME: + # Per RFC5280 countryName should be encoded as PrintableString, + # not UTF8String + type = backend._lib.MBSTRING_ASC + else: + type = backend._lib.MBSTRING_UTF8 res = backend._lib.X509_NAME_add_entry_by_OBJ( - subject, - obj, - backend._lib.MBSTRING_UTF8, - value, - -1, -1, 0, + subject, obj, type, value, -1, -1, 0, ) backend.openssl_assert(res == 1) return subject diff --git a/tests/test_x509.py b/tests/test_x509.py index 8035886c..1fa4d82a 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -9,6 +9,8 @@ import datetime import ipaddress import os +from asn1crypto import core, x509 as asn1cryptox509 + import pytest import six @@ -834,6 +836,43 @@ class TestRSACertificateRequest(object): x509.DNSName(u"cryptography.io"), ] + def test_build_cert_printable_string_country_name(self, backend): + issuer_private_key = RSA_KEY_2048.private_key(backend) + subject_private_key = RSA_KEY_2048.private_key(backend) + + not_valid_before = datetime.datetime(2002, 1, 1, 12, 1) + not_valid_after = datetime.datetime(2030, 12, 31, 8, 30) + + builder = x509.CertificateBuilder().serial_number( + 777 + ).issuer_name(x509.Name([ + x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'), + ])).subject_name(x509.Name([ + x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'), + x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'), + ])).public_key( + subject_private_key.public_key() + ).not_valid_before( + not_valid_before + ).not_valid_after( + not_valid_after + ) + + cert = builder.sign(issuer_private_key, hashes.SHA256(), backend) + + parsedasn1 = asn1cryptox509.Certificate.load( + cert.public_bytes(serialization.Encoding.DER) + ) + assert isinstance( + parsedasn1.subject.chosen[0][0]['value'].chosen, + core.PrintableString + ) + assert isinstance( + parsedasn1.subject.chosen[1][0]['value'].chosen, + core.UTF8String + ) + class TestCertificateBuilder(object): @pytest.mark.requires_backend_interface(interface=RSABackend) @@ -9,6 +9,7 @@ deps = pretend pytest hypothesis>=1.11.4 + asn1crypto ./vectors passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME commands = |