aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py39
-rw-r--r--cryptography/hazmat/backends/openssl/ec.py35
-rw-r--r--cryptography/hazmat/primitives/interfaces.py18
-rw-r--r--docs/hazmat/primitives/interfaces.rst36
-rw-r--r--tests/hazmat/primitives/test_ec.py36
5 files changed, 147 insertions, 17 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index d0f69371..582623f5 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -1103,30 +1103,19 @@ class Backend(object):
finally:
self._lib.BN_CTX_end(bn_ctx)
- def _ec_key_set_public_key_affine_coordinates(self, ctx, x, y):
+ def _ec_key_determine_group_get_set_funcs(self, ctx):
"""
- This is a port of EC_KEY_set_public_key_affine_coordinates that was
- added in 1.0.1.
-
- Sets the public key point in the EC_KEY context to the affine x and y
- values.
+ Given an EC_KEY determine the group and what methods are required to
+ get/set point coordinates.
"""
-
assert ctx != self._ffi.NULL
- bn_x = self._int_to_bn(x)
- bn_y = self._int_to_bn(y)
-
nid_two_field = self._lib.OBJ_sn2nid(b"characteristic-two-field")
assert nid_two_field != self._lib.NID_undef
group = self._lib.EC_KEY_get0_group(ctx)
assert group != self._ffi.NULL
- point = self._lib.EC_POINT_new(group)
- assert point != self._ffi.NULL
- point = self._ffi.gc(point, self._lib.EC_POINT_free)
-
method = self._lib.EC_GROUP_method_of(group)
assert method != self._ffi.NULL
@@ -1142,6 +1131,28 @@ class Backend(object):
assert set_func and get_func
+ return set_func, get_func, group
+
+ def _ec_key_set_public_key_affine_coordinates(self, ctx, x, y):
+ """
+ This is a port of EC_KEY_set_public_key_affine_coordinates that was
+ added in 1.0.1.
+
+ Sets the public key point in the EC_KEY context to the affine x and y
+ values.
+ """
+
+ bn_x = self._int_to_bn(x)
+ bn_y = self._int_to_bn(y)
+
+ set_func, get_func, group = (
+ self._ec_key_determine_group_get_set_funcs(ctx)
+ )
+
+ point = self._lib.EC_POINT_new(group)
+ assert point != self._ffi.NULL
+ point = self._ffi.gc(point, self._lib.EC_POINT_free)
+
with self._tmp_bn_ctx() as bn_ctx:
check_x = self._lib.BN_CTX_get(bn_ctx)
check_y = self._lib.BN_CTX_get(bn_ctx)
diff --git a/cryptography/hazmat/backends/openssl/ec.py b/cryptography/hazmat/backends/openssl/ec.py
index 611dba2c..369b185b 100644
--- a/cryptography/hazmat/backends/openssl/ec.py
+++ b/cryptography/hazmat/backends/openssl/ec.py
@@ -129,7 +129,7 @@ class _ECDSAVerificationContext(object):
return True
-@utils.register_interface(interfaces.EllipticCurvePrivateKey)
+@utils.register_interface(interfaces.EllipticCurvePrivateKeyWithNumbers)
class _EllipticCurvePrivateKey(object):
def __init__(self, backend, ec_key_cdata, curve):
self._backend = backend
@@ -172,8 +172,16 @@ class _EllipticCurvePrivateKey(object):
self._backend, public_ec_key, self._curve
)
+ def private_numbers(self):
+ bn = self._backend._lib.EC_KEY_get0_private_key(self._ec_key)
+ private_value = self._backend._bn_to_int(bn)
+ return ec.EllipticCurvePrivateNumbers(
+ private_value=private_value,
+ public_numbers=self.public_key().public_numbers()
+ )
+
-@utils.register_interface(interfaces.EllipticCurvePublicKey)
+@utils.register_interface(interfaces.EllipticCurvePublicKeyWithNumbers)
class _EllipticCurvePublicKey(object):
def __init__(self, backend, ec_key_cdata, curve):
self._backend = backend
@@ -193,3 +201,26 @@ class _EllipticCurvePublicKey(object):
raise UnsupportedAlgorithm(
"Unsupported elliptic curve signature algorithm.",
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def public_numbers(self):
+ set_func, get_func, group = (
+ self._backend._ec_key_determine_group_get_set_funcs(self._ec_key)
+ )
+ point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
+ assert point != self._backend._ffi.NULL
+
+ with self._backend._tmp_bn_ctx() as bn_ctx:
+ bn_x = self._backend._lib.BN_CTX_get(bn_ctx)
+ bn_y = self._backend._lib.BN_CTX_get(bn_ctx)
+
+ res = get_func(group, point, bn_x, bn_y, bn_ctx)
+ assert res == 1
+
+ x = self._backend._bn_to_int(bn_x)
+ y = self._backend._bn_to_int(bn_y)
+
+ return ec.EllipticCurvePublicNumbers(
+ x=x,
+ y=y,
+ curve=self._curve
+ )
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index d60f9e0e..c7ad0cf8 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -444,6 +444,15 @@ class EllipticCurvePrivateKey(object):
@six.add_metaclass(abc.ABCMeta)
+class EllipticCurvePrivateKeyWithNumbers(EllipticCurvePrivateKey):
+ @abc.abstractmethod
+ def private_numbers(self):
+ """
+ Returns an EllipticCurvePrivateNumbers.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
class EllipticCurvePublicKey(object):
@abc.abstractmethod
def verifier(self, signature, signature_algorithm):
@@ -456,3 +465,12 @@ class EllipticCurvePublicKey(object):
"""
The EllipticCurve that this key is on.
"""
+
+
+@six.add_metaclass(abc.ABCMeta)
+class EllipticCurvePublicKeyWithNumbers(EllipticCurvePublicKey):
+ @abc.abstractmethod
+ def public_numbers(self):
+ """
+ Returns an EllipticCurvePublicNumbers.
+ """
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index ac47c1e1..2d594c8d 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -416,7 +416,7 @@ DSA
Extends :class:`DSAPublicKey`.
- .. method:: private_numbers()
+ .. method:: public_numbers()
Create a
:class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
@@ -492,6 +492,23 @@ Elliptic Curve
The EllipticCurvePublicKey object for this private key.
+.. class:: EllipticCurvePrivateKeyWithNumbers
+
+ .. versionadded:: 0.6
+
+ Extends :class:`EllipticCurvePrivateKey`.
+
+ .. method:: private_numbers()
+
+ Create a
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateNumbers`
+ object.
+
+ :returns: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateNumbers`
+ instance.
+
+
.. class:: EllipticCurvePublicKey
.. versionadded:: 0.5
@@ -518,6 +535,23 @@ Elliptic Curve
The elliptic curve for this key.
+.. class:: EllipticCurvePublicKeyWithNumbers
+
+ .. versionadded:: 0.6
+
+ Extends :class:`EllipticCurvePublicKey`.
+
+ .. method:: public_numbers()
+
+ Create a
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`
+ object.
+
+ :returns: An
+ :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`
+ instance.
+
+
Hash algorithms
---------------
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 35505820..c53a0cb6 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -139,6 +139,42 @@ def test_ec_numbers():
@pytest.mark.elliptic
+class TestECWithNumbers(object):
+ @pytest.mark.parametrize(
+ ("vector", "hash_type"),
+ list(itertools.product(
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "ECDSA", "FIPS_186-3", "KeyPair.rsp"),
+ load_fips_ecdsa_key_pair_vectors
+ ),
+ _HASH_TYPES.values()
+ ))
+ )
+ def test_with_numbers(self, backend, vector, hash_type):
+ curve_type = ec._CURVE_TYPES[vector['curve']]
+
+ _skip_ecdsa_vector(backend, curve_type, hash_type)
+
+ key = ec.EllipticCurvePrivateNumbers(
+ vector['d'],
+ ec.EllipticCurvePublicNumbers(
+ vector['x'],
+ vector['y'],
+ curve_type()
+ )
+ ).private_key(backend)
+ assert key
+
+ if isinstance(key, interfaces.EllipticCurvePrivateKeyWithNumbers):
+ priv_num = key.private_numbers()
+ assert priv_num.private_value == vector['d']
+ assert priv_num.public_numbers.x == vector['x']
+ assert priv_num.public_numbers.y == vector['y']
+ assert curve_type().name == priv_num.public_numbers.curve.name
+
+
+@pytest.mark.elliptic
class TestECDSAVectors(object):
@pytest.mark.parametrize(
("vector", "hash_type"),