aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst8
-rw-r--r--docs/hazmat/primitives/asymmetric/ec.rst30
-rw-r--r--docs/hazmat/primitives/asymmetric/serialization.rst8
-rw-r--r--src/cryptography/hazmat/backends/openssl/ec.py23
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py19
-rw-r--r--tests/hazmat/primitives/test_ec.py70
6 files changed, 153 insertions, 5 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 86628946..e45a4ae6 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -115,6 +115,14 @@ Changelog
:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization.public_bytes`
to
:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`.
+* Added
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`
+ and deprecated
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithNumbers`.
+* Added
+ :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization.public_bytes`
+ to
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKeyWithSerialization`.
0.7.2 - 2015-01-16
~~~~~~~~~~~~~~~~~~
diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst
index 256c1832..6c03d773 100644
--- a/docs/hazmat/primitives/asymmetric/ec.rst
+++ b/docs/hazmat/primitives/asymmetric/ec.rst
@@ -405,6 +405,36 @@ Key Interfaces
:returns: An :class:`EllipticCurvePublicNumbers` instance.
+.. class:: EllipticCurvePublicKeyWithSerialization
+
+ .. versionadded:: 0.6
+
+ Extends :class:`EllipticCurvePublicKey`.
+
+ .. method:: public_numbers()
+
+ Create a :class:`EllipticCurvePublicNumbers` object.
+
+ :returns: An :class:`EllipticCurvePublicNumbers` instance.
+
+ .. method:: public_bytes(encoding, format)
+
+ Allows serialization of the key to bytes. Encoding (
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or
+ :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and
+ format (
+ :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`)
+ are chosen to define the exact serialization.
+
+ :param encoding: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
+
+ :param format: A value from the
+ :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum.
+
+ :return bytes: Serialized key.
+
+
.. _`FIPS 186-3`: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
.. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
.. _`some concern`: https://crypto.stackexchange.com/questions/10263/should-we-trust-the-nist-recommended-ecc-parameters
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst
index fb8c93a4..e4b2d68b 100644
--- a/docs/hazmat/primitives/asymmetric/serialization.rst
+++ b/docs/hazmat/primitives/asymmetric/serialization.rst
@@ -315,7 +315,9 @@ Serialization Formats
An enumeration for public key formats. Used with the ``public_bytes``
method available on
- :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`
+ and
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.EllipticCurvePublicKeyWithSerialization`.
.. attribute:: SubjectPublicKeyInfo
@@ -341,7 +343,9 @@ Serialization Encodings
,
:class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization`
and
- :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`.
+ :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKeyWithSerialization`
+ as well as ``public_bytes`` on
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKeyWithSerialization`.
.. attribute:: PEM
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index 19d646e8..39b0a555 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -9,7 +9,7 @@ from cryptography.exceptions import (
InvalidSignature, UnsupportedAlgorithm, _Reasons
)
from cryptography.hazmat.backends.openssl.utils import _truncate_digest
-from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import (
AsymmetricSignatureContext, AsymmetricVerificationContext, ec
)
@@ -262,3 +262,24 @@ class _EllipticCurvePublicKey(object):
y=y,
curve=self._curve
)
+
+ def public_bytes(self, encoding, format):
+ if format is serialization.PublicFormat.PKCS1:
+ raise ValueError(
+ "EC public keys do not support PKCS1 serialization"
+ )
+
+ evp_pkey = self._backend._lib.EVP_PKEY_new()
+ assert evp_pkey != self._backend._ffi.NULL
+ evp_pkey = self._backend._ffi.gc(
+ evp_pkey, self._backend._lib.EVP_PKEY_free
+ )
+ res = self._backend._lib.EVP_PKEY_set1_EC_KEY(evp_pkey, self._ec_key)
+ assert res == 1
+ return self._backend._public_key_bytes(
+ encoding,
+ format,
+ None,
+ evp_pkey,
+ None
+ )
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index 52e14816..bf1705db 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -98,13 +98,30 @@ class EllipticCurvePublicKey(object):
@six.add_metaclass(abc.ABCMeta)
-class EllipticCurvePublicKeyWithNumbers(EllipticCurvePublicKey):
+class EllipticCurvePublicKeyWithSerialization(EllipticCurvePublicKey):
@abc.abstractmethod
def public_numbers(self):
"""
Returns an EllipticCurvePublicNumbers.
"""
+ @abc.abstractmethod
+ def public_bytes(self, encoding, format):
+ """
+ Returns the key serialized as bytes.
+ """
+
+
+EllipticCurvePublicKeyWithNumbers = utils.deprecated(
+ EllipticCurvePublicKeyWithSerialization,
+ __name__,
+ (
+ "The EllipticCurvePublicKeyWithNumbers interface has been renamed to "
+ "EllipticCurvePublicKeyWithSerialization"
+ ),
+ utils.DeprecatedIn08
+)
+
@utils.register_interface(EllipticCurve)
class SECT571R1(object):
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 77ee38b4..73201f8e 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -34,7 +34,12 @@ _HASH_TYPES = {
def _skip_if_no_serialization(key, backend):
- if not isinstance(key, ec.EllipticCurvePrivateKeyWithSerialization):
+ if not isinstance(
+ key, (
+ ec.EllipticCurvePrivateKeyWithSerialization,
+ ec.EllipticCurvePublicKeyWithSerialization
+ )
+ ):
pytest.skip(
"{0} does not support EC key serialization".format(backend)
)
@@ -548,3 +553,66 @@ class TestECSerialization(object):
serialization.PrivateFormat.TraditionalOpenSSL,
DummyKeyEncryption()
)
+
+
+@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):
+ key_bytes = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "ec_public_key.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_invalid_encoding(self, backend):
+ key = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "ec_public_key.pem"
+ ),
+ lambda pemfile: serialization.load_pem_public_key(
+ pemfile.read().encode(), backend
+ )
+ )
+ _skip_if_no_serialization(key, backend)
+ with pytest.raises(TypeError):
+ key.public_bytes(
+ "notencoding",
+ serialization.PublicFormat.SubjectPublicKeyInfo
+ )
+
+ def test_public_bytes_invalid_format(self, backend):
+ key = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "ec_public_key.pem"
+ ),
+ lambda pemfile: serialization.load_pem_public_key(
+ pemfile.read().encode(), backend
+ )
+ )
+ _skip_if_no_serialization(key, backend)
+ with pytest.raises(TypeError):
+ key.public_bytes(serialization.Encoding.PEM, "invalidformat")
+
+ def test_public_bytes_pkcs1_unsupported(self, backend):
+ key = load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "PEM_Serialization", "ec_public_key.pem"
+ ),
+ lambda pemfile: serialization.load_pem_public_key(
+ pemfile.read().encode(), backend
+ )
+ )
+ _skip_if_no_serialization(key, backend)
+ with pytest.raises(ValueError):
+ key.public_bytes(
+ serialization.Encoding.PEM, serialization.PublicFormat.PKCS1
+ )