aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/primitives/asymmetric/rsa.py79
-rw-r--r--docs/hazmat/primitives/asymmetric/rsa.rst79
-rw-r--r--tests/hazmat/primitives/test_rsa.py114
3 files changed, 272 insertions, 0 deletions
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
index 9e11c58a..481797fe 100644
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -269,3 +269,82 @@ class RSAPrivateKey(object):
@property
def n(self):
return self.modulus
+
+
+class RSAPrivateNumbers(object):
+ def __init__(self, p, q, d, dmp1, dmq1, iqmp,
+ public_numbers):
+ if (
+ not isinstance(p, six.integer_types) or
+ not isinstance(q, six.integer_types) or
+ not isinstance(d, six.integer_types) or
+ not isinstance(dmp1, six.integer_types) or
+ not isinstance(dmq1, six.integer_types) or
+ not isinstance(iqmp, six.integer_types)
+ ):
+ raise TypeError(
+ "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must"
+ " all be an integers."
+ )
+
+ if not isinstance(public_numbers, RSAPublicNumbers):
+ raise TypeError(
+ "RSAPrivateNumbers public_numbers must be an RSAPublicNumbers"
+ " instance."
+ )
+
+ self._p = p
+ self._q = q
+ self._d = d
+ self._dmp1 = dmp1
+ self._dmq1 = dmq1
+ self._iqmp = iqmp
+ self._public_numbers = public_numbers
+
+ @property
+ def p(self):
+ return self._p
+
+ @property
+ def q(self):
+ return self._q
+
+ @property
+ def d(self):
+ return self._d
+
+ @property
+ def dmp1(self):
+ return self._dmp1
+
+ @property
+ def dmq1(self):
+ return self._dmq1
+
+ @property
+ def iqmp(self):
+ return self._iqmp
+
+ @property
+ def public_numbers(self):
+ return self._public_numbers
+
+
+class RSAPublicNumbers(object):
+ def __init__(self, e, n):
+ if (
+ not isinstance(e, six.integer_types) or
+ not isinstance(n, six.integer_types)
+ ):
+ raise TypeError("RSAPublicNumbers arguments must be integers.")
+
+ self._e = e
+ self._n = n
+
+ @property
+ def e(self):
+ return self._e
+
+ @property
+ def n(self):
+ return self._n
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 234a5c66..54839119 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -355,6 +355,85 @@ RSA
... )
+.. class:: RSAPublicNumbers(e, n)
+
+ .. versionadded:: 0.5
+
+ The collection of integers that make up an RSA public key.
+
+ .. attribute:: n
+
+ :type: int
+
+ The public modulus.
+
+ .. attribute:: e
+
+ :type: int
+
+ The public exponent.
+
+
+.. class:: RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, public_numbers)
+
+ .. versionadded:: 0.5
+
+ The collection of integers that make up an RSA private key.
+
+ .. warning::
+
+ With the exception of the integers contained in the
+ :class:`RSAPublicNumbers` all attributes of this class must be kept
+ secret. Revealing them will compromise the security of any
+ cryptographic operations performed with a key loaded from them.
+
+ .. attribute:: public_numbers
+
+ :type: :class:`~cryptography.hazmat.primitives.rsa.RSAPublicNumbers`
+
+ The :class:`RSAPublicNumbers` which makes up the RSA public key
+ associated with this RSA private key.
+
+ .. attribute:: p
+
+ :type: int
+
+ ``p``, one of the two primes composing the :attr:`modulus`.
+
+ .. attribute:: q
+
+ :type: int
+
+ ``q``, one of the two primes composing the :attr:`modulus`.
+
+ .. attribute:: d
+
+ :type: int
+
+ The private exponent. Alias for :attr:`private_exponent`.
+
+ .. attribute:: dmp1
+
+ :type: int
+
+ A `Chinese remainder theorem`_ coefficient used to speed up RSA
+ operations. Calculated as: d mod (p-1)
+
+ .. attribute:: dmq1
+
+ :type: int
+
+ A `Chinese remainder theorem`_ coefficient used to speed up RSA
+ operations. Calculated as: d mod (q-1)
+
+ .. attribute:: iqmp
+
+ :type: int
+
+ A `Chinese remainder theorem`_ coefficient used to speed up RSA
+ operations. Calculated as: q\ :sup:`-1` mod p
+
+
Handling partial RSA private keys
---------------------------------
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index ea72f916..ba668bff 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -1664,3 +1664,117 @@ class TestRSAEncryption(object):
),
backend
)
+
+
+class TestRSANumbers(object):
+ def test_rsa_public_numbers(self):
+ public_numbers = rsa.RSAPublicNumbers(e=1, n=15)
+ assert public_numbers.e == 1
+ assert public_numbers.n == 15
+
+ def test_rsa_private_numbers(self):
+ public_numbers = rsa.RSAPublicNumbers(e=1, n=15)
+ private_numbers = rsa.RSAPrivateNumbers(
+ p=3,
+ q=5,
+ d=1,
+ dmp1=1,
+ dmq1=1,
+ iqmp=2,
+ public_numbers=public_numbers
+ )
+
+ assert private_numbers.p == 3
+ assert private_numbers.q == 5
+ assert private_numbers.d == 1
+ assert private_numbers.dmp1 == 1
+ assert private_numbers.dmq1 == 1
+ assert private_numbers.iqmp == 2
+ assert private_numbers.public_numbers == public_numbers
+
+ def test_public_numbers_invalid_types(self):
+ with pytest.raises(TypeError):
+ rsa.RSAPublicNumbers(e=None, n=15)
+
+ with pytest.raises(TypeError):
+ rsa.RSAPublicNumbers(e=1, n=None)
+
+ def test_private_numbers_invalid_types(self):
+ public_numbers = rsa.RSAPublicNumbers(e=1, n=15)
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=None,
+ q=5,
+ d=1,
+ dmp1=1,
+ dmq1=1,
+ iqmp=2,
+ public_numbers=public_numbers
+ )
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=None,
+ d=1,
+ dmp1=1,
+ dmq1=1,
+ iqmp=2,
+ public_numbers=public_numbers
+ )
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=5,
+ d=None,
+ dmp1=1,
+ dmq1=1,
+ iqmp=2,
+ public_numbers=public_numbers
+ )
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=5,
+ d=1,
+ dmp1=None,
+ dmq1=1,
+ iqmp=2,
+ public_numbers=public_numbers
+ )
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=5,
+ d=1,
+ dmp1=1,
+ dmq1=None,
+ iqmp=2,
+ public_numbers=public_numbers
+ )
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=5,
+ d=1,
+ dmp1=1,
+ dmq1=1,
+ iqmp=None,
+ public_numbers=public_numbers
+ )
+
+ with pytest.raises(TypeError):
+ rsa.RSAPrivateNumbers(
+ p=3,
+ q=5,
+ d=1,
+ dmp1=1,
+ dmq1=1,
+ iqmp=2,
+ public_numbers=None
+ )