From c6656af81d3b4440d0d1032fd82e64d717541d62 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 16 Jan 2019 19:08:12 -0600 Subject: add support for byteslike password/data to load_{pem,der}_private_key (#4693) * add support for byteslike password/data to load_{pem,der}_private_key * pypy 5.4 can't do memoryview from_buffer --- .../hazmat/primitives/asymmetric/serialization.rst | 12 ++++-- .../hazmat/backends/openssl/backend.py | 4 +- tests/hazmat/primitives/test_serialization.py | 49 ++++++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 85aeced3..4c2e5f2a 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -133,10 +133,12 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END Deserialize a private key from PEM encoded data to one of the supported asymmetric private key types. - :param bytes data: The PEM encoded key data. + :param data: The PEM encoded key data. + :type data: :term:`bytes-like` - :param bytes password: The password to use to decrypt the data. Should + :param password: The password to use to decrypt the data. Should be ``None`` if the private key is not encrypted. + :type data: :term:`bytes-like` :param backend: An instance of :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`. @@ -241,10 +243,12 @@ the rest. Deserialize a private key from DER encoded data to one of the supported asymmetric private key types. - :param bytes data: The DER encoded key data. + :param data: The DER encoded key data. + :type data: :term:`bytes-like` - :param bytes password: The password to use to decrypt the data. Should + :param password: The password to use to decrypt the data. Should be ``None`` if the private key is not encrypted. + :type password: :term:`bytes-like` :param backend: An instance of :class:`~cryptography.hazmat.backends.interfaces.DERSerializationBackend`. diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 3ab34c17..fd6057f8 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1224,11 +1224,9 @@ class Backend(object): def _load_key(self, openssl_read_func, convert_func, data, password): mem_bio = self._bytes_to_bio(data) - if password is not None: - utils._check_byteslike("password", password) - userdata = self._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") if password is not None: + utils._check_byteslike("password", password) password_ptr = self._ffi.from_buffer(password) userdata.password = password_ptr userdata.length = len(password) diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 2bc49078..5dd72489 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -34,6 +34,55 @@ from .utils import ( from ...utils import raises_unsupported_algorithm +class TestBufferProtocolSerialization(object): + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.parametrize( + ("key_path", "password"), + [ + (["DER_Serialization", "enc-rsa-pkcs8.der"], bytearray(b"foobar")), + (["DER_Serialization", "enc2-rsa-pkcs8.der"], bytearray(b"baz")), + (["DER_Serialization", "unenc-rsa-pkcs8.der"], None), + (["DER_Serialization", "testrsa.der"], None), + ] + ) + def test_load_der_rsa_private_key(self, key_path, password, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", *key_path), + lambda derfile: derfile.read(), mode="rb" + ) + key = load_der_private_key(bytearray(data), password, backend) + assert key + assert isinstance(key, rsa.RSAPrivateKey) + _check_rsa_private_numbers(key.private_numbers()) + + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.parametrize( + ("key_path", "password"), + [ + ( + ["PEM_Serialization", "rsa_private_key.pem"], + bytearray(b"123456") + ), + (["PKCS8", "unenc-rsa-pkcs8.pem"], None), + (["PKCS8", "enc-rsa-pkcs8.pem"], bytearray(b"foobar")), + (["PKCS8", "enc2-rsa-pkcs8.pem"], bytearray(b"baz")), + ( + ["Traditional_OpenSSL_Serialization", "key1.pem"], + bytearray(b"123456") + ), + ] + ) + def test_load_pem_rsa_private_key(self, key_path, password, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", *key_path), + lambda pemfile: pemfile.read(), mode="rb" + ) + key = load_pem_private_key(bytearray(data), password, backend) + assert key + assert isinstance(key, rsa.RSAPrivateKey) + _check_rsa_private_numbers(key.private_numbers()) + + @pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestDERSerialization(object): @pytest.mark.requires_backend_interface(interface=RSABackend) -- cgit v1.2.3