blob: df3a70f551da28c89154169344da5aa738334daf [file] [log] [blame]
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
import itertools
import os
import pytest
from cryptography.hazmat.primitives.asymmetric import rsa
from ...utils import load_pkcs1_vectors, load_vectors_from_file
def _modinv(e, m):
"""
Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1
"""
x1, y1, x2, y2 = 1, 0, 0, 1
a, b = e, m
while b > 0:
q, r = divmod(a, b)
xn, yn = x1 - q * x2, y1 - q * y2
a, b, x1, y1, x2, y2 = b, r, x2, y2, xn, yn
return x1 % m
def _check_rsa_private_key(skey):
assert skey
assert skey.modulus
assert skey.public_exponent
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
assert skey.modulus == pkey.modulus
assert skey.public_exponent == pkey.public_exponent
assert skey.key_size == pkey.key_size
def test_modular_inverse():
p = int(
"d1f9f6c09fd3d38987f7970247b85a6da84907753d42ec52bc23b745093f4fff5cff3"
"617ce43d00121a9accc0051f519c76e08cf02fc18acfe4c9e6aea18da470a2b611d2e"
"56a7b35caa2c0239bc041a53cc5875ca0b668ae6377d4b23e932d8c995fd1e58ecfd8"
"c4b73259c0d8a54d691cca3f6fb85c8a5c1baf588e898d481", 16
)
q = int(
"d1519255eb8f678c86cfd06802d1fbef8b664441ac46b73d33d13a8404580a33a8e74"
"cb2ea2e2963125b3d454d7a922cef24dd13e55f989cbabf64255a736671f4629a47b5"
"b2347cfcd669133088d1c159518531025297c2d67c9da856a12e80222cd03b4c6ec0f"
"86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01", 16
)
assert _modinv(q, p) == int(
"0275e06afa722999315f8f322275483e15e2fb46d827b17800f99110b269a6732748f"
"624a382fa2ed1ec68c99f7fc56fb60e76eea51614881f497ba7034c17dde955f92f15"
"772f8b2b41f3e56d88b1e096cdd293eba4eae1e82db815e0fadea0c4ec971bc6fd875"
"c20e67e48c31a611e98d32c6213ae4c4d7b53023b2f80c538", 16
)
@pytest.mark.rsa
class TestRSA(object):
@pytest.mark.parametrize(
"public_exponent,key_size",
itertools.product(
(3, 5, 65537),
(1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048)
)
)
def test_generate_rsa_keys(self, backend, public_exponent, key_size):
skey = rsa.RSAPrivateKey.generate(public_exponent, key_size, backend)
_check_rsa_private_key(skey)
assert skey.key_size == key_size
assert skey.public_exponent == public_exponent
def test_generate_bad_rsa_key(self, backend):
with pytest.raises(ValueError):
rsa.RSAPrivateKey.generate(public_exponent=1,
key_size=2048,
backend=backend)
with pytest.raises(ValueError):
rsa.RSAPrivateKey.generate(public_exponent=4,
key_size=2048,
backend=backend)
def test_cant_generate_insecure_tiny_key(self, backend):
with pytest.raises(ValueError):
rsa.RSAPrivateKey.generate(public_exponent=65537,
key_size=511,
backend=backend)
with pytest.raises(ValueError):
rsa.RSAPrivateKey.generate(public_exponent=65537,
key_size=256,
backend=backend)
@pytest.mark.parametrize(
"pkcs1_example",
load_vectors_from_file(
os.path.join(
"asymmetric", "RSA", "pkcs-1v2-1d2-vec", "pss-vect.txt"),
load_pkcs1_vectors
)
)
def test_load_pss_vect_example_keys(self, pkcs1_example):
secret, public = pkcs1_example
skey = rsa.RSAPrivateKey(
p=secret["p"],
q=secret["q"],
private_exponent=secret["private_exponent"],
dmp1=secret["dmp1"],
dmq1=secret["dmq1"],
iqmp=secret["iqmp"],
public_exponent=secret["public_exponent"],
modulus=secret["modulus"]
)
assert skey
_check_rsa_private_key(skey)
pkey = rsa.RSAPublicKey(
public_exponent=public["public_exponent"],
modulus=public["modulus"]
)
assert pkey
pkey2 = skey.public_key()
assert pkey2
assert skey.modulus == pkey.modulus
assert skey.modulus == skey.n
assert skey.public_exponent == pkey.public_exponent
assert skey.public_exponent == skey.e
assert skey.private_exponent == skey.d
assert pkey.modulus
assert pkey.modulus == pkey2.modulus
assert pkey.modulus == pkey.n
assert pkey.public_exponent == pkey2.public_exponent
assert pkey.public_exponent == pkey.e
assert skey.key_size
assert skey.key_size == pkey.key_size
assert skey.key_size == pkey2.key_size
def test_invalid_private_key_argument_types(self):
with pytest.raises(TypeError):
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=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=11,
private_exponent=3,
dmp1=1,
dmq1=3,
iqmp=2,
public_exponent=7,
modulus=2
)
# Test a modulus != p * q.
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
q=11,
private_exponent=3,
dmp1=1,
dmq1=3,
iqmp=2,
public_exponent=7,
modulus=35
)
# Test a p > modulus.
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=37,
q=11,
private_exponent=3,
dmp1=1,
dmq1=3,
iqmp=2,
public_exponent=7,
modulus=33
)
# Test a q > modulus.
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
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=33
)
# Test a private_exponent > modulus
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
q=11,
private_exponent=37,
dmp1=1,
dmq1=3,
iqmp=2,
public_exponent=7,
modulus=33
)
# Test a public_exponent < 3
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
q=11,
private_exponent=3,
dmp1=1,
dmq1=3,
iqmp=2,
public_exponent=1,
modulus=33
)
# Test a public_exponent > modulus
with pytest.raises(ValueError):
rsa.RSAPrivateKey(
p=3,
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=11,
private_exponent=3,
dmp1=1,
dmq1=3,
iqmp=2,
public_exponent=6,
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):
# 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):
rsa.RSAPublicKey(public_exponent=7, modulus=2)
# Test a public_exponent < 3
with pytest.raises(ValueError):
rsa.RSAPublicKey(public_exponent=1, modulus=15)
# Test a public_exponent > modulus
with pytest.raises(ValueError):
rsa.RSAPublicKey(public_exponent=17, modulus=15)
# Test a public_exponent that is not odd.
with pytest.raises(ValueError):
rsa.RSAPublicKey(public_exponent=6, modulus=15)