diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2015-03-10 18:37:28 -0400 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2015-03-10 18:37:28 -0400 |
commit | b9287cac82a06fde4e474d88ee1989efd7144dff (patch) | |
tree | 1f6b2cdb7c0501ee8a9810b118fadf11f4bdb4b8 | |
parent | a66cb11b6abdd5a77f09c7bf8adbd424c701bb2b (diff) | |
parent | a2c48659274fb25a07fbffca3a74d11c6a49f131 (diff) | |
download | cryptography-b9287cac82a06fde4e474d88ee1989efd7144dff.tar.gz cryptography-b9287cac82a06fde4e474d88ee1989efd7144dff.tar.bz2 cryptography-b9287cac82a06fde4e474d88ee1989efd7144dff.zip |
Merge pull request #1741 from reaperhulk/serialize-der-public-keys
support DER serialization of public keys
-rw-r--r-- | CHANGELOG.rst | 7 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 21 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/dsa.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/ec.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/rsa.py | 1 | ||||
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 8 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_dsa.py | 29 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_ec.py | 31 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_rsa.py | 56 |
9 files changed, 101 insertions, 54 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4c866f65..9e19186a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,13 @@ Changelog .. note:: This version is not yet released and is under active development. +* Support :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER` + serialization of public keys using the ``public_bytes`` method of + :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`, + :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKeyWithSerialization`, + and + :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`. + 0.8 - 2015-03-08 ~~~~~~~~~~~~~~~~ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index f33aba95..25cce6e9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1184,8 +1184,7 @@ class Backend(object): assert res == 1 return self._read_mem_bio(bio) - def _public_key_bytes(self, encoding, format, pkcs1_write_func, evp_pkey, - cdata): + def _public_key_bytes(self, encoding, format, evp_pkey, cdata): if not isinstance(encoding, serialization.Encoding): raise TypeError("encoding must be an item from the Encoding enum") @@ -1194,15 +1193,21 @@ class Backend(object): "format must be an item from the PublicFormat enum" ) - # This is a temporary check until we land DER serialization. - if encoding is not serialization.Encoding.PEM: - raise ValueError("Only PEM encoding is supported by this backend") - if format is serialization.PublicFormat.SubjectPublicKeyInfo: - write_bio = self._lib.PEM_write_bio_PUBKEY + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_PUBKEY + elif encoding is serialization.Encoding.DER: + write_bio = self._lib.i2d_PUBKEY_bio + key = evp_pkey elif format is serialization.PublicFormat.PKCS1: - write_bio = pkcs1_write_func + # Only RSA is supported here. + assert evp_pkey.type == self._lib.EVP_PKEY_RSA + if encoding is serialization.Encoding.PEM: + write_bio = self._lib.PEM_write_bio_RSAPublicKey + elif encoding is serialization.Encoding.DER: + write_bio = self._lib.i2d_RSAPublicKey_bio + key = cdata bio = self._create_mem_bio() diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index 0089f58c..4e9ab3df 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -225,7 +225,6 @@ class _DSAPublicKey(object): return self._backend._public_key_bytes( encoding, format, - None, evp_pkey, None ) diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index 39b0a555..76c529db 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -279,7 +279,6 @@ class _EllipticCurvePublicKey(object): return self._backend._public_key_bytes( encoding, format, - None, evp_pkey, None ) diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 25168c2f..8aafa8a7 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -609,7 +609,6 @@ class _RSAPublicKey(object): return self._backend._public_key_bytes( encoding, format, - self._backend._lib.PEM_write_bio_RSAPublicKey, self._evp_pkey, self._rsa_cdata ) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index ba0a2ba3..cfdc06b4 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -516,11 +516,3 @@ class TestRSAPEMSerialization(object): serialization.PrivateFormat.PKCS8, serialization.NoEncryption() ) - - def test_unsupported_public_key_encoding(self): - key = RSA_KEY_2048.private_key(backend).public_key() - with pytest.raises(ValueError): - key.public_bytes( - serialization.Encoding.DER, - serialization.PublicFormat.SubjectPublicKeyInfo - ) diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index bbafbc6c..5f53c36c 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -944,16 +944,33 @@ class TestDSASerialization(object): @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestDSAPEMPublicKeySerialization(object): - def test_public_bytes_unencrypted_pem(self, backend): + @pytest.mark.parametrize( + ("key_path", "loader_func", "encoding"), + [ + ( + os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"), + serialization.load_pem_public_key, + serialization.Encoding.PEM, + ), ( + os.path.join( + "asymmetric", + "DER_Serialization", + "unenc-dsa-pkcs8.pub.der" + ), + serialization.load_der_public_key, + serialization.Encoding.DER, + ) + ] + ) + def test_public_bytes_match(self, key_path, loader_func, encoding, + backend): key_bytes = load_vectors_from_file( - os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pub.pem"), - lambda pemfile: pemfile.read().encode() + key_path, lambda pemfile: pemfile.read(), mode="rb" ) - key = serialization.load_pem_public_key(key_bytes, backend) + key = loader_func(key_bytes, backend) _skip_if_no_serialization(key, backend) serialized = key.public_bytes( - serialization.Encoding.PEM, - serialization.PublicFormat.SubjectPublicKeyInfo, + encoding, serialization.PublicFormat.SubjectPublicKeyInfo, ) assert serialized == key_bytes diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 23f9aff9..620a5d39 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -558,19 +558,34 @@ class TestECSerialization(object): @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestEllipticCurvePEMPublicKeySerialization(object): - def test_public_bytes_unencrypted_pem(self, backend): + @pytest.mark.parametrize( + ("key_path", "loader_func", "encoding"), + [ + ( + os.path.join( + "asymmetric", "PEM_Serialization", "ec_public_key.pem" + ), + serialization.load_pem_public_key, + serialization.Encoding.PEM, + ), ( + os.path.join( + "asymmetric", "DER_Serialization", "ec_public_key.der" + ), + serialization.load_der_public_key, + serialization.Encoding.DER, + ) + ] + ) + def test_public_bytes_match(self, key_path, loader_func, encoding, + backend): _skip_curve_unsupported(backend, ec.SECP256R1()) key_bytes = load_vectors_from_file( - os.path.join( - "asymmetric", "PEM_Serialization", "ec_public_key.pem" - ), - lambda pemfile: pemfile.read().encode() + key_path, lambda pemfile: pemfile.read(), mode="rb" ) - key = serialization.load_pem_public_key(key_bytes, backend) + key = loader_func(key_bytes, backend) _skip_if_no_serialization(key, backend) serialized = key.public_bytes( - serialization.Encoding.PEM, - serialization.PublicFormat.SubjectPublicKeyInfo, + encoding, serialization.PublicFormat.SubjectPublicKeyInfo, ) assert serialized == key_bytes diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index d79d9320..ab7cc3ad 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -1865,30 +1865,44 @@ class TestRSAPEMPrivateKeySerialization(object): @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestRSAPEMPublicKeySerialization(object): - def test_public_bytes_unencrypted_pem(self, backend): - key_bytes = load_vectors_from_file( - os.path.join("asymmetric", "PKCS8", "unenc-rsa-pkcs8.pub.pem"), - lambda pemfile: pemfile.read().encode() - ) - key = serialization.load_pem_public_key(key_bytes, backend) - _skip_if_no_serialization(key, backend) - serialized = key.public_bytes( - serialization.Encoding.PEM, - serialization.PublicFormat.SubjectPublicKeyInfo, - ) - assert serialized == key_bytes - - def test_public_bytes_pkcs1_unencrypted_pem(self, backend): + @pytest.mark.parametrize( + ("key_path", "loader_func", "encoding", "format"), + [ + ( + os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.pem"), + serialization.load_pem_public_key, + serialization.Encoding.PEM, + serialization.PublicFormat.PKCS1, + ), ( + os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.der"), + serialization.load_der_public_key, + serialization.Encoding.DER, + serialization.PublicFormat.PKCS1, + ), ( + os.path.join("asymmetric", "PKCS8", "unenc-rsa-pkcs8.pub.pem"), + serialization.load_pem_public_key, + serialization.Encoding.PEM, + serialization.PublicFormat.SubjectPublicKeyInfo, + ), ( + os.path.join( + "asymmetric", + "DER_Serialization", + "unenc-rsa-pkcs8.pub.der" + ), + serialization.load_der_public_key, + serialization.Encoding.DER, + serialization.PublicFormat.SubjectPublicKeyInfo, + ) + ] + ) + def test_public_bytes_match(self, key_path, loader_func, encoding, format, + backend): key_bytes = load_vectors_from_file( - os.path.join("asymmetric", "public", "PKCS1", "rsa.pub.pem"), - lambda pemfile: pemfile.read().encode() + key_path, lambda pemfile: pemfile.read(), mode="rb" ) - key = serialization.load_pem_public_key(key_bytes, backend) + key = loader_func(key_bytes, backend) _skip_if_no_serialization(key, backend) - serialized = key.public_bytes( - serialization.Encoding.PEM, - serialization.PublicFormat.PKCS1, - ) + serialized = key.public_bytes(encoding, format) assert serialized == key_bytes def test_public_bytes_invalid_encoding(self, backend): |