diff options
author | Simo Sorce <simo@redhat.com> | 2015-04-30 14:06:47 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2015-10-17 11:58:07 -0400 |
commit | 9aaeee0dc62189204f38097c815a0913fabe006c (patch) | |
tree | 37621d2d6a20898d9665520a30ecb7a68c0db30e /src | |
parent | 7a0ed4a7e9443a0506ae5373a8e5cd1ce3539e97 (diff) | |
download | cryptography-9aaeee0dc62189204f38097c815a0913fabe006c.tar.gz cryptography-9aaeee0dc62189204f38097c815a0913fabe006c.tar.bz2 cryptography-9aaeee0dc62189204f38097c815a0913fabe006c.zip |
Add an Elliptic Curve Key Exchange Algorithm(ECDH)
The ECDH Key Exchange algorithm as standardized in NIST publication
800-56A Revision 2
Includes tests with vectors from NIST.
Signed-off-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/exceptions.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/interfaces.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/multibackend.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 20 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/ec.py | 25 |
5 files changed, 58 insertions, 0 deletions
diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py index 29be22be..3bf8a75b 100644 --- a/src/cryptography/exceptions.py +++ b/src/cryptography/exceptions.py @@ -20,6 +20,7 @@ class _Reasons(Enum): UNSUPPORTED_ELLIPTIC_CURVE = 6 UNSUPPORTED_SERIALIZATION = 7 UNSUPPORTED_X509 = 8 + UNSUPPORTED_EXCHANGE_ALGORITHM = 9 class UnsupportedAlgorithm(Exception): diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py index a43621a7..faa0b313 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -215,6 +215,12 @@ class EllipticCurveBackend(object): Return an EllipticCurvePublicKey provider using the given numbers. """ + @abc.abstractmethod + def elliptic_curve_exchange_algorithm_supported(self): + """ + Returns whether the exchange algorithm is supported by this backend. + """ + @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 9db32aa5..77a45ccd 100644 --- a/src/cryptography/hazmat/backends/multibackend.py +++ b/src/cryptography/hazmat/backends/multibackend.py @@ -271,6 +271,12 @@ class MultiBackend(object): _Reasons.UNSUPPORTED_ELLIPTIC_CURVE ) + def elliptic_curve_exchange_algorithm_supported(self): + return any( + b.elliptic_curve_exchange_algorithm_supported() + for b in self._filtered_backends(EllipticCurveBackend) + ) + def load_pem_private_key(self, data, password): for b in self._filtered_backends(PEMSerializationBackend): return b.load_pem_private_key(data, password) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 0d3b3dd4..d82f3834 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1671,6 +1671,26 @@ class Backend(object): return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + def elliptic_curve_exchange_algorithm_supported(self): + return (self._lib.Cryptography_HAS_EC == 1 and + self._lib.Cryptography_HAS_ECDH == 1) + + def ecdh_compute_key(self, private_key, peer_public_key): + pri_key = private_key._ec_key + pub_key = peer_public_key._ec_key + + group = self._lib.EC_KEY_get0_group(pri_key) + z_len = (self._lib.EC_GROUP_get_degree(group) + 7) // 8 + self.openssl_assert(z_len > 0) + z_buf = self._ffi.new("uint8_t[]", z_len) + peer_key = self._lib.EC_KEY_get0_public_key(pub_key) + + r = self._lib.ECDH_compute_key(z_buf, z_len, + peer_key, pri_key, + self._ffi.NULL) + self.openssl_assert(r > 0) + return self._ffi.buffer(z_buf)[:z_len] + def _ec_cdata_to_evp_pkey(self, ec_cdata): evp_pkey = self._lib.EVP_PKEY_new() self.openssl_assert(evp_pkey != self._ffi.NULL) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index f1d39eed..978a7c41 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -8,6 +8,7 @@ import abc import six +from cryptography import exceptions from cryptography import utils @@ -302,3 +303,27 @@ class EllipticCurvePrivateNumbers(object): def __ne__(self, other): return not self == other + + +class ECDH(object): + def __init__(self, private_key): + if not isinstance(private_key, EllipticCurvePrivateKey): + raise TypeError("Private Key must be a EllipticCurvePrivateKey") + self._private_key = private_key + self._backend = private_key._backend + if not self._backend.elliptic_curve_exchange_algorithm_supported(): + raise exceptions.UnsupportedAlgorithm( + "This backend does not support the ECDH algorithm.", + exceptions._Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + + private_key = utils.read_only_property("_private_key") + + def public_key(self): + return self._private_key.public_key() + + def compute_key(self, peer_public_key): + if not isinstance(peer_public_key, EllipticCurvePublicKey): + raise TypeError("Peer Public Key must be a EllipticCurvePublicKey") + return self._backend.ecdh_compute_key(self._private_key, + peer_public_key) |