aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py3
-rw-r--r--cryptography/hazmat/primitives/asymmetric/rsa.py24
-rw-r--r--tests/hazmat/primitives/test_rsa.py163
-rw-r--r--tests/test_utils.py31
-rw-r--r--tests/utils.py6
5 files changed, 196 insertions, 31 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index fc3c3bda..ce37e5c8 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -296,6 +296,9 @@ class Backend(object):
return rsa.RSAPrivateKey(
p=self._bn_to_int(ctx.p),
q=self._bn_to_int(ctx.q),
+ dmp1=self._bn_to_int(ctx.dmp1),
+ dmq1=self._bn_to_int(ctx.dmq1),
+ iqmp=self._bn_to_int(ctx.iqmp),
private_exponent=self._bn_to_int(ctx.d),
public_exponent=self._bn_to_int(ctx.e),
modulus=self._bn_to_int(ctx.n),
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
index 60c5c807..dbe56b47 100644
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -72,10 +72,14 @@ class RSAPublicKey(object):
@utils.register_interface(interfaces.RSAPrivateKey)
class RSAPrivateKey(object):
- def __init__(self, p, q, private_exponent, public_exponent, modulus):
+ def __init__(self, p, q, private_exponent, dmp1, dmq1, iqmp,
+ public_exponent, modulus):
if (
not isinstance(p, six.integer_types) or
not isinstance(q, six.integer_types) or
+ not isinstance(dmp1, six.integer_types) or
+ not isinstance(dmq1, six.integer_types) or
+ not isinstance(iqmp, six.integer_types) or
not isinstance(private_exponent, six.integer_types) or
not isinstance(public_exponent, six.integer_types) or
not isinstance(modulus, six.integer_types)
@@ -91,6 +95,15 @@ class RSAPrivateKey(object):
if q >= modulus:
raise ValueError("q must be < modulus")
+ if dmp1 >= modulus:
+ raise ValueError("dmp1 must be < modulus")
+
+ if dmq1 >= modulus:
+ raise ValueError("dmq1 must be < modulus")
+
+ if iqmp >= modulus:
+ raise ValueError("iqmp must be < modulus")
+
if private_exponent >= modulus:
raise ValueError("private_exponent must be < modulus")
@@ -100,11 +113,20 @@ class RSAPrivateKey(object):
if public_exponent & 1 == 0:
raise ValueError("public_exponent must be odd")
+ if dmp1 & 1 == 0:
+ raise ValueError("dmp1 must be odd")
+
+ if dmq1 & 1 == 0:
+ raise ValueError("dmq1 must be odd")
+
if p * q != modulus:
raise ValueError("p*q must equal modulus")
self._p = p
self._q = q
+ self._dmp1 = dmp1
+ self._dmq1 = dmq1
+ self._iqmp = iqmp
self._private_exponent = private_exponent
self._public_exponent = public_exponent
self._modulus = modulus
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 0e930e44..9dc1a9e4 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -24,6 +24,20 @@ from cryptography.hazmat.primitives.asymmetric import rsa
from ...utils import load_pkcs1_vectors, load_vectors_from_file
+def _egcd(a, b):
+ if a == 0:
+ return (b, 0, 1)
+ else:
+ g, y, x = _egcd(b % a, a)
+ return (g, x - (b // a) * y, y)
+
+
+def _modinv(a, m):
+ g, x, y = _egcd(a, m)
+ assert g == 1
+ return x % m
+
+
def _check_rsa_private_key(skey):
assert skey
assert skey.modulus
@@ -31,6 +45,9 @@ def _check_rsa_private_key(skey):
assert skey.private_exponent
assert skey.p * skey.q == skey.modulus
assert skey.key_size
+ assert skey._dmp1 == skey.d % (skey.p - 1)
+ assert skey._dmq1 == skey.d % (skey.q - 1)
+ assert skey._iqmp == _modinv(skey.q, skey.p)
pkey = skey.public_key()
assert pkey
@@ -115,22 +132,26 @@ class TestRSA(object):
def test_invalid_private_key_argument_types(self):
with pytest.raises(TypeError):
- rsa.RSAPrivateKey(None, None, None, None, None)
+ rsa.RSAPrivateKey(None, None, None, None, None, None, None, None)
def test_invalid_public_key_argument_types(self):
with pytest.raises(TypeError):
rsa.RSAPublicKey(None, None)
def test_invalid_private_key_argument_values(self):
- # Start with p=3, q=5, private_exponent=14, public_exponent=7,
- # modulus=15. Then change one value at a time to test the bounds.
+ # 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):
rsa.RSAPrivateKey(
p=3,
- q=5,
- private_exponent=14,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
public_exponent=7,
modulus=2
)
@@ -139,70 +160,156 @@ class TestRSA(object):
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
- q=5,
- private_exponent=14,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
public_exponent=7,
- modulus=16
+ modulus=35
)
# Test a p > modulus.
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
- p=16,
- q=5,
- private_exponent=14,
+ p=37,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
public_exponent=7,
- modulus=15
+ modulus=33
)
# Test a q > modulus.
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
- q=16,
- private_exponent=14,
+ q=37,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_exponent=7,
+ modulus=33
+ )
+
+ # Test a dmp1 > modulus.
+ with pytest.raises(ValueError):
+ rsa.RSAPrivateKey(
+ p=3,
+ q=11,
+ private_exponent=3,
+ dmp1=35,
+ dmq1=3,
+ iqmp=2,
+ public_exponent=7,
+ modulus=33
+ )
+
+ # Test a dmq1 > modulus.
+ with pytest.raises(ValueError):
+ rsa.RSAPrivateKey(
+ p=3,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=35,
+ iqmp=2,
+ public_exponent=7,
+ modulus=33
+ )
+
+ # Test an iqmp > modulus.
+ with pytest.raises(ValueError):
+ rsa.RSAPrivateKey(
+ p=3,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=35,
public_exponent=7,
- modulus=15
+ modulus=33
)
# Test a private_exponent > modulus
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
- q=5,
- private_exponent=16,
+ q=11,
+ private_exponent=37,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
public_exponent=7,
- modulus=15
+ modulus=33
)
# Test a public_exponent < 3
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
- q=5,
- private_exponent=14,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
public_exponent=1,
- modulus=15
+ modulus=33
)
# Test a public_exponent > modulus
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
- q=5,
- private_exponent=14,
- public_exponent=17,
- modulus=15
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
+ public_exponent=65537,
+ modulus=33
)
# Test a public_exponent that is not odd.
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
- q=5,
- private_exponent=14,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=3,
+ iqmp=2,
public_exponent=6,
- modulus=15
+ modulus=33
+ )
+
+ # Test a dmp1 that is not odd.
+ with pytest.raises(ValueError):
+ rsa.RSAPrivateKey(
+ p=3,
+ q=11,
+ private_exponent=3,
+ dmp1=2,
+ dmq1=3,
+ iqmp=2,
+ public_exponent=7,
+ modulus=33
+ )
+
+ # Test a dmq1 that is not odd.
+ with pytest.raises(ValueError):
+ rsa.RSAPrivateKey(
+ p=3,
+ q=11,
+ private_exponent=3,
+ dmp1=1,
+ dmq1=4,
+ iqmp=2,
+ public_exponent=7,
+ modulus=33
)
def test_invalid_public_key_argument_values(self):
diff --git a/tests/test_utils.py b/tests/test_utils.py
index a0571ad6..0e1d77b5 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -768,7 +768,19 @@ def test_load_pkcs1_vectors():
'q': int(
'847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b'
'97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca41'
- '74825b48f49706d', 16)
+ '74825b48f49706d', 16),
+ 'dmp1': int(
+ '05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fc'
+ 'e69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee1'
+ '03deb771d105fd85', 16),
+ 'dmq1': int(
+ '04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b366'
+ '9bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e3'
+ '0a7e7d241551e1b9', 16),
+ 'iqmp': int(
+ '07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef53'
+ '1b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7'
+ 'b06e45307dc91f3f', 16)
},
{
@@ -809,7 +821,22 @@ def test_load_pkcs1_vectors():
'ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f'
'288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e472'
'8cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b48'
- '9c176128092d629e49d3d', 16)
+ '9c176128092d629e49d3d', 16),
+ 'dmp1': int(
+ '2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e'
+ '39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0a'
+ 'b556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec9'
+ '93e9353e480d9eec6289f', 16),
+ 'dmq1': int(
+ '4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4'
+ 'ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec'
+ '56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56e'
+ 'e4dba42c5fdb61aec2669', 16),
+ 'iqmp': int(
+ '77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8'
+ '512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124c'
+ 'bbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65'
+ '757bb3f857a58dce52156', 16)
},
{
diff --git a/tests/utils.py b/tests/utils.py
index 408b05f6..2bbecd7d 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -262,6 +262,12 @@ def load_pkcs1_vectors(vector_data):
attr = "p"
elif line.startswith("# Prime 2:"):
attr = "q"
+ elif line.startswith("# Prime exponent 1:"):
+ attr = "dmp1"
+ elif line.startswith("# Prime exponent 2:"):
+ attr = "dmq1"
+ elif line.startswith("# Coefficient:"):
+ attr = "iqmp"
elif line.startswith("#"):
attr = None
else: