aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-06-04 13:41:37 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-06-04 13:41:37 -0500
commite5f7e3055ee28c420eda563aafad19d664a6a76c (patch)
tree7480aa0c66c9773bb889a8bb42b53c3fc1edda43
parent395be8ba6b482f52c76713e2d01f29c824ae96de (diff)
parentda76ae019e98ef8580b9568bdd59fd27121ff432 (diff)
downloadcryptography-e5f7e3055ee28c420eda563aafad19d664a6a76c.tar.gz
cryptography-e5f7e3055ee28c420eda563aafad19d664a6a76c.tar.bz2
cryptography-e5f7e3055ee28c420eda563aafad19d664a6a76c.zip
Merge pull request #1027 from dreid/rsa-number-loading
RSABackend support for loading RSA*Numbers
-rw-r--r--cryptography/hazmat/backends/interfaces.py12
-rw-r--r--cryptography/hazmat/backends/multibackend.py14
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py18
-rw-r--r--docs/hazmat/backends/interfaces.rst31
-rw-r--r--tests/hazmat/backends/test_multibackend.py20
-rw-r--r--tests/hazmat/primitives/test_rsa.py248
6 files changed, 343 insertions, 0 deletions
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index ba02bbd2..524e0a5b 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -142,6 +142,18 @@ class RSABackend(object):
generation.
"""
+ @abc.abstractmethod
+ def load_rsa_private_numbers(self, numbers):
+ """
+ Returns an RSAPrivateKey provider.
+ """
+
+ @abc.abstractmethod
+ def load_rsa_public_numbers(self, numbers):
+ """
+ Returns an RSAPublicKey provider.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class DSABackend(object):
diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py
index b4cb6889..f3c79376 100644
--- a/cryptography/hazmat/backends/multibackend.py
+++ b/cryptography/hazmat/backends/multibackend.py
@@ -178,6 +178,20 @@ class MultiBackend(object):
raise UnsupportedAlgorithm("RSA is not supported by the backend.",
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+ def load_rsa_private_numbers(self, numbers):
+ for b in self._filtered_backends(RSABackend):
+ return b.load_rsa_private_numbers(numbers)
+
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def load_rsa_public_numbers(self, numbers):
+ for b in self._filtered_backends(RSABackend):
+ return b.load_rsa_public_numbers(numbers)
+
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
def generate_dsa_parameters(self, key_size):
for b in self._filtered_backends(DSABackend):
return b.generate_dsa_parameters(key_size)
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 4112f0e5..ffe09663 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -377,6 +377,24 @@ class Backend(object):
return (public_exponent >= 3 and public_exponent & 1 != 0 and
key_size >= 512)
+ def load_rsa_private_numbers(self, numbers):
+ return rsa.RSAPrivateKey(
+ p=numbers.p,
+ q=numbers.q,
+ private_exponent=numbers.d,
+ dmp1=numbers.dmp1,
+ dmq1=numbers.dmq1,
+ iqmp=numbers.iqmp,
+ public_exponent=numbers.public_numbers.e,
+ modulus=numbers.public_numbers.n
+ )
+
+ def load_rsa_public_numbers(self, numbers):
+ return rsa.RSAPublicKey(
+ public_exponent=numbers.e,
+ modulus=numbers.n
+ )
+
def _new_evp_pkey(self):
evp_pkey = self._lib.EVP_PKEY_new()
assert evp_pkey != self._ffi.NULL
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index c1ce621a..1a2603bc 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -322,6 +322,37 @@ A specific ``backend`` may provide one or more of these interfaces.
:raises ValueError: When plaintext is too long for the key size.
+ .. method:: load_rsa_private_numbers(numbers):
+
+ :param numbers: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`.
+
+ :returns: A provider of
+ :class:`~cryptography.hazmat.primitives.interfaces.RSAPrivateKey`.
+
+ :raises ValueError: This is raised when the values of ``p``, ``q``,
+ ``private_exponent``, ``public_exponent``, or ``modulus`` do not
+ match the bounds specified in :rfc:`3447`.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This raised when
+ any backend specific criteria are not met.
+
+ .. method:: load_rsa_public_numbers(numbers):
+
+ :param numbers: An instance of
+ :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`.
+
+ :returns: A provider of
+ :class:`~cryptography.hazmat.primitives.interfaces.RSAPublicKey`.
+
+ :raises ValueError: This is raised when the values of
+ ``public_exponent`` or ``modulus`` do not match the bounds
+ specified in :rfc:`3447`.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This raised when
+ any backend specific criteria are not met.
+
+
.. class:: TraditionalOpenSSLSerializationBackend
.. versionadded:: 0.3
diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py
index 3fa364e2..93d58483 100644
--- a/tests/hazmat/backends/test_multibackend.py
+++ b/tests/hazmat/backends/test_multibackend.py
@@ -113,6 +113,12 @@ class DummyRSABackend(object):
def encrypt_rsa(self, public_key, plaintext, padding):
pass
+ def load_rsa_private_numbers(self, numbers):
+ pass
+
+ def load_rsa_public_numbers(self, numbers):
+ pass
+
@utils.register_interface(DSABackend)
class DummyDSABackend(object):
@@ -236,6 +242,10 @@ class TestMultiBackend(object):
backend.decrypt_rsa("private_key", "encrypted", padding.PKCS1v15())
+ backend.load_rsa_private_numbers("private_numbers")
+
+ backend.load_rsa_public_numbers("public_numbers")
+
backend = MultiBackend([])
with raises_unsupported_algorithm(
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
@@ -279,6 +289,16 @@ class TestMultiBackend(object):
):
backend.decrypt_rsa("private_key", "encrypted", padding.PKCS1v15())
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ backend.load_rsa_private_numbers("private_numbers")
+
+ with raises_unsupported_algorithm(
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ ):
+ backend.load_rsa_public_numbers("public_numbers")
+
def test_dsa(self):
backend = MultiBackend([
DummyDSABackend()
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index ba668bff..a76c0ec2 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -1666,6 +1666,7 @@ class TestRSAEncryption(object):
)
+@pytest.mark.rsa
class TestRSANumbers(object):
def test_rsa_public_numbers(self):
public_numbers = rsa.RSAPublicNumbers(e=1, n=15)
@@ -1778,3 +1779,250 @@ class TestRSANumbers(object):
iqmp=2,
public_numbers=None
)
+
+ def test_invalid_public_numbers_argument_values(self, backend):
+ # Start with public_exponent=7, modulus=15. Then change one value at a
+ # time to test the bounds.
+
+ # Test a modulus < 3.
+
+ with pytest.raises(ValueError):
+ backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=7, n=2))
+
+ # Test a public_exponent < 3
+ with pytest.raises(ValueError):
+ backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=1, n=15))
+
+ # Test a public_exponent > modulus
+ with pytest.raises(ValueError):
+ backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=17, n=15))
+
+ # Test a public_exponent that is not odd.
+ with pytest.raises(ValueError):
+ backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=16, n=15))
+
+ def test_invalid_private_numbers_argument_values(self, backend):
+ # Start with p=3, q=11, private_exponent=3, public_exponent=7,
+ # modulus=33, dmp1=1, dmq1=3, iqmp=2. Then change one value at
+ # a time to test the bounds.
+
+ # Test a modulus < 3.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=2
+ )
+ )
+ )
+
+ # Test a modulus != p * q.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=35
+ )
+ )
+ )
+
+ # Test a p > modulus.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=37,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test a q > modulus.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=37,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test a dmp1 > modulus.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=35,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test a dmq1 > modulus.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=35,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test an iqmp > modulus.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=35,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test a private_exponent > modulus
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=37,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test a public_exponent < 3
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=1,
+ n=33
+ )
+ )
+ )
+
+ # Test a public_exponent > modulus
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=35,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=65537,
+ n=33
+ )
+ )
+ )
+
+ # Test a public_exponent that is not odd.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=6,
+ n=33
+ )
+ )
+ )
+
+ # Test a dmp1 that is not odd.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=2,
+ dmq1=3,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )
+
+ # Test a dmq1 that is not odd.
+ with pytest.raises(ValueError):
+ backend.load_rsa_private_numbers(
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=11,
+ d=3,
+ dmp1=1,
+ dmq1=4,
+ iqmp=2,
+ public_numbers=rsa.RSAPublicNumbers(
+ e=7,
+ n=33
+ )
+ )
+ )