aboutsummaryrefslogtreecommitdiffstats
path: root/tests/hazmat/primitives
diff options
context:
space:
mode:
Diffstat (limited to 'tests/hazmat/primitives')
-rw-r--r--tests/hazmat/primitives/test_cmac.py217
-rw-r--r--tests/hazmat/primitives/test_dsa.py2
-rw-r--r--tests/hazmat/primitives/test_pbkdf2hmac.py1
-rw-r--r--tests/hazmat/primitives/test_rsa.py193
-rw-r--r--tests/hazmat/primitives/utils.py18
5 files changed, 396 insertions, 35 deletions
diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py
new file mode 100644
index 00000000..7ec4af68
--- /dev/null
+++ b/tests/hazmat/primitives/test_cmac.py
@@ -0,0 +1,217 @@
+# 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 binascii
+
+import pretend
+
+import pytest
+
+import six
+
+from cryptography import utils
+from cryptography.exceptions import (
+ AlreadyFinalized, InvalidSignature, _Reasons
+)
+from cryptography.hazmat.backends.interfaces import CMACBackend
+from cryptography.hazmat.primitives.ciphers.algorithms import (
+ AES, ARC4, TripleDES
+)
+from cryptography.hazmat.primitives.cmac import CMAC
+
+from tests.utils import (
+ load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm
+)
+
+vectors_aes128 = load_vectors_from_file(
+ "CMAC/nist-800-38b-aes128.txt", load_nist_vectors)
+
+vectors_aes192 = load_vectors_from_file(
+ "CMAC/nist-800-38b-aes192.txt", load_nist_vectors)
+
+vectors_aes256 = load_vectors_from_file(
+ "CMAC/nist-800-38b-aes256.txt", load_nist_vectors)
+
+vectors_aes = vectors_aes128 + vectors_aes192 + vectors_aes256
+
+vectors_3des = load_vectors_from_file(
+ "CMAC/nist-800-38b-3des.txt", load_nist_vectors)
+
+fake_key = b"\x00" * 16
+
+
+@pytest.mark.cmac
+class TestCMAC(object):
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ AES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ @pytest.mark.parametrize("params", vectors_aes)
+ def test_aes_generate(self, backend, params):
+ key = params["key"]
+ message = params["message"]
+ output = params["output"]
+
+ cmac = CMAC(AES(binascii.unhexlify(key)), backend)
+ cmac.update(binascii.unhexlify(message))
+ assert binascii.hexlify(cmac.finalize()) == output
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ AES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ @pytest.mark.parametrize("params", vectors_aes)
+ def test_aes_verify(self, backend, params):
+ key = params["key"]
+ message = params["message"]
+ output = params["output"]
+
+ cmac = CMAC(AES(binascii.unhexlify(key)), backend)
+ cmac.update(binascii.unhexlify(message))
+ assert cmac.verify(binascii.unhexlify(output)) is None
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ TripleDES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ @pytest.mark.parametrize("params", vectors_3des)
+ def test_3des_generate(self, backend, params):
+ key1 = params["key1"]
+ key2 = params["key2"]
+ key3 = params["key3"]
+
+ key = key1 + key2 + key3
+
+ message = params["message"]
+ output = params["output"]
+
+ cmac = CMAC(TripleDES(binascii.unhexlify(key)), backend)
+ cmac.update(binascii.unhexlify(message))
+ assert binascii.hexlify(cmac.finalize()) == output
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ TripleDES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ @pytest.mark.parametrize("params", vectors_3des)
+ def test_3des_verify(self, backend, params):
+ key1 = params["key1"]
+ key2 = params["key2"]
+ key3 = params["key3"]
+
+ key = key1 + key2 + key3
+
+ message = params["message"]
+ output = params["output"]
+
+ cmac = CMAC(TripleDES(binascii.unhexlify(key)), backend)
+ cmac.update(binascii.unhexlify(message))
+ assert cmac.verify(binascii.unhexlify(output)) is None
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ AES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ def test_invalid_verify(self, backend):
+ key = b"2b7e151628aed2a6abf7158809cf4f3c"
+ cmac = CMAC(AES(key), backend)
+ cmac.update(b"6bc1bee22e409f96e93d7e117393172a")
+
+ with pytest.raises(InvalidSignature):
+ cmac.verify(b"foobar")
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ ARC4(fake_key), None),
+ skip_message="Does not support CMAC."
+ )
+ def test_invalid_algorithm(self, backend):
+ key = b"0102030405"
+ with pytest.raises(TypeError):
+ CMAC(ARC4(key), backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ AES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ def test_raises_after_finalize(self, backend):
+ key = b"2b7e151628aed2a6abf7158809cf4f3c"
+ cmac = CMAC(AES(key), backend)
+ cmac.finalize()
+
+ with pytest.raises(AlreadyFinalized):
+ cmac.update(b"foo")
+
+ with pytest.raises(AlreadyFinalized):
+ cmac.copy()
+
+ with pytest.raises(AlreadyFinalized):
+ cmac.finalize()
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ AES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ def test_verify_reject_unicode(self, backend):
+ key = b"2b7e151628aed2a6abf7158809cf4f3c"
+ cmac = CMAC(AES(key), backend)
+
+ with pytest.raises(TypeError):
+ cmac.update(six.u(''))
+
+ with pytest.raises(TypeError):
+ cmac.verify(six.u(''))
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cmac_algorithm_supported(
+ AES(fake_key)),
+ skip_message="Does not support CMAC."
+ )
+ def test_copy_with_backend(self, backend):
+ key = b"2b7e151628aed2a6abf7158809cf4f3c"
+ cmac = CMAC(AES(key), backend)
+ cmac.update(b"6bc1bee22e409f96e93d7e117393172a")
+ copy_cmac = cmac.copy()
+ assert cmac.finalize() == copy_cmac.finalize()
+
+
+def test_copy():
+ @utils.register_interface(CMACBackend)
+ class PretendBackend(object):
+ pass
+
+ pretend_backend = PretendBackend()
+ copied_ctx = pretend.stub()
+ pretend_ctx = pretend.stub(copy=lambda: copied_ctx)
+ key = b"2b7e151628aed2a6abf7158809cf4f3c"
+ cmac = CMAC(AES(key), backend=pretend_backend, ctx=pretend_ctx)
+
+ assert cmac._backend is pretend_backend
+ assert cmac.copy()._backend is pretend_backend
+
+
+def test_invalid_backend():
+ key = b"2b7e151628aed2a6abf7158809cf4f3c"
+ pretend_backend = object()
+
+ with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
+ CMAC(AES(key), pretend_backend)
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 2b5d4bb3..bc3b1db6 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -23,7 +23,7 @@ from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.utils import bit_length
from ...utils import (
- load_vectors_from_file, load_fips_dsa_key_pair_vectors,
+ load_fips_dsa_key_pair_vectors, load_vectors_from_file,
raises_unsupported_algorithm
)
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py
index 62ca0921..e928fc6a 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac.py
@@ -14,6 +14,7 @@
from __future__ import absolute_import, division, print_function
import pytest
+
import six
from cryptography import utils
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 1cbd1636..34b80cc3 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -26,7 +26,9 @@ from cryptography.exceptions import _Reasons
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import padding, rsa
-from .utils import generate_rsa_verification_test
+from .utils import (
+ _check_rsa_private_key, generate_rsa_verification_test
+)
from ...utils import (
load_pkcs1_vectors, load_rsa_nist_vectors, load_vectors_from_file,
raises_unsupported_algorithm
@@ -42,37 +44,6 @@ class DummyMGF(object):
_salt_length = 0
-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 _flatten_pkcs1_examples(vectors):
flattened_vectors = []
for vector in vectors:
@@ -97,7 +68,7 @@ def test_modular_inverse():
"b2347cfcd669133088d1c159518531025297c2d67c9da856a12e80222cd03b4c6ec0f"
"86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01", 16
)
- assert _modinv(q, p) == int(
+ assert rsa._modinv(q, p) == int(
"0275e06afa722999315f8f322275483e15e2fb46d827b17800f99110b269a6732748f"
"624a382fa2ed1ec68c99f7fc56fb60e76eea51614881f497ba7034c17dde955f92f15"
"772f8b2b41f3e56d88b1e096cdd293eba4eae1e82db815e0fadea0c4ec971bc6fd875"
@@ -108,7 +79,7 @@ def test_modular_inverse():
@pytest.mark.rsa
class TestRSA(object):
@pytest.mark.parametrize(
- "public_exponent,key_size",
+ ("public_exponent", "key_size"),
itertools.product(
(3, 5, 65537),
(1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1536, 2048)
@@ -1238,3 +1209,157 @@ class TestMGF1(object):
mgf = padding.MGF1(algorithm, padding.MGF1.MAX_LENGTH)
assert mgf._algorithm == algorithm
assert mgf._salt_length == padding.MGF1.MAX_LENGTH
+
+
+class TestOAEP(object):
+ def test_invalid_algorithm(self):
+ mgf = padding.MGF1(hashes.SHA1())
+ with pytest.raises(TypeError):
+ padding.OAEP(
+ mgf=mgf,
+ algorithm=b"",
+ label=None
+ )
+
+
+@pytest.mark.rsa
+class TestRSADecryption(object):
+ @pytest.mark.parametrize(
+ "vector",
+ _flatten_pkcs1_examples(load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"),
+ load_pkcs1_vectors
+ ))
+ )
+ def test_decrypt_pkcs1v15_vectors(self, vector, backend):
+ private, public, example = vector
+ skey = rsa.RSAPrivateKey(
+ p=private["p"],
+ q=private["q"],
+ private_exponent=private["private_exponent"],
+ dmp1=private["dmp1"],
+ dmq1=private["dmq1"],
+ iqmp=private["iqmp"],
+ public_exponent=private["public_exponent"],
+ modulus=private["modulus"]
+ )
+ ciphertext = binascii.unhexlify(example["encryption"])
+ assert len(ciphertext) == math.ceil(skey.key_size / 8.0)
+ message = skey.decrypt(
+ ciphertext,
+ padding.PKCS1v15(),
+ backend
+ )
+ assert message == binascii.unhexlify(example["message"])
+
+ def test_unsupported_padding(self, backend):
+ private_key = rsa.RSAPrivateKey.generate(
+ public_exponent=65537,
+ key_size=512,
+ backend=backend
+ )
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
+ private_key.decrypt(b"somedata", DummyPadding(), backend)
+
+ def test_decrypt_invalid_decrypt(self, backend):
+ private_key = rsa.RSAPrivateKey.generate(
+ public_exponent=65537,
+ key_size=512,
+ backend=backend
+ )
+ with pytest.raises(ValueError):
+ private_key.decrypt(
+ b"\x00" * 64,
+ padding.PKCS1v15(),
+ backend
+ )
+
+ def test_decrypt_ciphertext_too_large(self, backend):
+ private_key = rsa.RSAPrivateKey.generate(
+ public_exponent=65537,
+ key_size=512,
+ backend=backend
+ )
+ with pytest.raises(ValueError):
+ private_key.decrypt(
+ b"\x00" * 65,
+ padding.PKCS1v15(),
+ backend
+ )
+
+ def test_decrypt_ciphertext_too_small(self, backend):
+ private_key = rsa.RSAPrivateKey.generate(
+ public_exponent=65537,
+ key_size=512,
+ backend=backend
+ )
+ ct = binascii.unhexlify(
+ b"50b4c14136bd198c2f3c3ed243fce036e168d56517984a263cd66492b80804f1"
+ b"69d210f2b9bdfb48b12f9ea05009c77da257cc600ccefe3a6283789d8ea0"
+ )
+ with pytest.raises(ValueError):
+ private_key.decrypt(
+ ct,
+ padding.PKCS1v15(),
+ backend
+ )
+
+ def test_rsa_decrypt_invalid_backend(self, backend):
+ pretend_backend = object()
+ private_key = rsa.RSAPrivateKey.generate(65537, 2048, backend)
+
+ with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
+ private_key.decrypt(
+ b"irrelevant",
+ padding.PKCS1v15(),
+ pretend_backend
+ )
+
+ @pytest.mark.parametrize(
+ "vector",
+ _flatten_pkcs1_examples(load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt"),
+ load_pkcs1_vectors
+ ))
+ )
+ def test_decrypt_oaep_vectors(self, vector, backend):
+ private, public, example = vector
+ skey = rsa.RSAPrivateKey(
+ p=private["p"],
+ q=private["q"],
+ private_exponent=private["private_exponent"],
+ dmp1=private["dmp1"],
+ dmq1=private["dmq1"],
+ iqmp=private["iqmp"],
+ public_exponent=private["public_exponent"],
+ modulus=private["modulus"]
+ )
+ message = skey.decrypt(
+ binascii.unhexlify(example["encryption"]),
+ padding.OAEP(
+ mgf=padding.MGF1(algorithm=hashes.SHA1()),
+ algorithm=hashes.SHA1(),
+ label=None
+ ),
+ backend
+ )
+ assert message == binascii.unhexlify(example["message"])
+
+ def test_unsupported_oaep_mgf(self, backend):
+ private_key = rsa.RSAPrivateKey.generate(
+ public_exponent=65537,
+ key_size=512,
+ backend=backend
+ )
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
+ private_key.decrypt(
+ b"ciphertext",
+ padding.OAEP(
+ mgf=DummyMGF(),
+ algorithm=hashes.SHA1(),
+ label=None
+ ),
+ backend
+ )
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index 2e838474..6c3f4c95 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -406,3 +406,21 @@ def rsa_verification_test(backend, params, hash_alg, pad_factory):
verifier.verify()
else:
verifier.verify()
+
+
+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 == rsa.rsa_crt_dmp1(skey.d, skey.p)
+ assert skey.dmq1 == rsa.rsa_crt_dmq1(skey.d, skey.q)
+ assert skey.iqmp == rsa.rsa_crt_iqmp(skey.p, skey.q)
+
+ 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