From 62ee71432cca0a8ba5bd52b8d29189d2fbd2880c Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 7 Jun 2014 18:35:52 +0100 Subject: Multibackend support for EC --- cryptography/hazmat/backends/multibackend.py | 57 +++++++++++++- docs/hazmat/primitives/asymmetric/ec.rst | 2 +- tests/hazmat/backends/test_multibackend.py | 107 ++++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 6 deletions(-) diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py index f3c79376..27ab0636 100644 --- a/cryptography/hazmat/backends/multibackend.py +++ b/cryptography/hazmat/backends/multibackend.py @@ -16,8 +16,8 @@ from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends.interfaces import ( - CMACBackend, CipherBackend, DSABackend, HMACBackend, HashBackend, - PBKDF2HMACBackend, RSABackend + CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend, + HashBackend, PBKDF2HMACBackend, RSABackend ) @@ -28,6 +28,7 @@ from cryptography.hazmat.backends.interfaces import ( @utils.register_interface(PBKDF2HMACBackend) @utils.register_interface(RSABackend) @utils.register_interface(DSABackend) +@utils.register_interface(EllipticCurveBackend) class MultiBackend(object): name = "multibackend" @@ -243,3 +244,55 @@ class MultiBackend(object): pass raise UnsupportedAlgorithm("This backend does not support CMAC.", _Reasons.UNSUPPORTED_CIPHER) + + def elliptic_curve_supported(self, curve): + return any( + b.elliptic_curve_supported(curve) + for b in self._filtered_backends(EllipticCurveBackend) + ) + + def elliptic_curve_signature_algorithm_supported( + self, signature_algorithm, curve + ): + return any( + b.elliptic_curve_signature_algorithm_supported( + signature_algorithm, curve + ) + for b in self._filtered_backends(EllipticCurveBackend) + ) + + def generate_elliptic_curve_private_key(self, curve): + for b in self._filtered_backends(EllipticCurveBackend): + try: + return b.generate_elliptic_curve_private_key(curve) + except UnsupportedAlgorithm: + continue + + raise UnsupportedAlgorithm( + "This backend does not support this elliptic curve.", + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) + + def elliptic_curve_private_key_from_numbers(self, numbers): + for b in self._filtered_backends(EllipticCurveBackend): + try: + return b.elliptic_curve_private_key_from_numbers(numbers) + except UnsupportedAlgorithm: + continue + + raise UnsupportedAlgorithm( + "This backend does not support this elliptic curve.", + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) + + def elliptic_curve_public_key_from_numbers(self, numbers): + for b in self._filtered_backends(EllipticCurveBackend): + try: + return b.elliptic_curve_public_key_from_numbers(numbers) + except UnsupportedAlgorithm: + continue + + raise UnsupportedAlgorithm( + "This backend does not support this elliptic curve.", + _Reasons.UNSUPPORTED_ELLIPTIC_CURVE + ) diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 798fbab1..646f979b 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -109,7 +109,7 @@ Elliptic Curve Signature Algorithms :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` provider. - .. code-block:: pycon + .. doctest:: >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import hashes diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index 93d58483..64dc062c 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -18,12 +18,12 @@ from cryptography.exceptions import ( UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import ( - CMACBackend, CipherBackend, DSABackend, HMACBackend, HashBackend, - PBKDF2HMACBackend, RSABackend + CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend, + HashBackend, PBKDF2HMACBackend, RSABackend ) from cryptography.hazmat.backends.multibackend import MultiBackend from cryptography.hazmat.primitives import cmac, hashes, hmac -from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives.asymmetric import ec, padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from ...utils import raises_unsupported_algorithm @@ -154,6 +154,41 @@ class DummyCMACBackend(object): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_CIPHER) +@utils.register_interface(EllipticCurveBackend) +class DummyEllipticCurveBackend(object): + def __init__(self, supported_curves): + self._curves = supported_curves + + def elliptic_curve_supported(self, curve): + return any( + isinstance(curve, curve_type) + for curve_type in self._curves + ) + + def elliptic_curve_signature_algorithm_supported( + self, signature_algorithm, curve + ): + return ( + isinstance(signature_algorithm, ec.ECDSA) and + any( + isinstance(curve, curve_type) + for curve_type in self._curves + ) + ) + + def generate_elliptic_curve_private_key(self, curve): + if not self.elliptic_curve_supported(curve): + raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) + + def elliptic_curve_private_key_from_numbers(self, numbers): + if not self.elliptic_curve_supported(numbers.public_numbers.curve): + raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) + + def elliptic_curve_public_key_from_numbers(self, numbers): + if not self.elliptic_curve_supported(numbers.curve): + raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) + + class TestMultiBackend(object): def test_ciphers(self): backend = MultiBackend([ @@ -361,3 +396,69 @@ class TestMultiBackend(object): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): cmac.CMAC(algorithms.TripleDES(fake_key), backend) + + def test_elliptic_curve(self): + backend = MultiBackend([ + DummyEllipticCurveBackend([ + ec.SECT283K1 + ]) + ]) + + assert backend.elliptic_curve_supported(ec.SECT283K1()) is True + + assert backend.elliptic_curve_signature_algorithm_supported( + ec.ECDSA(hashes.SHA256()), + ec.SECT283K1() + ) is True + + backend.generate_elliptic_curve_private_key(ec.SECT283K1()) + + backend.elliptic_curve_private_key_from_numbers( + ec.EllipticCurvePrivateNumbers( + 1, + ec.EllipticCurvePublicNumbers( + 2, + 3, + ec.SECT283K1() + ) + ) + ) + + backend.elliptic_curve_public_key_from_numbers( + ec.EllipticCurvePublicNumbers( + 2, + 3, + ec.SECT283K1() + ) + ) + + assert backend.elliptic_curve_supported(ec.SECT163K1()) is False + + assert backend.elliptic_curve_signature_algorithm_supported( + ec.ECDSA(hashes.SHA256()), + ec.SECT163K1() + ) is False + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): + backend.generate_elliptic_curve_private_key(ec.SECT163K1()) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): + backend.elliptic_curve_private_key_from_numbers( + ec.EllipticCurvePrivateNumbers( + 1, + ec.EllipticCurvePublicNumbers( + 2, + 3, + ec.SECT163K1() + ) + ) + ) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE): + backend.elliptic_curve_public_key_from_numbers( + ec.EllipticCurvePublicNumbers( + 2, + 3, + ec.SECT163K1() + ) + ) -- cgit v1.2.3 From a28086e20b978f4286ab263e28dceb5b6c2a5a26 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 7 Jun 2014 18:37:48 +0100 Subject: Add EC to changelog --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 13c62de5..a38534d4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,7 +18,7 @@ Changelog and :class:`~cryptography.hazmat.backends.interfaces.TraditionalOpenSSLSerializationBackend` support to the :doc:`/hazmat/backends/openssl`. - +* Added :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`. 0.4 - 2014-05-03 ~~~~~~~~~~~~~~~~ -- cgit v1.2.3