diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2015-03-30 22:12:46 -0400 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2015-03-30 22:12:46 -0400 |
commit | 33bf83fbba6e3a0e2d308160d46865a0ffeb5a8b (patch) | |
tree | d549a53d61b314f9b024c9a76e9f2803802b35ef | |
parent | d10e1ab8bb4630eb8e0902b37e9e4ea2013bd349 (diff) | |
parent | 1effb6e11ef4248c65b37a97dfe9dd0c2710882e (diff) | |
download | cryptography-33bf83fbba6e3a0e2d308160d46865a0ffeb5a8b.tar.gz cryptography-33bf83fbba6e3a0e2d308160d46865a0ffeb5a8b.tar.bz2 cryptography-33bf83fbba6e3a0e2d308160d46865a0ffeb5a8b.zip |
Merge pull request #1801 from reaperhulk/x509-request-der
X509 request DER parsing
-rw-r--r-- | CHANGELOG.rst | 3 | ||||
-rw-r--r-- | docs/x509.rst | 16 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/interfaces.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/multibackend.py | 9 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 10 | ||||
-rw-r--r-- | src/cryptography/x509.py | 4 | ||||
-rw-r--r-- | tests/hazmat/backends/test_multibackend.py | 6 | ||||
-rw-r--r-- | tests/test_x509.py | 71 |
8 files changed, 104 insertions, 21 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2d705b18..b520e48e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,7 +23,8 @@ Changelog and :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`. * Add support for parsing X.509 certificate signing requests (CSRs) with - :func:`~cryptography.x509.load_pem_x509_csr`. + :func:`~cryptography.x509.load_pem_x509_csr` and + :func:`~cryptography.x509.load_der_x509_csr`. 0.8.1 - 2015-03-20 ~~~~~~~~~~~~~~~~~~ diff --git a/docs/x509.rst b/docs/x509.rst index 22b282ce..dbfb441b 100644 --- a/docs/x509.rst +++ b/docs/x509.rst @@ -118,6 +118,22 @@ Loading Certificate Signing Requests :returns: An instance of :class:`~cryptography.x509.CertificateSigningRequest`. +.. function:: load_der_x509_csr(data, backend) + + .. versionadded:: 0.9 + + Deserialize a certificate signing request (CSR) from DER encoded data. DER + is a binary format and is not commonly used with CSRs. + + :param bytes data: The DER encoded request data. + + :param backend: A backend supporting the + :class:`~cryptography.hazmat.backends.interfaces.X509Backend` + interface. + + :returns: An instance of + :class:`~cryptography.x509.CertificateSigningRequest`. + .. doctest:: >>> from cryptography import x509 diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index 354b5141..5224f5c7 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -263,6 +263,12 @@ class X509Backend(object): """ @abc.abstractmethod + def load_der_x509_csr(self, data): + """ + Load an X.509 CSR from DER encoded data. + """ + + @abc.abstractmethod def load_pem_x509_csr(self, data): """ Load an X.509 CSR from PEM encoded data. diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py index 54b044f0..784ab84d 100644 --- a/src/cryptography/hazmat/backends/multibackend.py +++ b/src/cryptography/hazmat/backends/multibackend.py @@ -325,6 +325,15 @@ class MultiBackend(object): _Reasons.UNSUPPORTED_X509 ) + def load_der_x509_csr(self, data): + for b in self._filtered_backends(X509Backend): + return b.load_der_x509_csr(data) + + raise UnsupportedAlgorithm( + "This backend does not support X.509.", + _Reasons.UNSUPPORTED_X509 + ) + def load_pem_x509_csr(self, data): for b in self._filtered_backends(X509Backend): return b.load_pem_x509_csr(data) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 854219f7..665771a8 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -834,6 +834,16 @@ class Backend(object): x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) return _CertificateSigningRequest(self, x509_req) + def load_der_x509_csr(self, data): + mem_bio = self._bytes_to_bio(data) + x509_req = self._lib.d2i_X509_REQ_bio(mem_bio.bio, self._ffi.NULL) + if x509_req == self._ffi.NULL: + self._consume_errors() + raise ValueError("Unable to load request") + + x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) + return _CertificateSigningRequest(self, x509_req) + def _load_key(self, openssl_read_func, convert_func, data, password): mem_bio = self._bytes_to_bio(data) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 25bbe9ca..113c35e0 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -64,6 +64,10 @@ def load_pem_x509_csr(data, backend): return backend.load_pem_x509_csr(data) +def load_der_x509_csr(data, backend): + return backend.load_der_x509_csr(data) + + class InvalidVersion(Exception): def __init__(self, msg, parsed_version): super(InvalidVersion, self).__init__(msg) diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index 40305387..5871e6c8 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -200,6 +200,9 @@ class DummyX509Backend(object): def load_pem_x509_csr(self, data): pass + def load_der_x509_csr(self, data): + pass + class TestMultiBackend(object): def test_ciphers(self): @@ -476,6 +479,7 @@ class TestMultiBackend(object): backend.load_pem_x509_certificate(b"certdata") backend.load_der_x509_certificate(b"certdata") backend.load_pem_x509_csr(b"reqdata") + backend.load_der_x509_csr(b"reqdata") backend = MultiBackend([]) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): @@ -484,3 +488,5 @@ class TestMultiBackend(object): backend.load_der_x509_certificate(b"certdata") with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): backend.load_pem_x509_csr(b"reqdata") + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509): + backend.load_der_x509_csr(b"reqdata") diff --git a/tests/test_x509.py b/tests/test_x509.py index 22b93f61..dc148d9d 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -340,12 +340,21 @@ class TestRSACertificate(object): with pytest.raises(UnsupportedAlgorithm): cert.signature_hash_algorithm - def test_load_rsa_certificate_request(self, backend): - request = _load_cert( - os.path.join("x509", "requests", "rsa_sha1.pem"), - x509.load_pem_x509_csr, - backend - ) + @pytest.mark.parametrize( + ("path", "loader_func"), + [ + [ + os.path.join("x509", "requests", "rsa_sha1.pem"), + x509.load_pem_x509_csr + ], + [ + os.path.join("x509", "requests", "rsa_sha1.der"), + x509.load_der_x509_csr + ], + ] + ) + def test_load_rsa_certificate_request(self, path, loader_func, backend): + request = _load_cert(path, loader_func, backend) assert isinstance(request.signature_hash_algorithm, hashes.SHA1) public_key = request.public_key() assert isinstance(public_key, rsa.RSAPublicKey) @@ -359,9 +368,13 @@ class TestRSACertificate(object): x509.NameAttribute(x509.OID_COMMON_NAME, 'cryptography.io'), ] - def test_invalid_certificate_request_pem(self, backend): + @pytest.mark.parametrize( + "loader_func", + [x509.load_pem_x509_csr, x509.load_der_x509_csr] + ) + def test_invalid_certificate_request(self, loader_func, backend): with pytest.raises(ValueError): - x509.load_pem_x509_csr(b"notacsr", backend) + loader_func(b"notacsr", backend) def test_unsupported_signature_hash_algorithm_request(self, backend): request = _load_cert( @@ -424,12 +437,21 @@ class TestDSACertificate(object): "822ff5d234e073b901cf5941f58e1f538e71d40d", 16 ) - def test_load_dsa_request(self, backend): - request = _load_cert( - os.path.join("x509", "requests", "dsa_sha1.pem"), - x509.load_pem_x509_csr, - backend - ) + @pytest.mark.parametrize( + ("path", "loader_func"), + [ + [ + os.path.join("x509", "requests", "dsa_sha1.pem"), + x509.load_pem_x509_csr + ], + [ + os.path.join("x509", "requests", "dsa_sha1.der"), + x509.load_der_x509_csr + ], + ] + ) + def test_load_dsa_request(self, path, loader_func, backend): + request = _load_cert(path, loader_func, backend) assert isinstance(request.signature_hash_algorithm, hashes.SHA1) public_key = request.public_key() assert isinstance(public_key, dsa.DSAPublicKey) @@ -479,13 +501,22 @@ class TestECDSACertificate(object): with pytest.raises(NotImplementedError): cert.public_key() - def test_load_ecdsa_certificate_request(self, backend): + @pytest.mark.parametrize( + ("path", "loader_func"), + [ + [ + os.path.join("x509", "requests", "ec_sha256.pem"), + x509.load_pem_x509_csr + ], + [ + os.path.join("x509", "requests", "ec_sha256.der"), + x509.load_der_x509_csr + ], + ] + ) + def test_load_ecdsa_certificate_request(self, path, loader_func, backend): _skip_curve_unsupported(backend, ec.SECP384R1()) - request = _load_cert( - os.path.join("x509", "requests", "ec_sha256.pem"), - x509.load_pem_x509_csr, - backend - ) + request = _load_cert(path, loader_func, backend) assert isinstance(request.signature_hash_algorithm, hashes.SHA256) public_key = request.public_key() assert isinstance(public_key, ec.EllipticCurvePublicKey) |