aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormichael-hart <michael.hart1994@gmail.com>2014-09-23 23:10:32 +0100
committermichael-hart <michael.hart1994@gmail.com>2014-09-25 22:37:08 +0100
commita3204baf9bcfd2288d049c4f27e75c535b4397ed (patch)
treeedd261144a3b6950618d9d5156df33c61796f9f4
parentd31446085ba34f5bacf2631c8adab1ab491bee2e (diff)
downloadcryptography-a3204baf9bcfd2288d049c4f27e75c535b4397ed.tar.gz
cryptography-a3204baf9bcfd2288d049c4f27e75c535b4397ed.tar.bz2
cryptography-a3204baf9bcfd2288d049c4f27e75c535b4397ed.zip
Part 1 of rebase, with corrections for pep8
-rw-r--r--cryptography/hazmat/backends/interfaces.py6
-rw-r--r--cryptography/hazmat/backends/multibackend.py11
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py29
-rw-r--r--cryptography/hazmat/primitives/serialization.py4
-rw-r--r--docs/hazmat/primitives/asymmetric/serialization.rst21
-rw-r--r--tests/hazmat/primitives/test_serialization.py36
-rw-r--r--vectors/cryptography_vectors/asymmetric/PEM_Serialization/README.txt4
7 files changed, 106 insertions, 5 deletions
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index 3761e254..187d7fc5 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -281,6 +281,12 @@ class PEMSerializationBackend(object):
if the data is encrypted.
"""
+ @abc.abstractmethod
+ def load_pem_public_key(self, data, password):
+ """
+ Loads a public key from PEM encoded data.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class TraditionalOpenSSLSerializationBackend(object):
diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py
index 221f1a1e..925e762d 100644
--- a/cryptography/hazmat/backends/multibackend.py
+++ b/cryptography/hazmat/backends/multibackend.py
@@ -187,14 +187,12 @@ class MultiBackend(object):
def load_rsa_private_numbers(self, numbers):
for b in self._filtered_backends(RSABackend):
return b.load_rsa_private_numbers(numbers)
-
raise UnsupportedAlgorithm("RSA is not supported by the backend",
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
def load_rsa_public_numbers(self, numbers):
for b in self._filtered_backends(RSABackend):
return b.load_rsa_public_numbers(numbers)
-
raise UnsupportedAlgorithm("RSA is not supported by the backend",
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
@@ -329,6 +327,15 @@ class MultiBackend(object):
_Reasons.UNSUPPORTED_SERIALIZATION
)
+ def load_pem_public_key(self, data):
+ for b in self._filtered_backends(PEMSerializationBackend):
+ return b.load_pem_public_key(data)
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this key serialization.",
+ _Reasons.UNSUPPORTED_SERIALIZATION
+ )
+
def load_pkcs8_pem_private_key(self, data, password):
for b in self._filtered_backends(PKCS8SerializationBackend):
return b.load_pkcs8_pem_private_key(data, password)
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index cb988ac9..dd50fd3b 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -483,6 +483,27 @@ class Backend(object):
else:
raise UnsupportedAlgorithm("Unsupported key type.")
+ def _evp_pkey_to_public_key(self, evp_pkey):
+ """
+ Return the appropriate type of PublicKey given an evp_pkey cdata
+ pointer.
+ """
+
+ type = evp_pkey.type
+
+ if type == self._lib.EVP_PKEY_RSA:
+ rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey)
+ assert rsa_cdata != self._ffi.NULL
+ rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+ return _RSAPublicKey(self, rsa_cdata)
+ elif type == self._lib.EVP_PKEY_DSA:
+ dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey)
+ assert dsa_cdata != self._ffi.NULL
+ dsa_cdata = self._ffi.gc(dsa_cdata, self._lib.DSA_free)
+ return _DSAPublicKey(self, dsa_cdata)
+ else:
+ raise UnsupportedAlgorithm("Unsupported key type.")
+
def _pem_password_cb(self, password):
"""
Generate a pem_password_cb function pointer that copied the password to
@@ -787,6 +808,14 @@ class Backend(object):
password,
)
+ def load_pem_public_key(self, data):
+ return self._load_key(
+ self._lib.PEM_read_bio_PUBKEY,
+ self._evp_pkey_to_public_key,
+ data,
+ None,
+ )
+
def load_traditional_openssl_pem_private_key(self, data, password):
warnings.warn(
"load_traditional_openssl_pem_private_key is deprecated and will "
diff --git a/cryptography/hazmat/primitives/serialization.py b/cryptography/hazmat/primitives/serialization.py
index cf1ca8ec..0fb560e0 100644
--- a/cryptography/hazmat/primitives/serialization.py
+++ b/cryptography/hazmat/primitives/serialization.py
@@ -44,3 +44,7 @@ def load_pem_pkcs8_private_key(data, password, backend):
def load_pem_private_key(data, password, backend):
return backend.load_pem_private_key(data, password)
+
+
+def load_pem_public_key(data, backend):
+ return backend.load_pem_public_key(data)
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index 7a953d9b..18b89c44 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -92,6 +92,27 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END
is not supported by the backend or if the key is encrypted with a
symmetric cipher that is not supported by the backend.
+.. function:: load_pem_public_key(data, backend):
+
+ .. versionadded:: 0.6
+
+ Deserialize a public key from PEM encoded data to one of the supported
+ asymmetric public key types.
+
+ :param bytes data: The PEM encoded key data.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.PEMSerializationBackend`
+ provider.
+
+ :returns: A new instance of a public key.
+
+ :raises ValueError: If the PEM data could not be decrypted or if its
+ structure could not be decoded successfully.
+
+ :raises UnsupportedAlgorithm: If the serialized key is of a type that
+ is not supported by the backend.
+
PKCS #8 Format
~~~~~~~~~~~~~~
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
index d369e8f4..4bc7e811 100644
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -24,6 +24,7 @@ from cryptography.hazmat.primitives import interfaces
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import (
load_pem_pkcs8_private_key, load_pem_private_key,
+ load_pem_public_key,
load_pem_traditional_openssl_private_key
)
@@ -38,7 +39,7 @@ 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"),
+ "asymmetric", "PEM_Serialization", "rsa_private_key.pem"),
lambda pemfile: load_pem_private_key(
pemfile.read().encode(), b"123456", backend
)
@@ -49,6 +50,17 @@ class TestPEMSerialization(object):
if isinstance(key, interfaces.RSAPrivateKeyWithNumbers):
_check_rsa_private_numbers(key.private_numbers())
+ def test_load_dsa_private_key(self, backend):
+ key = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "dsa_private_key.pem"),
+ lambda pemfile: load_pem_private_key(
+ pemfile.read().encode(), b"123456", backend
+ )
+ )
+ assert key
+ assert isinstance(key, interfaces.DSAPrivateKey)
+
@pytest.mark.parametrize(
("key_file", "password"),
[
@@ -70,6 +82,28 @@ class TestPEMSerialization(object):
assert key
assert isinstance(key, interfaces.EllipticCurvePrivateKey)
+ def test_load_pem_rsa_public_key(self, backend):
+ key = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "rsa_public_key.pem"),
+ lambda pemfile: load_pem_public_key(
+ pemfile.read().encode(), backend
+ )
+ )
+ assert key
+ assert isinstance(key, interfaces.RSAPublicKey)
+
+ def test_load_pem_dsa_public_key(self, backend):
+ key = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "dsa_public_key.pem"),
+ lambda pemfile: load_pem_public_key(
+ pemfile.read().encode(), backend
+ )
+ )
+ assert key
+ assert isinstance(key, interfaces.DSAPublicKey)
+
@pytest.mark.traditional_openssl_serialization
class TestTraditionalOpenSSLSerialization(object):
diff --git a/vectors/cryptography_vectors/asymmetric/PEM_Serialization/README.txt b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/README.txt
index 6963d2b5..865fbc9e 100644
--- a/vectors/cryptography_vectors/asymmetric/PEM_Serialization/README.txt
+++ b/vectors/cryptography_vectors/asymmetric/PEM_Serialization/README.txt
@@ -3,13 +3,13 @@ Example test files for PEM Serialization Backend tests
Contains
1. ec_private_key.pem - Contains an Elliptic Curve key generated using OpenSSL, from the curve secp256r1.
-2. ec_private_key_encrypted.pem - Contains the same Elliptic Curve key as ec_private_key.pem, except that
+2. ec_private_key_encrypted.pem - Contains the same Elliptic Curve key as ec_private_key.pem, except that
it is encrypted with AES-256 with the password "123456".
3. ec_public_key.pem - Contains the public key corresponding to ec_private_key.pem, generated using OpenSSL.
4. rsa_private_key.pem - Contains an RSA 2048 bit key generated using OpenSSL, protected by the secret
"123456" with DES3 encryption.
5. rsa_public_key.pem - Contains an RSA 2048 bit public generated using OpenSSL from rsa_private_key.pem.
6. dsaparam.pem - Contains 2048-bit DSA parameters generated using OpenSSL; contains no keys.
-7. dsa_private_key.pem - Contains a DSA 2048 bit key generated using OpenSSL from the parameters in
+7. dsa_private_key.pem - Contains a DSA 2048 bit key generated using OpenSSL from the parameters in
dsaparam.pem, protected by the secret "123456" with DES3 encryption.
8. dsa_public_key.pem - Contains a DSA 2048 bit key generated using OpenSSL from dsa_private_key.pem. \ No newline at end of file