diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-08-04 20:59:24 +0100 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2015-08-08 14:24:33 -0500 |
commit | 2c9d6f13bfbc5269af8d8d4baec63f7c70063a5d (patch) | |
tree | 107f522a7832ca59bdf5a6436ba88e130b32fb4e | |
parent | d5bf17ad99939920aa73e6d00a36818ecaf1c2cc (diff) | |
download | cryptography-2c9d6f13bfbc5269af8d8d4baec63f7c70063a5d.tar.gz cryptography-2c9d6f13bfbc5269af8d8d4baec63f7c70063a5d.tar.bz2 cryptography-2c9d6f13bfbc5269af8d8d4baec63f7c70063a5d.zip |
add support for encoding SubjectKeyIdentifier to CertificateBuilder
-rw-r--r-- | src/_cffi_src/openssl/asn1.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 13 | ||||
-rw-r--r-- | src/cryptography/x509.py | 4 | ||||
-rw-r--r-- | tests/test_x509.py | 36 |
4 files changed, 54 insertions, 0 deletions
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 44e9de17..c2d4fac0 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -128,6 +128,7 @@ MACROS = """ ASN1_BIT_STRING *ASN1_BIT_STRING_new(void); void ASN1_BIT_STRING_free(ASN1_BIT_STRING *); int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *, unsigned char **); +int i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *, unsigned char **); /* This is not a macro, but is const on some versions of OpenSSL */ int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *, int); ASN1_TIME *M_ASN1_TIME_dup(void *); diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 2752d98d..fdd38fa3 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -254,6 +254,17 @@ def _encode_subject_alt_name(backend, san): return pp, r +def _encode_subject_key_identifier(backend, ski): + asn1_str = _encode_asn1_str_gc(backend, ski.digest, len(ski.digest)) + pp = backend._ffi.new("unsigned char **") + r = backend._lib.i2d_ASN1_OCTET_STRING(asn1_str, pp) + assert r > 0 + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + def _encode_general_name(backend, name): if isinstance(name, x509.DNSName): gn = backend._lib.GENERAL_NAME_new() @@ -1235,6 +1246,8 @@ class Backend(object): pp, r = _encode_extended_key_usage(self, extension.value) elif isinstance(extension.value, x509.SubjectAlternativeName): pp, r = _encode_subject_alt_name(self, extension.value) + elif isinstance(extension.value, x509.SubjectKeyIdentifier): + pp, r = _encode_subject_key_identifier(self, extension.value) elif isinstance(extension.value, x509.AuthorityInformationAccess): pp, r = _encode_authority_information_access( self, extension.value diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 5ed3c094..38d540ab 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -1811,6 +1811,10 @@ class CertificateBuilder(object): extension = Extension( OID_AUTHORITY_INFORMATION_ACCESS, critical, extension ) + elif isinstance(extension, SubjectKeyIdentifier): + extension = Extension( + OID_SUBJECT_KEY_IDENTIFIER, critical, extension + ) elif isinstance(extension, InhibitAnyPolicy): extension = Extension(OID_INHIBIT_ANY_POLICY, critical, extension) elif isinstance(extension, CRLDistributionPoints): diff --git a/tests/test_x509.py b/tests/test_x509.py index 4e763e36..1cbff511 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1990,6 +1990,42 @@ class TestCertificateSigningRequestBuilder(object): ) assert ext.value == aia + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.requires_backend_interface(interface=X509Backend) + def test_build_cert_with_ski(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) + + ski = x509.SubjectKeyIdentifier.from_public_key( + subject_private_key.public_key() + ) + + builder = x509.CertificateBuilder().serial_number( + 777 + ).issuer_name(x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'), + ])).subject_name(x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'), + ])).public_key( + subject_private_key.public_key() + ).add_extension( + ski, critical=False + ).not_valid_before( + not_valid_before + ).not_valid_after( + not_valid_after + ) + + cert = builder.sign(issuer_private_key, hashes.SHA1(), backend) + + ext = cert.extensions.get_extension_for_oid( + x509.OID_SUBJECT_KEY_IDENTIFIER + ) + assert ext.value == ski + @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) |