diff options
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 14 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/serialization.py | 22 | ||||
-rw-r--r-- | docs/hazmat/primitives/asymmetric/serialization.rst | 45 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_serialization.py | 24 |
4 files changed, 93 insertions, 12 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 01e61283..333bef0a 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -25,7 +25,8 @@ from cryptography.exceptions import ( ) from cryptography.hazmat.backends.interfaces import ( CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend, - HashBackend, PBKDF2HMACBackend, PKCS8SerializationBackend, RSABackend, + HashBackend, PBKDF2HMACBackend, PEMSerializationBackend, + PKCS8SerializationBackend, RSABackend, TraditionalOpenSSLSerializationBackend ) from cryptography.hazmat.backends.openssl.ciphers import ( @@ -74,6 +75,7 @@ _OpenSSLError = collections.namedtuple("_OpenSSLError", @utils.register_interface(PKCS8SerializationBackend) @utils.register_interface(RSABackend) @utils.register_interface(TraditionalOpenSSLSerializationBackend) +@utils.register_interface(PEMSerializationBackend) class Backend(object): """ OpenSSL API binding interfaces. @@ -770,12 +772,7 @@ class Backend(object): def create_cmac_ctx(self, algorithm): return _CMACContext(self, algorithm) - def load_traditional_openssl_pem_private_key(self, data, password): - # OpenSSLs API for loading PKCS#8 certs can also load the traditional - # format so we just use that for both of them. - return self.load_pkcs8_pem_private_key(data, password) - - def load_pkcs8_pem_private_key(self, data, password): + def load_pem_private_key(self, data, password): return self._load_key( self._lib.PEM_read_bio_PrivateKey, self._evp_pkey_to_private_key, @@ -783,6 +780,9 @@ class Backend(object): password, ) + load_traditional_openssl_pem_private_key = load_pkcs8_pem_private_key = \ + load_pem_private_key + def _load_key(self, openssl_read_func, convert_func, data, password): mem_bio = self._bytes_to_bio(data) diff --git a/cryptography/hazmat/primitives/serialization.py b/cryptography/hazmat/primitives/serialization.py index 55b8640e..cf1ca8ec 100644 --- a/cryptography/hazmat/primitives/serialization.py +++ b/cryptography/hazmat/primitives/serialization.py @@ -13,12 +13,34 @@ from __future__ import absolute_import, division, print_function +import warnings + +from cryptography import utils + def load_pem_traditional_openssl_private_key(data, password, backend): + warnings.warn( + "load_pem_traditional_openssl_private_key is deprecated and will be " + "removed in a future version, use load_pem_private_key instead.", + utils.DeprecatedIn06, + stacklevel=2 + ) + return backend.load_traditional_openssl_pem_private_key( data, password ) def load_pem_pkcs8_private_key(data, password, backend): + warnings.warn( + "load_pem_pkcs8_private_key is deprecated and will be removed in a " + "future version, use load_pem_private_key instead.", + utils.DeprecatedIn06, + stacklevel=2 + ) + return backend.load_pkcs8_pem_private_key(data, password) + + +def load_pem_private_key(data, password, backend): + return backend.load_pem_private_key(data, password) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 5438c249..e18f8c83 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -45,8 +45,8 @@ methods. >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import interfaces - >>> from cryptography.hazmat.primitives.serialization import load_pem_pkcs8_private_key - >>> key = load_pem_pkcs8_private_key(pem_data, password=None, backend=default_backend()) + >>> from cryptography.hazmat.primitives.serialization import load_pem_private_key + >>> key = load_pem_private_key(pem_data, password=None, backend=default_backend()) >>> if isinstance(key, interfaces.RSAPrivateKey): ... signature = sign_with_rsa_key(key, message) ... elif isinstance(key, interfaces.DSAPrivateKey): @@ -54,6 +54,43 @@ methods. ... else: ... raise TypeError +PEM +~~~ + +PEM is an encapsulation format, meaning keys in it can actually be any one of +several formats, however these are all self-identifying, so you don't need to +worry about this detail. PEM keys are recognizable because they all begin with +``-----BEGIN {format}-----`` and end with ``-----END {format}-----``. + +.. function:: load_pem_private_key(data, password, backend): + + .. versionadded:: 0.6 + + 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 bytes password: The password to use to decrypt the data. Should + be ``None`` if the private key is not encrypted. + + :param backend: A + :class:`~cryptography.hazmat.backends.interfaces.PKCS8SerializationBackend` + provider. + + :returns: A new instance of a private key. + + :raises ValueError: If the PEM data could not be decrypted or if its + structure could not be decoded successfully. + + :raises TypeError: If a ``password`` was given and the private key was + not encrypted. Or if the key was encrypted but no + password was supplied. + + :raises UnsupportedAlgorithm: If the serialized key is of a type that + is not supported by the backend or if the key is encrypted with a + symmetric cipher that is not supported by the backend. + PKCS #8 Format ~~~~~~~~~~~~~~ @@ -72,6 +109,8 @@ with ``-----BEGIN ENCRYPTED PRIVATE KEY-----`` if they have a password. Deserialize a private key from PEM encoded data to one of the supported asymmetric private key types. + This has been deprecated in favor of :func:`load_pem_private_key`. + :param bytes data: The PEM encoded key data. :param bytes password: The password to use to decrypt the data. Should @@ -111,6 +150,8 @@ KEY-----`` or ``-----BEGIN DSA PRIVATE KEY-----``. Deserialize a private key from PEM encoded data to one of the supported asymmetric private key types. + This has been deprecated in favor of :func:`load_pem_private_key`. + :param bytes data: The PEM encoded key data. :param bytes password: The password to use to decrypt the data. Should diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 30ac4f3d..e960878b 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -22,15 +22,33 @@ import pytest from cryptography.exceptions import _Reasons from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.serialization import ( - load_pem_pkcs8_private_key, load_pem_traditional_openssl_private_key + load_pem_private_key, load_pem_pkcs8_private_key, + load_pem_traditional_openssl_private_key ) from .utils import _check_rsa_private_numbers, load_vectors_from_file from ...utils import raises_unsupported_algorithm +@pytest.mark.pem_serialization +class TestPEMSerialization(object): + def test_load_pem_rsa_private_key(self, backend): + key = load_vectors_from_file( + os.path.join( + "asymmetric", "Traditional_OpenSSL_Serialization", "key1.pem"), + lambda pemfile: load_pem_private_key( + pemfile.read().encode(), b"123456", backend + ) + ) + + assert key + assert isinstance(key, interfaces.RSAPrivateKey) + if isinstance(key, interfaces.RSAPrivateKeyWithNumbers): + _check_rsa_private_numbers(key.private_numbers()) + + @pytest.mark.traditional_openssl_serialization -class TestTraditionalOpenSSLSerialisation(object): +class TestTraditionalOpenSSLSerialization(object): @pytest.mark.parametrize( ("key_file", "password"), [ @@ -252,7 +270,7 @@ class TestTraditionalOpenSSLSerialisation(object): @pytest.mark.pkcs8_serialization -class TestPKCS8Serialisation(object): +class TestPKCS8Serialization(object): @pytest.mark.parametrize( ("key_file", "password"), [ |