aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2013-10-18 23:58:33 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2013-10-18 23:58:33 -0700
commit2984b3f8fb433b4cbe5ec6712886db32f597e8af (patch)
treef682add3b8906c8df68895d74ba278ad06f7099d /tests
parent5762647e8d7f53ed9f4abed90626382b6c903ee2 (diff)
parentc21f968301b0d4cc848ea554403e9d9239327803 (diff)
downloadcryptography-2984b3f8fb433b4cbe5ec6712886db32f597e8af.tar.gz
cryptography-2984b3f8fb433b4cbe5ec6712886db32f597e8af.tar.bz2
cryptography-2984b3f8fb433b4cbe5ec6712886db32f597e8af.zip
Merge branch 'master' into bind-pkcs12
Conflicts: cryptography/bindings/openssl/api.py
Diffstat (limited to 'tests')
-rw-r--r--tests/primitives/test_hash_vectors.py111
-rw-r--r--tests/primitives/test_hashes.py78
-rw-r--r--tests/primitives/test_utils.py36
-rw-r--r--tests/primitives/utils.py78
-rw-r--r--tests/test_utils.py58
-rw-r--r--tests/utils.py35
6 files changed, 394 insertions, 2 deletions
diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py
new file mode 100644
index 00000000..51c4b85d
--- /dev/null
+++ b/tests/primitives/test_hash_vectors.py
@@ -0,0 +1,111 @@
+# 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 os
+
+from cryptography.primitives import hashes
+
+from .utils import generate_hash_test, generate_long_string_hash_test
+from ..utils import load_hash_vectors_from_file
+
+
+class TestSHA1(object):
+ test_SHA1 = generate_hash_test(
+ load_hash_vectors_from_file,
+ os.path.join("NIST", "SHABYTE"),
+ [
+ "SHA1LongMsg.rsp",
+ "SHA1ShortMsg.rsp",
+ ],
+ hashes.SHA1,
+ only_if=lambda api: api.supports_hash(hashes.SHA1),
+ skip_message="Does not support SHA1",
+ )
+
+
+class TestSHA224(object):
+ test_SHA224 = generate_hash_test(
+ load_hash_vectors_from_file,
+ os.path.join("NIST", "SHABYTE"),
+ [
+ "SHA224LongMsg.rsp",
+ "SHA224ShortMsg.rsp",
+ ],
+ hashes.SHA224,
+ only_if=lambda api: api.supports_hash(hashes.SHA224),
+ skip_message="Does not support SHA224",
+ )
+
+
+class TestSHA256(object):
+ test_SHA256 = generate_hash_test(
+ load_hash_vectors_from_file,
+ os.path.join("NIST", "SHABYTE"),
+ [
+ "SHA256LongMsg.rsp",
+ "SHA256ShortMsg.rsp",
+ ],
+ hashes.SHA256,
+ only_if=lambda api: api.supports_hash(hashes.SHA256),
+ skip_message="Does not support SHA256",
+ )
+
+
+class TestSHA384(object):
+ test_SHA384 = generate_hash_test(
+ load_hash_vectors_from_file,
+ os.path.join("NIST", "SHABYTE"),
+ [
+ "SHA384LongMsg.rsp",
+ "SHA384ShortMsg.rsp",
+ ],
+ hashes.SHA384,
+ only_if=lambda api: api.supports_hash(hashes.SHA384),
+ skip_message="Does not support SHA384",
+ )
+
+
+class TestSHA512(object):
+ test_SHA512 = generate_hash_test(
+ load_hash_vectors_from_file,
+ os.path.join("NIST", "SHABYTE"),
+ [
+ "SHA512LongMsg.rsp",
+ "SHA512ShortMsg.rsp",
+ ],
+ hashes.SHA512,
+ only_if=lambda api: api.supports_hash(hashes.SHA512),
+ skip_message="Does not support SHA512",
+ )
+
+
+class TestRIPEMD160(object):
+ test_RIPEMD160 = generate_hash_test(
+ load_hash_vectors_from_file,
+ os.path.join("ISO", "ripemd160"),
+ [
+ "ripevectors.txt",
+ ],
+ hashes.RIPEMD160,
+ only_if=lambda api: api.supports_hash(hashes.RIPEMD160),
+ skip_message="Does not support RIPEMD160",
+ )
+
+ test_RIPEMD160_long_string = generate_long_string_hash_test(
+ hashes.RIPEMD160,
+ "52783243c1697bdbe16d37f97f68f08325dc1528",
+ only_if=lambda api: api.supports_hash(hashes.RIPEMD160),
+ skip_message="Does not support RIPEMD160",
+ )
diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py
new file mode 100644
index 00000000..bfb45037
--- /dev/null
+++ b/tests/primitives/test_hashes.py
@@ -0,0 +1,78 @@
+# 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
+
+from cryptography.primitives import hashes
+
+from .utils import generate_base_hash_test
+
+
+class TestSHA1(object):
+ test_SHA1 = generate_base_hash_test(
+ hashes.SHA1,
+ digest_size=20,
+ block_size=64,
+ only_if=lambda api: api.supports_hash(hashes.SHA1),
+ skip_message="Does not support SHA1",
+ )
+
+
+class TestSHA224(object):
+ test_SHA224 = generate_base_hash_test(
+ hashes.SHA224,
+ digest_size=28,
+ block_size=64,
+ only_if=lambda api: api.supports_hash(hashes.SHA224),
+ skip_message="Does not support SHA224",
+ )
+
+
+class TestSHA256(object):
+ test_SHA256 = generate_base_hash_test(
+ hashes.SHA256,
+ digest_size=32,
+ block_size=64,
+ only_if=lambda api: api.supports_hash(hashes.SHA256),
+ skip_message="Does not support SHA256",
+ )
+
+
+class TestSHA384(object):
+ test_SHA384 = generate_base_hash_test(
+ hashes.SHA384,
+ digest_size=48,
+ block_size=128,
+ only_if=lambda api: api.supports_hash(hashes.SHA384),
+ skip_message="Does not support SHA384",
+ )
+
+
+class TestSHA512(object):
+ test_SHA512 = generate_base_hash_test(
+ hashes.SHA512,
+ digest_size=64,
+ block_size=128,
+ only_if=lambda api: api.supports_hash(hashes.SHA512),
+ skip_message="Does not support SHA512",
+ )
+
+
+class TestRIPEMD160(object):
+ test_RIPEMD160 = generate_base_hash_test(
+ hashes.RIPEMD160,
+ digest_size=20,
+ block_size=64,
+ only_if=lambda api: api.supports_hash(hashes.RIPEMD160),
+ skip_message="Does not support RIPEMD160",
+ )
diff --git a/tests/primitives/test_utils.py b/tests/primitives/test_utils.py
index 4666ece7..9888309e 100644
--- a/tests/primitives/test_utils.py
+++ b/tests/primitives/test_utils.py
@@ -1,6 +1,7 @@
import pytest
-from .utils import encrypt_test
+from .utils import (base_hash_test, encrypt_test, hash_test,
+ long_string_hash_test)
class TestEncryptTest(object):
@@ -12,3 +13,36 @@ class TestEncryptTest(object):
skip_message="message!"
)
assert exc_info.value.args[0] == "message!"
+
+
+class TestHashTest(object):
+ def test_skips_if_only_if_returns_false(self):
+ with pytest.raises(pytest.skip.Exception) as exc_info:
+ hash_test(
+ None, None, None,
+ only_if=lambda api: False,
+ skip_message="message!"
+ )
+ assert exc_info.value.args[0] == "message!"
+
+
+class TestBaseHashTest(object):
+ def test_skips_if_only_if_returns_false(self):
+ with pytest.raises(pytest.skip.Exception) as exc_info:
+ base_hash_test(
+ None, None, None, None,
+ only_if=lambda api: False,
+ skip_message="message!"
+ )
+ assert exc_info.value.args[0] == "message!"
+
+
+class TestLongHashTest(object):
+ def test_skips_if_only_if_returns_false(self):
+ with pytest.raises(pytest.skip.Exception) as exc_info:
+ long_string_hash_test(
+ None, None, None,
+ only_if=lambda api: False,
+ skip_message="message!"
+ )
+ assert exc_info.value.args[0] == "message!"
diff --git a/tests/primitives/utils.py b/tests/primitives/utils.py
index 3cf08c28..8b32700b 100644
--- a/tests/primitives/utils.py
+++ b/tests/primitives/utils.py
@@ -40,3 +40,81 @@ def encrypt_test(api, cipher_factory, mode_factory, params, only_if,
actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext))
actual_ciphertext += cipher.finalize()
assert actual_ciphertext == binascii.unhexlify(ciphertext)
+
+
+def generate_hash_test(param_loader, path, file_names, hash_cls,
+ only_if=lambda api: True, skip_message=None):
+ def test_hash(self):
+ for api in _ALL_APIS:
+ for file_name in file_names:
+ for params in param_loader(os.path.join(path, file_name)):
+ yield (
+ hash_test,
+ api,
+ hash_cls,
+ params,
+ only_if,
+ skip_message
+ )
+ return test_hash
+
+
+def hash_test(api, hash_cls, params, only_if, skip_message):
+ if not only_if(api):
+ pytest.skip(skip_message)
+ msg = params[0]
+ md = params[1]
+ m = hash_cls(api=api)
+ m.update(binascii.unhexlify(msg))
+ assert m.hexdigest() == md.replace(" ", "").lower()
+
+
+def generate_base_hash_test(hash_cls, digest_size, block_size,
+ only_if=lambda api: True, skip_message=None):
+ def test_base_hash(self):
+ for api in _ALL_APIS:
+ yield (
+ base_hash_test,
+ api,
+ hash_cls,
+ digest_size,
+ block_size,
+ only_if,
+ skip_message,
+ )
+ return test_base_hash
+
+
+def base_hash_test(api, hash_cls, digest_size, block_size, only_if,
+ skip_message):
+ if not only_if(api):
+ pytest.skip(skip_message)
+ m = hash_cls(api=api)
+ assert m.digest_size == digest_size
+ assert m.block_size == block_size
+ m_copy = m.copy()
+ assert m != m_copy
+ assert m._ctx != m_copy._ctx
+
+
+def generate_long_string_hash_test(hash_factory, md, only_if=lambda api: True,
+ skip_message=None):
+ def test_long_string_hash(self):
+ for api in _ALL_APIS:
+ yield(
+ long_string_hash_test,
+ api,
+ hash_factory,
+ md,
+ only_if,
+ skip_message
+ )
+ return test_long_string_hash
+
+
+def long_string_hash_test(api, hash_factory, md, only_if, skip_message):
+ if not only_if(api):
+ pytest.skip(skip_message)
+ m = hash_factory(api)
+ m.update(b"a" * 1000000)
+ assert m.hexdigest() == md.lower()
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 28e7407b..a9bb6a87 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -13,9 +13,12 @@
import textwrap
+import pytest
+
from .utils import (load_nist_vectors, load_nist_vectors_from_file,
load_cryptrec_vectors, load_cryptrec_vectors_from_file,
- load_openssl_vectors, load_openssl_vectors_from_file)
+ load_openssl_vectors, load_openssl_vectors_from_file, load_hash_vectors,
+ load_hash_vectors_from_file)
def test_load_nist_vectors_encrypt():
@@ -360,3 +363,56 @@ def test_load_openssl_vectors_from_file():
"ciphertext": b"D776379BE0E50825E681DA1A4C980E8E",
},
]
+
+
+def test_load_hash_vectors():
+ vector_data = textwrap.dedent("""
+
+ # http://tools.ietf.org/html/rfc1321
+ [irrelevant]
+
+ Len = 0
+ Msg = 00
+ MD = d41d8cd98f00b204e9800998ecf8427e
+
+ Len = 8
+ Msg = 61
+ MD = 0cc175b9c0f1b6a831c399e269772661
+
+ Len = 24
+ Msg = 616263
+ MD = 900150983cd24fb0d6963f7d28e17f72
+
+ Len = 112
+ Msg = 6d65737361676520646967657374
+ MD = f96b697d7cb7938d525a2f31aaf161d0
+ """).splitlines()
+ assert load_hash_vectors(vector_data) == [
+ (b"", "d41d8cd98f00b204e9800998ecf8427e"),
+ (b"61", "0cc175b9c0f1b6a831c399e269772661"),
+ (b"616263", "900150983cd24fb0d6963f7d28e17f72"),
+ (b"6d65737361676520646967657374", "f96b697d7cb7938d525a2f31aaf161d0"),
+ ]
+
+
+def test_load_hash_vectors_bad_data():
+ vector_data = textwrap.dedent("""
+ # http://tools.ietf.org/html/rfc1321
+
+ Len = 0
+ Msg = 00
+ UNKNOWN=Hello World
+ """).splitlines()
+ with pytest.raises(ValueError):
+ load_hash_vectors(vector_data)
+
+
+def test_load_hash_vectors_from_file():
+ test_list = load_hash_vectors_from_file("RFC/MD5/rfc-1321.txt")
+ assert len(test_list) == 7
+ assert test_list[:4] == [
+ (b"", "d41d8cd98f00b204e9800998ecf8427e"),
+ (b"61", "0cc175b9c0f1b6a831c399e269772661"),
+ (b"616263", "900150983cd24fb0d6963f7d28e17f72"),
+ (b"6d65737361676520646967657374", "f96b697d7cb7938d525a2f31aaf161d0"),
+ ]
diff --git a/tests/utils.py b/tests/utils.py
index 6b1cfd79..03b780f8 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -119,3 +119,38 @@ def load_openssl_vectors(vector_data):
"ciphertext": vector[4].encode("ascii"),
})
return vectors
+
+
+def load_hash_vectors(vector_data):
+ vectors = []
+
+ for line in vector_data:
+ line = line.strip()
+
+ if not line or line.startswith("#") or line.startswith("["):
+ continue
+
+ if line.startswith("Len"):
+ length = int(line.split(" = ")[1])
+ elif line.startswith("Msg"):
+ """
+ In the NIST vectors they have chosen to represent an empty
+ string as hex 00, which is of course not actually an empty
+ string. So we parse the provided length and catch this edge case.
+ """
+ msg = line.split(" = ")[1].encode("ascii") if length > 0 else b""
+ elif line.startswith("MD"):
+ md = line.split(" = ")[1]
+ # after MD is found the Msg+MD tuple is complete
+ vectors.append((msg, md))
+ else:
+ raise ValueError("Unknown line in hash vector")
+ return vectors
+
+
+def load_hash_vectors_from_file(filename):
+ base = os.path.join(
+ os.path.dirname(__file__), "primitives", "vectors"
+ )
+ with open(os.path.join(base, filename), "r") as vector_file:
+ return load_hash_vectors(vector_file)