aboutsummaryrefslogtreecommitdiffstats
path: root/src/cryptography
diff options
context:
space:
mode:
authorOfek Lev <ofekmeister@gmail.com>2016-11-11 10:54:00 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2016-11-11 07:54:00 -0800
commitc816735f0e9250328e4a697c8dfb23f0aa1e584b (patch)
tree2e95196a00131e26f078abee5516926dc72797a3 /src/cryptography
parent01ee6f5e391eee76e6cd3062de8fc84851bd06e3 (diff)
downloadcryptography-c816735f0e9250328e4a697c8dfb23f0aa1e584b.tar.gz
cryptography-c816735f0e9250328e4a697c8dfb23f0aa1e584b.tar.bz2
cryptography-c816735f0e9250328e4a697c8dfb23f0aa1e584b.zip
add ec.private_key_from_secret_and_curve (#3225)
* finish https://github.com/pyca/cryptography/pull/1973 * change API & add test Function will now return an instance of EllipticCurvePrivateKey, as that is the users' ultimate goal anyway. * fix test * improve coverage * complete coverage * final fix * centos fix * retry * cleanup asserts * use openssl_assert * skip unsupported platforms * change API name to derive_private_key * change version added * improve description of `secret` param * separate successful and failure test cases * simplify successful case * add docs for derive_elliptic_curve_public_point * add period
Diffstat (limited to 'src/cryptography')
-rw-r--r--src/cryptography/hazmat/backends/interfaces.py6
-rw-r--r--src/cryptography/hazmat/backends/multibackend.py13
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py34
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py13
4 files changed, 66 insertions, 0 deletions
diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py
index 9a1d704a..ad4a4364 100644
--- a/src/cryptography/hazmat/backends/interfaces.py
+++ b/src/cryptography/hazmat/backends/interfaces.py
@@ -221,6 +221,12 @@ class EllipticCurveBackend(object):
Returns whether the exchange algorithm is supported by this backend.
"""
+ @abc.abstractmethod
+ def derive_elliptic_curve_public_point(self, private_value, curve):
+ """
+ Compute the public key point (x, y) given the private value and curve.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class PEMSerializationBackend(object):
diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py
index deca020e..ab9127f7 100644
--- a/src/cryptography/hazmat/backends/multibackend.py
+++ b/src/cryptography/hazmat/backends/multibackend.py
@@ -279,6 +279,19 @@ class MultiBackend(object):
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
)
+ def derive_elliptic_curve_public_point(self, private_value, curve):
+ for b in self._filtered_backends(EllipticCurveBackend):
+ try:
+ return b.derive_elliptic_curve_public_point(private_value,
+ curve)
+ except UnsupportedAlgorithm:
+ continue
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this elliptic curve.",
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ )
+
def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
return any(
b.elliptic_curve_exchange_algorithm_supported(algorithm, curve)
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 41e7e773..79914293 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -1386,6 +1386,40 @@ class Backend(object):
return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey)
+ def derive_elliptic_curve_public_point(self, private_value, curve):
+ curve_nid = self._elliptic_curve_to_nid(curve)
+
+ ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid)
+ self.openssl_assert(ec_cdata != self._ffi.NULL)
+ ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
+
+ set_func, get_func, group = (
+ self._ec_key_determine_group_get_set_funcs(ec_cdata)
+ )
+
+ point = self._lib.EC_POINT_new(group)
+ self.openssl_assert(point != self._ffi.NULL)
+ point = self._ffi.gc(point, self._lib.EC_POINT_free)
+
+ value = self._int_to_bn(private_value)
+ value = self._ffi.gc(value, self._lib.BN_free)
+
+ with self._tmp_bn_ctx() as bn_ctx:
+ res = self._lib.EC_POINT_mul(group, point, value, self._ffi.NULL,
+ self._ffi.NULL, bn_ctx)
+ self.openssl_assert(res == 1)
+
+ bn_x = self._lib.BN_CTX_get(bn_ctx)
+ bn_y = self._lib.BN_CTX_get(bn_ctx)
+
+ res = get_func(group, point, bn_x, bn_y, bn_ctx)
+ self.openssl_assert(res == 1)
+
+ point_x = self._bn_to_int(bn_x)
+ point_y = self._bn_to_int(bn_y)
+
+ return point_x, point_y
+
def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
return (
self.elliptic_curve_supported(curve) and
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index 1c576c6d..1005ccd6 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -253,6 +253,19 @@ def generate_private_key(curve, backend):
return backend.generate_elliptic_curve_private_key(curve)
+def derive_private_key(secret, curve, backend):
+ if not isinstance(secret, six.integer_types):
+ raise TypeError("secret must be an integer type.")
+
+ if not isinstance(curve, EllipticCurve):
+ raise TypeError("curve must provide the EllipticCurve interface.")
+
+ x, y = backend.derive_elliptic_curve_public_point(secret, curve)
+ public_numbers = EllipticCurvePublicNumbers(x, y, curve)
+ private_numbers = EllipticCurvePrivateNumbers(secret, public_numbers)
+ return private_numbers.private_key(backend)
+
+
class EllipticCurvePublicNumbers(object):
def __init__(self, x, y, curve):
if (