Merge pull request #808 from public/tidy-rsa
RSAPrivateKey to evp_pkey utility method
diff --git a/cryptography/hazmat/backends/__init__.py b/cryptography/hazmat/backends/__init__.py
index 59d1bc6..ae78822 100644
--- a/cryptography/hazmat/backends/__init__.py
+++ b/cryptography/hazmat/backends/__init__.py
@@ -13,23 +13,42 @@
from __future__ import absolute_import, division, print_function
-from cryptography.hazmat.backends import openssl
from cryptography.hazmat.backends.multibackend import MultiBackend
from cryptography.hazmat.bindings.commoncrypto.binding import (
Binding as CommonCryptoBinding
)
-
-_ALL_BACKENDS = []
-
-if CommonCryptoBinding.is_available():
- from cryptography.hazmat.backends import commoncrypto
- _ALL_BACKENDS.append(commoncrypto.backend)
-
-_ALL_BACKENDS.append(openssl.backend)
+from cryptography.hazmat.bindings.openssl.binding import (
+ Binding as OpenSSLBinding
+)
-_default_backend = MultiBackend(_ALL_BACKENDS)
+_available_backends_list = None
+
+
+def _available_backends():
+ global _available_backends_list
+
+ if _available_backends_list is None:
+ _available_backends_list = []
+
+ if CommonCryptoBinding.is_available():
+ from cryptography.hazmat.backends import commoncrypto
+ _available_backends_list.append(commoncrypto.backend)
+
+ if OpenSSLBinding.is_available():
+ from cryptography.hazmat.backends import openssl
+ _available_backends_list.append(openssl.backend)
+
+ return _available_backends_list
+
+
+_default_backend = None
def default_backend():
+ global _default_backend
+
+ if _default_backend is None:
+ _default_backend = MultiBackend(_available_backends())
+
return _default_backend
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
index dfb4334..cbef8e3 100644
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -16,6 +16,8 @@
import six
from cryptography import utils
+from cryptography.exceptions import UnsupportedInterface
+from cryptography.hazmat.backends.interfaces import RSABackend
from cryptography.hazmat.primitives import interfaces
@@ -41,6 +43,10 @@
self._modulus = modulus
def verifier(self, signature, padding, algorithm, backend):
+ if not isinstance(backend, RSABackend):
+ raise UnsupportedInterface(
+ "Backend object does not implement RSABackend")
+
return backend.create_rsa_verification_ctx(self, signature, padding,
algorithm)
@@ -128,9 +134,17 @@
@classmethod
def generate(cls, public_exponent, key_size, backend):
+ if not isinstance(backend, RSABackend):
+ raise UnsupportedInterface(
+ "Backend object does not implement RSABackend")
+
return backend.generate_rsa_private_key(public_exponent, key_size)
def signer(self, padding, algorithm, backend):
+ if not isinstance(backend, RSABackend):
+ raise UnsupportedInterface(
+ "Backend object does not implement RSABackend")
+
return backend.create_rsa_signature_ctx(self, padding, algorithm)
@property
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index d366e4c..1275019 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -15,13 +15,18 @@
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, NotYetFinalized, AlreadyUpdated,
+ AlreadyFinalized, NotYetFinalized, AlreadyUpdated, UnsupportedInterface
)
+from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives import interfaces
class Cipher(object):
def __init__(self, algorithm, mode, backend):
+ if not isinstance(backend, CipherBackend):
+ raise UnsupportedInterface(
+ "Backend object does not implement CipherBackend")
+
if not isinstance(algorithm, interfaces.CipherAlgorithm):
raise TypeError("Expected interface of interfaces.CipherAlgorithm")
diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py
index bee188b..409f564 100644
--- a/cryptography/hazmat/primitives/hashes.py
+++ b/cryptography/hazmat/primitives/hashes.py
@@ -16,13 +16,18 @@
import six
from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized
+from cryptography.exceptions import AlreadyFinalized, UnsupportedInterface
+from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.HashContext)
class Hash(object):
def __init__(self, algorithm, backend, ctx=None):
+ if not isinstance(backend, HashBackend):
+ raise UnsupportedInterface(
+ "Backend object does not implement HashBackend")
+
if not isinstance(algorithm, interfaces.HashAlgorithm):
raise TypeError("Expected instance of interfaces.HashAlgorithm.")
self.algorithm = algorithm
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 76d658a..0bcbb3c 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -16,13 +16,20 @@
import six
from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, InvalidSignature
+from cryptography.exceptions import (
+ AlreadyFinalized, InvalidSignature, UnsupportedInterface
+)
+from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, interfaces
@utils.register_interface(interfaces.HashContext)
class HMAC(object):
def __init__(self, key, algorithm, backend, ctx=None):
+ if not isinstance(backend, HMACBackend):
+ raise UnsupportedInterface(
+ "Backend object does not implement HMACBackend")
+
if not isinstance(algorithm, interfaces.HashAlgorithm):
raise TypeError("Expected instance of interfaces.HashAlgorithm.")
self.algorithm = algorithm
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 7943981..03a7cae 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -50,6 +50,11 @@
provider.
:return: A new instance of ``RSAPrivateKey``.
+ :raises cryptography.exceptions.UnsupportedInterface: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
+
+
.. method:: signer(padding, algorithm, backend)
.. versionadded:: 0.3
@@ -90,6 +95,9 @@
:returns:
:class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+ :raises cryptography.exceptions.UnsupportedInterface: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
.. class:: RSAPublicKey(public_exponent, modulus)
@@ -154,6 +162,10 @@
:returns:
:class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`
+ :raises cryptography.exceptions.UnsupportedInterface: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
+
.. _`RSA`: https://en.wikipedia.org/wiki/RSA_(cryptosystem)
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
.. _`use 65537`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst
index 627ca7b..b7eee2f 100644
--- a/docs/hazmat/primitives/cryptographic-hashes.rst
+++ b/docs/hazmat/primitives/cryptographic-hashes.rst
@@ -45,6 +45,10 @@
:class:`~cryptography.hazmat.backends.interfaces.HashBackend`
provider.
+ :raises cryptography.exceptions.UnsupportedInterface: This is raised if the
+ provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+
.. method:: update(data)
:param bytes data: The bytes to be hashed.
diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst
index 6ca9e16..ce4e880 100644
--- a/docs/hazmat/primitives/hmac.rst
+++ b/docs/hazmat/primitives/hmac.rst
@@ -56,6 +56,10 @@
:class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
provider.
+ :raises cryptography.exceptions.UnsupportedInterface: This is raised if the
+ provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
.. method:: update(msg)
:param bytes msg: The bytes to hash and authenticate.
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 741091b..71a1064 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -56,6 +56,10 @@
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
provider.
+ :raises cryptography.exceptions.UnsupportedInterface: This is raised if the
+ provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
+
.. method:: encryptor()
:return: An encrypting
diff --git a/tests/conftest.py b/tests/conftest.py
index 0069f2c..36183f4 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -15,7 +15,7 @@
import pytest
-from cryptography.hazmat.backends import _ALL_BACKENDS
+from cryptography.hazmat.backends import _available_backends
from cryptography.hazmat.backends.interfaces import (
HMACBackend, CipherBackend, HashBackend, PBKDF2HMACBackend, RSABackend
)
@@ -25,7 +25,7 @@
def pytest_generate_tests(metafunc):
names = metafunc.config.getoption("--backend")
- selected_backends = select_backends(names, _ALL_BACKENDS)
+ selected_backends = select_backends(names, _available_backends())
if "backend" in metafunc.fixturenames:
metafunc.parametrize("backend", selected_backends)
diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py
index d9f8353..bd9625e 100644
--- a/tests/hazmat/primitives/test_ciphers.py
+++ b/tests/hazmat/primitives/test_ciphers.py
@@ -17,9 +17,12 @@
import pytest
+from cryptography.exceptions import UnsupportedInterface
+from cryptography.hazmat.primitives import ciphers
from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, Camellia, TripleDES, Blowfish, ARC4, CAST5, IDEA
)
+from cryptography.hazmat.primitives.ciphers.modes import ECB
class TestAES(object):
@@ -120,3 +123,10 @@
def test_invalid_key_size(self):
with pytest.raises(ValueError):
IDEA(b"\x00" * 17)
+
+
+def test_invalid_backend():
+ pretend_backend = object()
+
+ with pytest.raises(UnsupportedInterface):
+ ciphers.Cipher(AES(b"AAAAAAAAAAAAAAAA"), ECB, pretend_backend)
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index fc53d63..5b318f6 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -20,7 +20,10 @@
import six
from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, UnsupportedHash
+from cryptography.exceptions import (
+ AlreadyFinalized, UnsupportedHash, UnsupportedInterface
+)
+from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import hashes, interfaces
from .utils import generate_base_hash_test
@@ -39,7 +42,11 @@
m.update(six.u("\u00FC"))
def test_copy_backend_object(self):
- pretend_backend = pretend.stub()
+ @utils.register_interface(HashBackend)
+ class PretendBackend(object):
+ pass
+
+ pretend_backend = PretendBackend()
copied_ctx = pretend.stub()
pretend_ctx = pretend.stub(copy=lambda: copied_ctx)
h = hashes.Hash(hashes.SHA1(), backend=pretend_backend,
@@ -171,3 +178,10 @@
digest_size=16,
block_size=64,
)
+
+
+def test_invalid_backend():
+ pretend_backend = object()
+
+ with pytest.raises(UnsupportedInterface):
+ hashes.Hash(hashes.SHA1(), pretend_backend)
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 88bed52..3589e6a 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -21,8 +21,9 @@
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, UnsupportedHash, InvalidSignature
+ AlreadyFinalized, UnsupportedHash, InvalidSignature, UnsupportedInterface
)
+from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import hashes, hmac, interfaces
from .utils import generate_base_hmac_test
@@ -52,8 +53,11 @@
h.update(six.u("\u00FC"))
def test_copy_backend_object(self):
- pretend_hmac = pretend.stub()
- pretend_backend = pretend.stub(hmacs=pretend_hmac)
+ @utils.register_interface(HMACBackend)
+ class PretendBackend(object):
+ pass
+
+ pretend_backend = PretendBackend()
copied_ctx = pretend.stub()
pretend_ctx = pretend.stub(copy=lambda: copied_ctx)
h = hmac.HMAC(b"key", hashes.SHA1(), backend=pretend_backend,
@@ -104,3 +108,10 @@
def test_unsupported_hash(self, backend):
with pytest.raises(UnsupportedHash):
hmac.HMAC(b"key", UnsupportedDummyHash(), backend)
+
+
+def test_invalid_backend():
+ pretend_backend = object()
+
+ with pytest.raises(UnsupportedInterface):
+ hmac.HMAC(b"key", hashes.SHA1(), pretend_backend)
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 114dc41..0e88bb7 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -21,9 +21,9 @@
import pytest
from cryptography import exceptions, utils
+from cryptography.exceptions import UnsupportedInterface
from cryptography.hazmat.primitives import hashes, interfaces
-from cryptography.hazmat.primitives.asymmetric import rsa
-from cryptography.hazmat.primitives.asymmetric import padding
+from cryptography.hazmat.primitives.asymmetric import rsa, padding
from ...utils import load_pkcs1_vectors, load_vectors_from_file
@@ -385,6 +385,13 @@
rsa.RSAPublicKey(public_exponent=6, modulus=15)
+def test_rsa_generate_invalid_backend():
+ pretend_backend = object()
+
+ with pytest.raises(UnsupportedInterface):
+ rsa.RSAPrivateKey.generate(65537, 2048, pretend_backend)
+
+
@pytest.mark.rsa
class TestRSASignature(object):
@pytest.mark.parametrize(
@@ -444,6 +451,14 @@
with pytest.raises(TypeError):
private_key.signer("notpadding", hashes.SHA1(), backend)
+ def test_rsa_signer_invalid_backend(self, backend):
+ pretend_backend = object()
+ private_key = rsa.RSAPrivateKey.generate(65537, 2048, backend)
+
+ with pytest.raises(UnsupportedInterface):
+ private_key.signer(
+ padding.PKCS1v15(), hashes.SHA256, pretend_backend)
+
@pytest.mark.rsa
class TestRSAVerification(object):
@@ -559,6 +574,15 @@
with pytest.raises(TypeError):
public_key.verifier(b"sig", "notpadding", hashes.SHA1(), backend)
+ def test_rsa_verifier_invalid_backend(self, backend):
+ pretend_backend = object()
+ private_key = rsa.RSAPrivateKey.generate(65537, 2048, backend)
+ public_key = private_key.public_key()
+
+ with pytest.raises(UnsupportedInterface):
+ public_key.verifier(
+ b"foo", padding.PKCS1v15(), hashes.SHA256(), pretend_backend)
+
class TestMGF1(object):
def test_invalid_hash_algorithm(self):