summaryrefslogtreecommitdiffstats
path: root/lib/Crypto/SelfTest/Hash
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Crypto/SelfTest/Hash')
-rw-r--r--lib/Crypto/SelfTest/Hash/__init__.py61
-rw-r--r--lib/Crypto/SelfTest/Hash/common.py290
-rw-r--r--lib/Crypto/SelfTest/Hash/test_BLAKE2.py482
-rw-r--r--lib/Crypto/SelfTest/Hash/test_CMAC.py448
-rw-r--r--lib/Crypto/SelfTest/Hash/test_HMAC.py548
-rw-r--r--lib/Crypto/SelfTest/Hash/test_KMAC.py346
-rw-r--r--lib/Crypto/SelfTest/Hash/test_KangarooTwelve.py324
-rw-r--r--lib/Crypto/SelfTest/Hash/test_MD2.py62
-rw-r--r--lib/Crypto/SelfTest/Hash/test_MD4.py64
-rw-r--r--lib/Crypto/SelfTest/Hash/test_MD5.py94
-rw-r--r--lib/Crypto/SelfTest/Hash/test_Poly1305.py542
-rw-r--r--lib/Crypto/SelfTest/Hash/test_RIPEMD160.py71
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA1.py84
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA224.py63
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA256.py94
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA384.py61
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA3_224.py79
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA3_256.py80
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA3_384.py79
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA3_512.py79
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHA512.py140
-rw-r--r--lib/Crypto/SelfTest/Hash/test_SHAKE.py143
-rw-r--r--lib/Crypto/SelfTest/Hash/test_TupleHash.py286
-rw-r--r--lib/Crypto/SelfTest/Hash/test_cSHAKE.py178
-rw-r--r--lib/Crypto/SelfTest/Hash/test_keccak.py250
25 files changed, 4948 insertions, 0 deletions
diff --git a/lib/Crypto/SelfTest/Hash/__init__.py b/lib/Crypto/SelfTest/Hash/__init__.py
new file mode 100644
index 0000000..008a810
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/__init__.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/__init__.py: Self-test for hash modules
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test for hash modules"""
+
+__revision__ = "$Id$"
+
+def get_tests(config={}):
+ tests = []
+ from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_RIPEMD160; tests += test_RIPEMD160.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA1; tests += test_SHA1.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA512; tests += test_SHA512.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA3_224; tests += test_SHA3_224.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA3_256; tests += test_SHA3_256.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA3_384; tests += test_SHA3_384.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHA3_512; tests += test_SHA3_512.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_keccak; tests += test_keccak.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_SHAKE; tests += test_SHAKE.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_BLAKE2; tests += test_BLAKE2.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_Poly1305; tests += test_Poly1305.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_cSHAKE; tests += test_cSHAKE.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_KMAC; tests += test_KMAC.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_TupleHash; tests += test_TupleHash.get_tests(config=config)
+ from Crypto.SelfTest.Hash import test_KangarooTwelve; tests += test_KangarooTwelve.get_tests(config=config)
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/common.py b/lib/Crypto/SelfTest/Hash/common.py
new file mode 100644
index 0000000..1578667
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/common.py
@@ -0,0 +1,290 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-testing for PyCrypto hash modules"""
+
+import re
+import sys
+import unittest
+import binascii
+import Crypto.Hash
+from binascii import hexlify, unhexlify
+from Crypto.Util.py3compat import b, tobytes
+from Crypto.Util.strxor import strxor_c
+
+def t2b(hex_string):
+ shorter = re.sub(br'\s+', b'', tobytes(hex_string))
+ return unhexlify(shorter)
+
+
+class HashDigestSizeSelfTest(unittest.TestCase):
+
+ def __init__(self, hashmod, description, expected, extra_params):
+ unittest.TestCase.__init__(self)
+ self.hashmod = hashmod
+ self.expected = expected
+ self.description = description
+ self.extra_params = extra_params
+
+ def shortDescription(self):
+ return self.description
+
+ def runTest(self):
+ if "truncate" not in self.extra_params:
+ self.assertTrue(hasattr(self.hashmod, "digest_size"))
+ self.assertEqual(self.hashmod.digest_size, self.expected)
+ h = self.hashmod.new(**self.extra_params)
+ self.assertTrue(hasattr(h, "digest_size"))
+ self.assertEqual(h.digest_size, self.expected)
+
+
+class HashSelfTest(unittest.TestCase):
+
+ def __init__(self, hashmod, description, expected, input, extra_params):
+ unittest.TestCase.__init__(self)
+ self.hashmod = hashmod
+ self.expected = expected.lower()
+ self.input = input
+ self.description = description
+ self.extra_params = extra_params
+
+ def shortDescription(self):
+ return self.description
+
+ def runTest(self):
+ h = self.hashmod.new(**self.extra_params)
+ h.update(self.input)
+
+ out1 = binascii.b2a_hex(h.digest())
+ out2 = h.hexdigest()
+
+ h = self.hashmod.new(self.input, **self.extra_params)
+
+ out3 = h.hexdigest()
+ out4 = binascii.b2a_hex(h.digest())
+
+ # PY3K: hexdigest() should return str(), and digest() bytes
+ self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest()
+ if sys.version_info[0] == 2:
+ self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest()
+ self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest()
+ else:
+ self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest()
+ self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest()
+ self.assertEqual(self.expected, out4) # h = .new(data); h.digest()
+
+ # Verify that the .new() method produces a fresh hash object, except
+ # for MD5 and SHA1, which are hashlib objects. (But test any .new()
+ # method that does exist.)
+ if self.hashmod.__name__ not in ('Crypto.Hash.MD5', 'Crypto.Hash.SHA1') or hasattr(h, 'new'):
+ h2 = h.new()
+ h2.update(self.input)
+ out5 = binascii.b2a_hex(h2.digest())
+ self.assertEqual(self.expected, out5)
+
+
+class HashTestOID(unittest.TestCase):
+ def __init__(self, hashmod, oid, extra_params):
+ unittest.TestCase.__init__(self)
+ self.hashmod = hashmod
+ self.oid = oid
+ self.extra_params = extra_params
+
+ def runTest(self):
+ h = self.hashmod.new(**self.extra_params)
+ self.assertEqual(h.oid, self.oid)
+
+
+class ByteArrayTest(unittest.TestCase):
+
+ def __init__(self, module, extra_params):
+ unittest.TestCase.__init__(self)
+ self.module = module
+ self.extra_params = extra_params
+
+ def runTest(self):
+ data = b("\x00\x01\x02")
+
+ # Data can be a bytearray (during initialization)
+ ba = bytearray(data)
+
+ h1 = self.module.new(data, **self.extra_params)
+ h2 = self.module.new(ba, **self.extra_params)
+ ba[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a bytearray (during operation)
+ ba = bytearray(data)
+
+ h1 = self.module.new(**self.extra_params)
+ h2 = self.module.new(**self.extra_params)
+
+ h1.update(data)
+ h2.update(ba)
+
+ ba[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class MemoryViewTest(unittest.TestCase):
+
+ def __init__(self, module, extra_params):
+ unittest.TestCase.__init__(self)
+ self.module = module
+ self.extra_params = extra_params
+
+ def runTest(self):
+
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in get_mv_ro, get_mv_rw:
+
+ # Data can be a memoryview (during initialization)
+ mv = get_mv(data)
+
+ h1 = self.module.new(data, **self.extra_params)
+ h2 = self.module.new(mv, **self.extra_params)
+ if not mv.readonly:
+ mv[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a memoryview (during operation)
+ mv = get_mv(data)
+
+ h1 = self.module.new(**self.extra_params)
+ h2 = self.module.new(**self.extra_params)
+ h1.update(data)
+ h2.update(mv)
+ if not mv.readonly:
+ mv[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class MACSelfTest(unittest.TestCase):
+
+ def __init__(self, module, description, result, data, key, params):
+ unittest.TestCase.__init__(self)
+ self.module = module
+ self.result = t2b(result)
+ self.data = t2b(data)
+ self.key = t2b(key)
+ self.params = params
+ self.description = description
+
+ def shortDescription(self):
+ return self.description
+
+ def runTest(self):
+
+ result_hex = hexlify(self.result)
+
+ # Verify result
+ h = self.module.new(self.key, **self.params)
+ h.update(self.data)
+ self.assertEqual(self.result, h.digest())
+ self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest())
+
+ # Verify that correct MAC does not raise any exception
+ h.verify(self.result)
+ h.hexverify(result_hex)
+
+ # Verify that incorrect MAC does raise ValueError exception
+ wrong_mac = strxor_c(self.result, 255)
+ self.assertRaises(ValueError, h.verify, wrong_mac)
+ self.assertRaises(ValueError, h.hexverify, "4556")
+
+ # Verify again, with data passed to new()
+ h = self.module.new(self.key, self.data, **self.params)
+ self.assertEqual(self.result, h.digest())
+ self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest())
+
+ # Test .copy()
+ try:
+ h = self.module.new(self.key, self.data, **self.params)
+ h2 = h.copy()
+ h3 = h.copy()
+
+ # Verify that changing the copy does not change the original
+ h2.update(b"bla")
+ self.assertEqual(h3.digest(), self.result)
+
+ # Verify that both can reach the same state
+ h.update(b"bla")
+ self.assertEqual(h.digest(), h2.digest())
+ except NotImplementedError:
+ pass
+
+ # PY3K: Check that hexdigest() returns str and digest() returns bytes
+ self.assertTrue(isinstance(h.digest(), type(b"")))
+ self.assertTrue(isinstance(h.hexdigest(), type("")))
+
+ # PY3K: Check that .hexverify() accepts bytes or str
+ h.hexverify(h.hexdigest())
+ h.hexverify(h.hexdigest().encode('ascii'))
+
+
+def make_hash_tests(module, module_name, test_data, digest_size, oid=None,
+ extra_params={}):
+ tests = []
+ for i in range(len(test_data)):
+ row = test_data[i]
+ (expected, input) = map(tobytes,row[0:2])
+ if len(row) < 3:
+ description = repr(input)
+ else:
+ description = row[2]
+ name = "%s #%d: %s" % (module_name, i+1, description)
+ tests.append(HashSelfTest(module, name, expected, input, extra_params))
+
+ name = "%s #%d: digest_size" % (module_name, len(test_data) + 1)
+ tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params))
+
+ if oid is not None:
+ tests.append(HashTestOID(module, oid, extra_params))
+
+ tests.append(ByteArrayTest(module, extra_params))
+
+ tests.append(MemoryViewTest(module, extra_params))
+
+ return tests
+
+
+def make_mac_tests(module, module_name, test_data):
+ tests = []
+ for i, row in enumerate(test_data):
+ if len(row) == 4:
+ (key, data, results, description, params) = list(row) + [ {} ]
+ else:
+ (key, data, results, description, params) = row
+ name = "%s #%d: %s" % (module_name, i+1, description)
+ tests.append(MACSelfTest(module, name, results, data, key, params))
+ return tests
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_BLAKE2.py b/lib/Crypto/SelfTest/Hash/test_BLAKE2.py
new file mode 100644
index 0000000..f953eab
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_BLAKE2.py
@@ -0,0 +1,482 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+import os
+import re
+import unittest
+import warnings
+from binascii import unhexlify, hexlify
+
+from Crypto.Util.py3compat import tobytes
+from Crypto.Util.strxor import strxor_c
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import BLAKE2b, BLAKE2s
+
+
+class Blake2Test(unittest.TestCase):
+
+ def test_new_positive(self):
+
+ h = self.BLAKE2.new(digest_bits=self.max_bits)
+ for new_func in self.BLAKE2.new, h.new:
+
+ for dbits in range(8, self.max_bits + 1, 8):
+ hobj = new_func(digest_bits=dbits)
+ self.assertEqual(hobj.digest_size, dbits // 8)
+
+ for dbytes in range(1, self.max_bytes + 1):
+ hobj = new_func(digest_bytes=dbytes)
+ self.assertEqual(hobj.digest_size, dbytes)
+
+ digest1 = new_func(data=b"\x90", digest_bytes=self.max_bytes).digest()
+ digest2 = new_func(digest_bytes=self.max_bytes).update(b"\x90").digest()
+ self.assertEqual(digest1, digest2)
+
+ new_func(data=b"A", key=b"5", digest_bytes=self.max_bytes)
+
+ hobj = h.new()
+ self.assertEqual(hobj.digest_size, self.max_bytes)
+
+ def test_new_negative(self):
+
+ h = self.BLAKE2.new(digest_bits=self.max_bits)
+ for new_func in self.BLAKE2.new, h.new:
+ self.assertRaises(TypeError, new_func,
+ digest_bytes=self.max_bytes,
+ digest_bits=self.max_bits)
+ self.assertRaises(ValueError, new_func, digest_bytes=0)
+ self.assertRaises(ValueError, new_func,
+ digest_bytes=self.max_bytes + 1)
+ self.assertRaises(ValueError, new_func, digest_bits=7)
+ self.assertRaises(ValueError, new_func, digest_bits=15)
+ self.assertRaises(ValueError, new_func,
+ digest_bits=self.max_bits + 1)
+ self.assertRaises(TypeError, new_func,
+ digest_bytes=self.max_bytes,
+ key=u"string")
+ self.assertRaises(TypeError, new_func,
+ digest_bytes=self.max_bytes,
+ data=u"string")
+
+ def test_default_digest_size(self):
+ digest = self.BLAKE2.new(data=b'abc').digest()
+ self.assertEqual(len(digest), self.max_bytes)
+
+ def test_update(self):
+ pieces = [b"\x0A" * 200, b"\x14" * 300]
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes)
+ h.update(pieces[0]).update(pieces[1])
+ digest = h.digest()
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes)
+ h.update(pieces[0] + pieces[1])
+ self.assertEqual(h.digest(), digest)
+
+ def test_update_negative(self):
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes)
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes)
+ digest = h.digest()
+
+ # hexdigest does not change the state
+ self.assertEqual(h.digest(), digest)
+ # digest returns a byte string
+ self.assertTrue(isinstance(digest, type(b"digest")))
+
+ def test_update_after_digest(self):
+ msg = b"rrrrttt"
+
+ # Normally, update() cannot be done after digest()
+ h = self.BLAKE2.new(digest_bits=256, data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = self.BLAKE2.new(digest_bits=256, data=msg).digest()
+
+ # With the proper flag, it is allowed
+ h = self.BLAKE2.new(digest_bits=256, data=msg[:4], update_after_digest=True)
+ self.assertEqual(h.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h.update(msg[4:])
+ self.assertEqual(h.digest(), dig2)
+
+ def test_hex_digest(self):
+ mac = self.BLAKE2.new(digest_bits=self.max_bits)
+ digest = mac.digest()
+ hexdigest = mac.hexdigest()
+
+ # hexdigest is equivalent to digest
+ self.assertEqual(hexlify(digest), tobytes(hexdigest))
+ # hexdigest does not change the state
+ self.assertEqual(mac.hexdigest(), hexdigest)
+ # hexdigest returns a string
+ self.assertTrue(isinstance(hexdigest, type("digest")))
+
+ def test_verify(self):
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4")
+ mac = h.digest()
+ h.verify(mac)
+ wrong_mac = strxor_c(mac, 255)
+ self.assertRaises(ValueError, h.verify, wrong_mac)
+
+ def test_hexverify(self):
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4")
+ mac = h.hexdigest()
+ h.hexverify(mac)
+ self.assertRaises(ValueError, h.hexverify, "4556")
+
+ def test_oid(self):
+
+ prefix = "1.3.6.1.4.1.1722.12.2." + self.oid_variant + "."
+
+ for digest_bits in self.digest_bits_oid:
+ h = self.BLAKE2.new(digest_bits=digest_bits)
+ self.assertEqual(h.oid, prefix + str(digest_bits // 8))
+
+ h = self.BLAKE2.new(digest_bits=digest_bits, key=b"secret")
+ self.assertRaises(AttributeError, lambda: h.oid)
+
+ for digest_bits in (8, self.max_bits):
+ if digest_bits in self.digest_bits_oid:
+ continue
+ self.assertRaises(AttributeError, lambda: h.oid)
+
+ def test_bytearray(self):
+
+ key = b'0' * 16
+ data = b"\x00\x01\x02"
+
+ # Data and key can be a bytearray (during initialization)
+ key_ba = bytearray(key)
+ data_ba = bytearray(data)
+
+ h1 = self.BLAKE2.new(data=data, key=key)
+ h2 = self.BLAKE2.new(data=data_ba, key=key_ba)
+ key_ba[:1] = b'\xFF'
+ data_ba[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a bytearray (during operation)
+ data_ba = bytearray(data)
+
+ h1 = self.BLAKE2.new()
+ h2 = self.BLAKE2.new()
+ h1.update(data)
+ h2.update(data_ba)
+ data_ba[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ def test_memoryview(self):
+
+ key = b'0' * 16
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in (get_mv_ro, get_mv_rw):
+
+ # Data and key can be a memoryview (during initialization)
+ key_mv = get_mv(key)
+ data_mv = get_mv(data)
+
+ h1 = self.BLAKE2.new(data=data, key=key)
+ h2 = self.BLAKE2.new(data=data_mv, key=key_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+ key_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a memoryview (during operation)
+ data_mv = get_mv(data)
+
+ h1 = self.BLAKE2.new()
+ h2 = self.BLAKE2.new()
+ h1.update(data)
+ h2.update(data_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class Blake2bTest(Blake2Test):
+ #: Module
+ BLAKE2 = BLAKE2b
+ #: Max output size (in bits)
+ max_bits = 512
+ #: Max output size (in bytes)
+ max_bytes = 64
+ #: Bit size of the digests for which an ASN OID exists
+ digest_bits_oid = (160, 256, 384, 512)
+ # http://tools.ietf.org/html/draft-saarinen-blake2-02
+ oid_variant = "1"
+
+
+class Blake2sTest(Blake2Test):
+ #: Module
+ BLAKE2 = BLAKE2s
+ #: Max output size (in bits)
+ max_bits = 256
+ #: Max output size (in bytes)
+ max_bytes = 32
+ #: Bit size of the digests for which an ASN OID exists
+ digest_bits_oid = (128, 160, 224, 256)
+ # http://tools.ietf.org/html/draft-saarinen-blake2-02
+ oid_variant = "2"
+
+
+class Blake2OfficialTestVector(unittest.TestCase):
+
+ def _load_tests(self, test_vector_file):
+ expected = "in"
+ test_vectors = []
+ with open(test_vector_file, "rt") as test_vector_fd:
+ for line_number, line in enumerate(test_vector_fd):
+
+ if line.strip() == "" or line.startswith("#"):
+ continue
+
+ res = re.match("%s:\t([0-9A-Fa-f]*)" % expected, line)
+ if not res:
+ raise ValueError("Incorrect test vector format (line %d)"
+ % line_number)
+
+ if res.group(1):
+ bin_value = unhexlify(tobytes(res.group(1)))
+ else:
+ bin_value = b""
+ if expected == "in":
+ input_data = bin_value
+ expected = "key"
+ elif expected == "key":
+ key = bin_value
+ expected = "hash"
+ else:
+ result = bin_value
+ expected = "in"
+ test_vectors.append((input_data, key, result))
+ return test_vectors
+
+ def setUp(self):
+
+ dir_comps = ("Hash", self.name)
+ file_name = self.name.lower() + "-test.txt"
+ self.description = "%s tests" % self.name
+
+ try:
+ import pycryptodome_test_vectors # type: ignore
+ except ImportError:
+ warnings.warn("Warning: skipping extended tests for %s" % self.name,
+ UserWarning)
+ self.test_vectors = []
+ return
+
+ init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
+ full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name)
+ self.test_vectors = self._load_tests(full_file_name)
+
+ def runTest(self):
+ for (input_data, key, result) in self.test_vectors:
+ mac = self.BLAKE2.new(key=key, digest_bytes=self.max_bytes)
+ mac.update(input_data)
+ self.assertEqual(mac.digest(), result)
+
+
+class Blake2bOfficialTestVector(Blake2OfficialTestVector):
+ #: Module
+ BLAKE2 = BLAKE2b
+ #: Hash name
+ name = "BLAKE2b"
+ #: Max digest size
+ max_bytes = 64
+
+
+class Blake2sOfficialTestVector(Blake2OfficialTestVector):
+ #: Module
+ BLAKE2 = BLAKE2s
+ #: Hash name
+ name = "BLAKE2s"
+ #: Max digest size
+ max_bytes = 32
+
+
+class Blake2TestVector1(unittest.TestCase):
+
+ def _load_tests(self, test_vector_file):
+ test_vectors = []
+ with open(test_vector_file, "rt") as test_vector_fd:
+ for line_number, line in enumerate(test_vector_fd):
+ if line.strip() == "" or line.startswith("#"):
+ continue
+ res = re.match("digest: ([0-9A-Fa-f]*)", line)
+ if not res:
+ raise ValueError("Incorrect test vector format (line %d)"
+ % line_number)
+
+ test_vectors.append(unhexlify(tobytes(res.group(1))))
+ return test_vectors
+
+ def setUp(self):
+ dir_comps = ("Hash", self.name)
+ file_name = "tv1.txt"
+ self.description = "%s tests" % self.name
+
+ try:
+ import pycryptodome_test_vectors
+ except ImportError:
+ warnings.warn("Warning: skipping extended tests for %s" % self.name,
+ UserWarning)
+ self.test_vectors = []
+ return
+
+ init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
+ full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name)
+ self.test_vectors = self._load_tests(full_file_name)
+
+ def runTest(self):
+
+ for tv in self.test_vectors:
+ digest_bytes = len(tv)
+ next_data = b""
+ for _ in range(100):
+ h = self.BLAKE2.new(digest_bytes=digest_bytes)
+ h.update(next_data)
+ next_data = h.digest() + next_data
+ self.assertEqual(h.digest(), tv)
+
+
+class Blake2bTestVector1(Blake2TestVector1):
+ #: Module
+ BLAKE2 = BLAKE2b
+ #: Hash name
+ name = "BLAKE2b"
+
+
+class Blake2sTestVector1(Blake2TestVector1):
+ #: Module
+ BLAKE2 = BLAKE2s
+ #: Hash name
+ name = "BLAKE2s"
+
+
+class Blake2TestVector2(unittest.TestCase):
+
+ def _load_tests(self, test_vector_file):
+ test_vectors = []
+ with open(test_vector_file, "rt") as test_vector_fd:
+ for line_number, line in enumerate(test_vector_fd):
+ if line.strip() == "" or line.startswith("#"):
+ continue
+ res = re.match(r"digest\(([0-9]+)\): ([0-9A-Fa-f]*)", line)
+ if not res:
+ raise ValueError("Incorrect test vector format (line %d)"
+ % line_number)
+ key_size = int(res.group(1))
+ result = unhexlify(tobytes(res.group(2)))
+ test_vectors.append((key_size, result))
+ return test_vectors
+
+ def setUp(self):
+ dir_comps = ("Hash", self.name)
+ file_name = "tv2.txt"
+ self.description = "%s tests" % self.name
+
+ try:
+ import pycryptodome_test_vectors # type: ignore
+ except ImportError:
+ warnings.warn("Warning: skipping extended tests for %s" % self.name,
+ UserWarning)
+ self.test_vectors = []
+ return
+
+ init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
+ full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name)
+ self.test_vectors = self._load_tests(full_file_name)
+
+ def runTest(self):
+
+ for key_size, result in self.test_vectors:
+ next_data = b""
+ for _ in range(100):
+ h = self.BLAKE2.new(digest_bytes=self.max_bytes,
+ key=b"A" * key_size)
+ h.update(next_data)
+ next_data = h.digest() + next_data
+ self.assertEqual(h.digest(), result)
+
+
+class Blake2bTestVector2(Blake2TestVector1):
+ #: Module
+ BLAKE2 = BLAKE2b
+ #: Hash name
+ name = "BLAKE2b"
+ #: Max digest size in bytes
+ max_bytes = 64
+
+
+class Blake2sTestVector2(Blake2TestVector1):
+ #: Module
+ BLAKE2 = BLAKE2s
+ #: Hash name
+ name = "BLAKE2s"
+ #: Max digest size in bytes
+ max_bytes = 32
+
+
+def get_tests(config={}):
+ tests = []
+
+ tests += list_test_cases(Blake2bTest)
+ tests.append(Blake2bOfficialTestVector())
+ tests.append(Blake2bTestVector1())
+ tests.append(Blake2bTestVector2())
+
+ tests += list_test_cases(Blake2sTest)
+ tests.append(Blake2sOfficialTestVector())
+ tests.append(Blake2sTestVector1())
+ tests.append(Blake2sTestVector2())
+
+ return tests
+
+
+if __name__ == '__main__':
+ import unittest
+ def suite():
+ return unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_CMAC.py b/lib/Crypto/SelfTest/Hash/test_CMAC.py
new file mode 100644
index 0000000..f4763f2
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_CMAC.py
@@ -0,0 +1,448 @@
+#
+# SelfTest/Hash/CMAC.py: Self-test for the CMAC module
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.CMAC"""
+
+import json
+import unittest
+from binascii import unhexlify
+
+from Crypto.Util.py3compat import tobytes
+
+from Crypto.Hash import CMAC
+from Crypto.Cipher import AES, DES3
+from Crypto.Hash import SHAKE128
+
+from Crypto.Util.strxor import strxor
+
+from Crypto.SelfTest.st_common import list_test_cases
+from Crypto.SelfTest.loader import load_test_vectors_wycheproof
+
+# This is a list of (key, data, result, description, module) tuples.
+test_data = [
+
+ ## Test vectors from RFC 4493 ##
+ ## The are also in NIST SP 800 38B D.2 ##
+ ( '2b7e151628aed2a6abf7158809cf4f3c',
+ '',
+ 'bb1d6929e95937287fa37d129b756746',
+ 'RFC 4493 #1',
+ AES
+ ),
+
+ ( '2b7e151628aed2a6abf7158809cf4f3c',
+ '6bc1bee22e409f96e93d7e117393172a',
+ '070a16b46b4d4144f79bdd9dd04a287c',
+ 'RFC 4493 #2',
+ AES
+ ),
+
+ ( '2b7e151628aed2a6abf7158809cf4f3c',
+ '6bc1bee22e409f96e93d7e117393172a'+
+ 'ae2d8a571e03ac9c9eb76fac45af8e51'+
+ '30c81c46a35ce411',
+ 'dfa66747de9ae63030ca32611497c827',
+ 'RFC 4493 #3',
+ AES
+ ),
+
+ ( '2b7e151628aed2a6abf7158809cf4f3c',
+ '6bc1bee22e409f96e93d7e117393172a'+
+ 'ae2d8a571e03ac9c9eb76fac45af8e51'+
+ '30c81c46a35ce411e5fbc1191a0a52ef'+
+ 'f69f2445df4f9b17ad2b417be66c3710',
+ '51f0bebf7e3b9d92fc49741779363cfe',
+ 'RFC 4493 #4',
+ AES
+ ),
+
+ ## The rest of Appendix D of NIST SP 800 38B
+ ## was not totally correct.
+ ## Values in Examples 14, 15, 18, and 19 were wrong.
+ ## The updated test values are published in:
+ ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
+
+ ( '8e73b0f7da0e6452c810f32b809079e5'+
+ '62f8ead2522c6b7b',
+ '',
+ 'd17ddf46adaacde531cac483de7a9367',
+ 'NIST SP 800 38B D.2 Example 5',
+ AES
+ ),
+
+ ( '8e73b0f7da0e6452c810f32b809079e5'+
+ '62f8ead2522c6b7b',
+ '6bc1bee22e409f96e93d7e117393172a',
+ '9e99a7bf31e710900662f65e617c5184',
+ 'NIST SP 800 38B D.2 Example 6',
+ AES
+ ),
+
+ ( '8e73b0f7da0e6452c810f32b809079e5'+
+ '62f8ead2522c6b7b',
+ '6bc1bee22e409f96e93d7e117393172a'+
+ 'ae2d8a571e03ac9c9eb76fac45af8e51'+
+ '30c81c46a35ce411',
+ '8a1de5be2eb31aad089a82e6ee908b0e',
+ 'NIST SP 800 38B D.2 Example 7',
+ AES
+ ),
+
+ ( '8e73b0f7da0e6452c810f32b809079e5'+
+ '62f8ead2522c6b7b',
+ '6bc1bee22e409f96e93d7e117393172a'+
+ 'ae2d8a571e03ac9c9eb76fac45af8e51'+
+ '30c81c46a35ce411e5fbc1191a0a52ef'+
+ 'f69f2445df4f9b17ad2b417be66c3710',
+ 'a1d5df0eed790f794d77589659f39a11',
+ 'NIST SP 800 38B D.2 Example 8',
+ AES
+ ),
+
+ ( '603deb1015ca71be2b73aef0857d7781'+
+ '1f352c073b6108d72d9810a30914dff4',
+ '',
+ '028962f61b7bf89efc6b551f4667d983',
+ 'NIST SP 800 38B D.3 Example 9',
+ AES
+ ),
+
+ ( '603deb1015ca71be2b73aef0857d7781'+
+ '1f352c073b6108d72d9810a30914dff4',
+ '6bc1bee22e409f96e93d7e117393172a',
+ '28a7023f452e8f82bd4bf28d8c37c35c',
+ 'NIST SP 800 38B D.3 Example 10',
+ AES
+ ),
+
+ ( '603deb1015ca71be2b73aef0857d7781'+
+ '1f352c073b6108d72d9810a30914dff4',
+ '6bc1bee22e409f96e93d7e117393172a'+
+ 'ae2d8a571e03ac9c9eb76fac45af8e51'+
+ '30c81c46a35ce411',
+ 'aaf3d8f1de5640c232f5b169b9c911e6',
+ 'NIST SP 800 38B D.3 Example 11',
+ AES
+ ),
+
+ ( '603deb1015ca71be2b73aef0857d7781'+
+ '1f352c073b6108d72d9810a30914dff4',
+ '6bc1bee22e409f96e93d7e117393172a'+
+ 'ae2d8a571e03ac9c9eb76fac45af8e51'+
+ '30c81c46a35ce411e5fbc1191a0a52ef'+
+ 'f69f2445df4f9b17ad2b417be66c3710',
+ 'e1992190549f6ed5696a2c056c315410',
+ 'NIST SP 800 38B D.3 Example 12',
+ AES
+ ),
+
+ ( '8aa83bf8cbda1062'+
+ '0bc1bf19fbb6cd58'+
+ 'bc313d4a371ca8b5',
+ '',
+ 'b7a688e122ffaf95',
+ 'NIST SP 800 38B D.4 Example 13',
+ DES3
+ ),
+
+ ( '8aa83bf8cbda1062'+
+ '0bc1bf19fbb6cd58'+
+ 'bc313d4a371ca8b5',
+ '6bc1bee22e409f96',
+ '8e8f293136283797',
+ 'NIST SP 800 38B D.4 Example 14',
+ DES3
+ ),
+
+ ( '8aa83bf8cbda1062'+
+ '0bc1bf19fbb6cd58'+
+ 'bc313d4a371ca8b5',
+ '6bc1bee22e409f96'+
+ 'e93d7e117393172a'+
+ 'ae2d8a57',
+ '743ddbe0ce2dc2ed',
+ 'NIST SP 800 38B D.4 Example 15',
+ DES3
+ ),
+
+ ( '8aa83bf8cbda1062'+
+ '0bc1bf19fbb6cd58'+
+ 'bc313d4a371ca8b5',
+ '6bc1bee22e409f96'+
+ 'e93d7e117393172a'+
+ 'ae2d8a571e03ac9c'+
+ '9eb76fac45af8e51',
+ '33e6b1092400eae5',
+ 'NIST SP 800 38B D.4 Example 16',
+ DES3
+ ),
+
+ ( '4cf15134a2850dd5'+
+ '8a3d10ba80570d38',
+ '',
+ 'bd2ebf9a3ba00361',
+ 'NIST SP 800 38B D.7 Example 17',
+ DES3
+ ),
+
+ ( '4cf15134a2850dd5'+
+ '8a3d10ba80570d38',
+ '6bc1bee22e409f96',
+ '4ff2ab813c53ce83',
+ 'NIST SP 800 38B D.7 Example 18',
+ DES3
+ ),
+
+ ( '4cf15134a2850dd5'+
+ '8a3d10ba80570d38',
+ '6bc1bee22e409f96'+
+ 'e93d7e117393172a'+
+ 'ae2d8a57',
+ '62dd1b471902bd4e',
+ 'NIST SP 800 38B D.7 Example 19',
+ DES3
+ ),
+
+ ( '4cf15134a2850dd5'+
+ '8a3d10ba80570d38',
+ '6bc1bee22e409f96'+
+ 'e93d7e117393172a'+
+ 'ae2d8a571e03ac9c'+
+ '9eb76fac45af8e51',
+ '31b1e431dabc4eb8',
+ 'NIST SP 800 38B D.7 Example 20',
+ DES3
+ ),
+
+]
+
+
+def get_tag_random(tag, length):
+ return SHAKE128.new(data=tobytes(tag)).read(length)
+
+
+class TestCMAC(unittest.TestCase):
+
+ def test_internal_caching(self):
+ """Verify that internal caching is implemented correctly"""
+
+ data_to_mac = get_tag_random("data_to_mac", 128)
+ key = get_tag_random("key", 16)
+ ref_mac = CMAC.new(key, msg=data_to_mac, ciphermod=AES).digest()
+
+ # Break up in chunks of different length
+ # The result must always be the same
+ for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
+
+ chunks = [data_to_mac[i:i+chunk_length] for i in
+ range(0, len(data_to_mac), chunk_length)]
+
+ mac = CMAC.new(key, ciphermod=AES)
+ for chunk in chunks:
+ mac.update(chunk)
+ self.assertEqual(ref_mac, mac.digest())
+
+ def test_update_after_digest(self):
+ msg = b"rrrrttt"
+ key = b"4" * 16
+
+ # Normally, update() cannot be done after digest()
+ h = CMAC.new(key, msg[:4], ciphermod=AES)
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = CMAC.new(key, msg, ciphermod=AES).digest()
+
+ # With the proper flag, it is allowed
+ h2 = CMAC.new(key, msg[:4], ciphermod=AES, update_after_digest=True)
+ self.assertEqual(h2.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h2.update(msg[4:])
+ self.assertEqual(h2.digest(), dig2)
+
+
+class ByteArrayTests(unittest.TestCase):
+
+ def runTest(self):
+
+ key = b"0" * 16
+ data = b"\x00\x01\x02"
+
+ # Data and key can be a bytearray (during initialization)
+ key_ba = bytearray(key)
+ data_ba = bytearray(data)
+
+ h1 = CMAC.new(key, data, ciphermod=AES)
+ h2 = CMAC.new(key_ba, data_ba, ciphermod=AES)
+ key_ba[:1] = b'\xFF'
+ data_ba[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a bytearray (during operation)
+ key_ba = bytearray(key)
+ data_ba = bytearray(data)
+
+ h1 = CMAC.new(key, ciphermod=AES)
+ h2 = CMAC.new(key, ciphermod=AES)
+ h1.update(data)
+ h2.update(data_ba)
+ data_ba[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class MemoryViewTests(unittest.TestCase):
+
+ def runTest(self):
+
+ key = b"0" * 16
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in (get_mv_ro, get_mv_rw):
+
+ # Data and key can be a memoryview (during initialization)
+ key_mv = get_mv(key)
+ data_mv = get_mv(data)
+
+ h1 = CMAC.new(key, data, ciphermod=AES)
+ h2 = CMAC.new(key_mv, data_mv, ciphermod=AES)
+ if not data_mv.readonly:
+ key_mv[:1] = b'\xFF'
+ data_mv[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a memoryview (during operation)
+ data_mv = get_mv(data)
+
+ h1 = CMAC.new(key, ciphermod=AES)
+ h2 = CMAC.new(key, ciphermod=AES)
+ h1.update(data)
+ h2.update(data_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class TestVectorsWycheproof(unittest.TestCase):
+
+ def __init__(self, wycheproof_warnings):
+ unittest.TestCase.__init__(self)
+ self._wycheproof_warnings = wycheproof_warnings
+ self._id = "None"
+
+ def setUp(self):
+
+ def filter_tag(group):
+ return group['tagSize'] // 8
+
+ self.tv = load_test_vectors_wycheproof(("Hash", "wycheproof"),
+ "aes_cmac_test.json",
+ "Wycheproof CMAC",
+ group_tag={'tag_size': filter_tag})
+
+ def shortDescription(self):
+ return self._id
+
+ def warn(self, tv):
+ if tv.warning and self._wycheproof_warnings:
+ import warnings
+ warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
+
+ def test_create_mac(self, tv):
+ self._id = "Wycheproof MAC creation Test #" + str(tv.id)
+
+ try:
+ tag = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size).digest()
+ except ValueError as e:
+ if len(tv.key) not in (16, 24, 32) and "key length" in str(e):
+ return
+ raise e
+ if tv.valid:
+ self.assertEqual(tag, tv.tag)
+ self.warn(tv)
+
+ def test_verify_mac(self, tv):
+ self._id = "Wycheproof MAC verification Test #" + str(tv.id)
+
+ try:
+ mac = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size)
+ except ValueError as e:
+ if len(tv.key) not in (16, 24, 32) and "key length" in str(e):
+ return
+ raise e
+ try:
+ mac.verify(tv.tag)
+ except ValueError:
+ assert not tv.valid
+ else:
+ assert tv.valid
+ self.warn(tv)
+
+ def runTest(self):
+
+ for tv in self.tv:
+ self.test_create_mac(tv)
+ self.test_verify_mac(tv)
+
+
+def get_tests(config={}):
+ global test_data
+ import types
+ from .common import make_mac_tests
+
+ wycheproof_warnings = config.get('wycheproof_warnings')
+
+ # Add new() parameters to the back of each test vector
+ params_test_data = []
+ for row in test_data:
+ t = list(row)
+ t[4] = dict(ciphermod=t[4])
+ params_test_data.append(t)
+
+ tests = make_mac_tests(CMAC, "CMAC", params_test_data)
+ tests.append(ByteArrayTests())
+ tests.append(list_test_cases(TestCMAC))
+ tests.append(MemoryViewTests())
+ tests += [ TestVectorsWycheproof(wycheproof_warnings) ]
+ return tests
+
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_HMAC.py b/lib/Crypto/SelfTest/Hash/test_HMAC.py
new file mode 100644
index 0000000..26b7b24
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_HMAC.py
@@ -0,0 +1,548 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/HMAC.py: Self-test for the HMAC module
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.HMAC"""
+
+import unittest
+from binascii import hexlify
+from Crypto.Util.py3compat import tostr, tobytes
+
+from Crypto.Hash import (HMAC, MD5, SHA1, SHA256,
+ SHA224, SHA384, SHA512,
+ RIPEMD160,
+ SHA3_224, SHA3_256, SHA3_384, SHA3_512)
+
+
+hash_modules = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256,
+ SHA224=SHA224, SHA384=SHA384, SHA512=SHA512,
+ RIPEMD160=RIPEMD160,
+ SHA3_224=SHA3_224, SHA3_256=SHA3_256,
+ SHA3_384=SHA3_384, SHA3_512=SHA3_512)
+
+default_hash = None
+
+def xl(text):
+ return tostr(hexlify(tobytes(text)))
+
+# This is a list of (key, data, results, description) tuples.
+test_data = [
+ ## Test vectors from RFC 2202 ##
+ # Test that the default hashmod is MD5
+ ('0b' * 16,
+ '4869205468657265',
+ dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'),
+ 'default-is-MD5'),
+
+ # Test case 1 (MD5)
+ ('0b' * 16,
+ '4869205468657265',
+ dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'),
+ 'RFC 2202 #1-MD5 (HMAC-MD5)'),
+
+ # Test case 1 (SHA1)
+ ('0b' * 20,
+ '4869205468657265',
+ dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'),
+ 'RFC 2202 #1-SHA1 (HMAC-SHA1)'),
+
+ # Test case 2
+ ('4a656665',
+ '7768617420646f2079612077616e7420666f72206e6f7468696e673f',
+ dict(MD5='750c783e6ab0b503eaa86e310a5db738',
+ SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'),
+ 'RFC 2202 #2 (HMAC-MD5/SHA1)'),
+
+ # Test case 3 (MD5)
+ ('aa' * 16,
+ 'dd' * 50,
+ dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'),
+ 'RFC 2202 #3-MD5 (HMAC-MD5)'),
+
+ # Test case 3 (SHA1)
+ ('aa' * 20,
+ 'dd' * 50,
+ dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'),
+ 'RFC 2202 #3-SHA1 (HMAC-SHA1)'),
+
+ # Test case 4
+ ('0102030405060708090a0b0c0d0e0f10111213141516171819',
+ 'cd' * 50,
+ dict(MD5='697eaf0aca3a3aea3a75164746ffaa79',
+ SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'),
+ 'RFC 2202 #4 (HMAC-MD5/SHA1)'),
+
+ # Test case 5 (MD5)
+ ('0c' * 16,
+ '546573742057697468205472756e636174696f6e',
+ dict(MD5='56461ef2342edc00f9bab995690efd4c'),
+ 'RFC 2202 #5-MD5 (HMAC-MD5)'),
+
+ # Test case 5 (SHA1)
+ # NB: We do not implement hash truncation, so we only test the full hash here.
+ ('0c' * 20,
+ '546573742057697468205472756e636174696f6e',
+ dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'),
+ 'RFC 2202 #5-SHA1 (HMAC-SHA1)'),
+
+ # Test case 6
+ ('aa' * 80,
+ '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
+ + '65204b6579202d2048617368204b6579204669727374',
+ dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd',
+ SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'),
+ 'RFC 2202 #6 (HMAC-MD5/SHA1)'),
+
+ # Test case 7
+ ('aa' * 80,
+ '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
+ + '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d'
+ + '53697a652044617461',
+ dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e',
+ SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'),
+ 'RFC 2202 #7 (HMAC-MD5/SHA1)'),
+
+ ## Test vectors from RFC 4231 ##
+ # 4.2. Test Case 1
+ ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
+ '4869205468657265',
+ dict(SHA256='''
+ b0344c61d8db38535ca8afceaf0bf12b
+ 881dc200c9833da726e9376c2e32cff7
+ '''),
+ 'RFC 4231 #1 (HMAC-SHA256)'),
+
+ # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC
+ # output.
+ ('4a656665',
+ '7768617420646f2079612077616e7420666f72206e6f7468696e673f',
+ dict(SHA256='''
+ 5bdcc146bf60754e6a042426089575c7
+ 5a003f089d2739839dec58b964ec3843
+ '''),
+ 'RFC 4231 #2 (HMAC-SHA256)'),
+
+ # 4.4. Test Case 3 - Test with a combined length of key and data that is
+ # larger than 64 bytes (= block-size of SHA-224 and SHA-256).
+ ('aa' * 20,
+ 'dd' * 50,
+ dict(SHA256='''
+ 773ea91e36800e46854db8ebd09181a7
+ 2959098b3ef8c122d9635514ced565fe
+ '''),
+ 'RFC 4231 #3 (HMAC-SHA256)'),
+
+ # 4.5. Test Case 4 - Test with a combined length of key and data that is
+ # larger than 64 bytes (= block-size of SHA-224 and SHA-256).
+ ('0102030405060708090a0b0c0d0e0f10111213141516171819',
+ 'cd' * 50,
+ dict(SHA256='''
+ 82558a389a443c0ea4cc819899f2083a
+ 85f0faa3e578f8077a2e3ff46729665b
+ '''),
+ 'RFC 4231 #4 (HMAC-SHA256)'),
+
+ # 4.6. Test Case 5 - Test with a truncation of output to 128 bits.
+ #
+ # Not included because we do not implement hash truncation.
+ #
+
+ # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of
+ # SHA-384 and SHA-512).
+ ('aa' * 131,
+ '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
+ + '65204b6579202d2048617368204b6579204669727374',
+ dict(SHA256='''
+ 60e431591ee0b67f0d8a26aacbf5b77f
+ 8e0bc6213728c5140546040f0ee37f54
+ '''),
+ 'RFC 4231 #6 (HMAC-SHA256)'),
+
+ # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes
+ # (= block-size of SHA-384 and SHA-512).
+ ('aa' * 131,
+ '5468697320697320612074657374207573696e672061206c6172676572207468'
+ + '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074'
+ + '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565'
+ + '647320746f20626520686173686564206265666f7265206265696e6720757365'
+ + '642062792074686520484d414320616c676f726974686d2e',
+ dict(SHA256='''
+ 9b09ffa71b942fcb27635fbcd5b0e944
+ bfdc63644f0713938a7f51535c3a35e2
+ '''),
+ 'RFC 4231 #7 (HMAC-SHA256)'),
+
+ # Test case 8 (SHA224)
+ ('4a656665',
+ '7768617420646f2079612077616e74'
+ + '20666f72206e6f7468696e673f',
+ dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'),
+ 'RFC 4634 8.4 SHA224 (HMAC-SHA224)'),
+
+ # Test case 9 (SHA384)
+ ('4a656665',
+ '7768617420646f2079612077616e74'
+ + '20666f72206e6f7468696e673f',
+ dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'),
+ 'RFC 4634 8.4 SHA384 (HMAC-SHA384)'),
+
+ # Test case 10 (SHA512)
+ ('4a656665',
+ '7768617420646f2079612077616e74'
+ + '20666f72206e6f7468696e673f',
+ dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'),
+ 'RFC 4634 8.4 SHA512 (HMAC-SHA512)'),
+
+ # Test case 11 (RIPEMD)
+ ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
+ xl("Hi There"),
+ dict(RIPEMD160='24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668'),
+ 'RFC 2286 #1 (HMAC-RIPEMD)'),
+
+ # Test case 12 (RIPEMD)
+ (xl("Jefe"),
+ xl("what do ya want for nothing?"),
+ dict(RIPEMD160='dda6c0213a485a9e24f4742064a7f033b43c4069'),
+ 'RFC 2286 #2 (HMAC-RIPEMD)'),
+
+ # Test case 13 (RIPEMD)
+ ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+ 'dd' * 50,
+ dict(RIPEMD160='b0b105360de759960ab4f35298e116e295d8e7c1'),
+ 'RFC 2286 #3 (HMAC-RIPEMD)'),
+
+ # Test case 14 (RIPEMD)
+ ('0102030405060708090a0b0c0d0e0f10111213141516171819',
+ 'cd' * 50,
+ dict(RIPEMD160='d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4'),
+ 'RFC 2286 #4 (HMAC-RIPEMD)'),
+
+ # Test case 15 (RIPEMD)
+ ('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+ xl("Test With Truncation"),
+ dict(RIPEMD160='7619693978f91d90539ae786500ff3d8e0518e39'),
+ 'RFC 2286 #5 (HMAC-RIPEMD)'),
+
+ # Test case 16 (RIPEMD)
+ ('aa' * 80,
+ xl("Test Using Larger Than Block-Size Key - Hash Key First"),
+ dict(RIPEMD160='6466ca07ac5eac29e1bd523e5ada7605b791fd8b'),
+ 'RFC 2286 #6 (HMAC-RIPEMD)'),
+
+ # Test case 17 (RIPEMD)
+ ('aa' * 80,
+ xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
+ dict(RIPEMD160='69ea60798d71616cce5fd0871e23754cd75d5a0a'),
+ 'RFC 2286 #7 (HMAC-RIPEMD)'),
+
+ # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf
+ (
+ '000102030405060708090a0b0c0d0e0f'
+ '101112131415161718191a1b',
+ xl('Sample message for keylen<blocklen'),
+ dict(SHA3_224='332cfd59347fdb8e576e77260be4aba2d6dc53117b3bfb52c6d18c04'),
+ 'NIST CSRC Sample #1 (SHA3-224)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '606162636465666768696a6b6c6d6e6f'\
+ '707172737475767778797a7b7c7d7e7f'\
+ '808182838485868788898a8b8c8d8e8f',
+ xl('Sample message for keylen=blocklen'),
+ dict(SHA3_224='d8b733bcf66c644a12323d564e24dcf3fc75f231f3b67968359100c7'),
+ 'NIST CSRC Sample #2 (SHA3-224)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '606162636465666768696a6b6c6d6e6f'\
+ '707172737475767778797a7b7c7d7e7f'\
+ '808182838485868788898a8b8c8d8e8f'\
+ '909192939495969798999a9b9c9d9e9f'\
+ 'a0a1a2a3a4a5a6a7a8a9aaab',
+ xl('Sample message for keylen>blocklen'),
+ dict(SHA3_224='078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59'),
+ 'NIST CSRC Sample #3 (SHA3-224)'
+ ),
+
+ # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f',
+ xl('Sample message for keylen<blocklen'),
+ dict(SHA3_256='4fe8e202c4f058e8dddc23d8c34e467343e23555e24fc2f025d598f558f67205'),
+ 'NIST CSRC Sample #1 (SHA3-256)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '606162636465666768696a6b6c6d6e6f'\
+ '707172737475767778797a7b7c7d7e7f'\
+ '8081828384858687',
+ xl('Sample message for keylen=blocklen'),
+ dict(SHA3_256='68b94e2e538a9be4103bebb5aa016d47961d4d1aa906061313b557f8af2c3faa'),
+ 'NIST CSRC Sample #2 (SHA3-256)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '606162636465666768696a6b6c6d6e6f'\
+ '707172737475767778797a7b7c7d7e7f'\
+ '808182838485868788898a8b8c8d8e8f'\
+ '909192939495969798999a9b9c9d9e9f'\
+ 'a0a1a2a3a4a5a6a7',
+ xl('Sample message for keylen>blocklen'),
+ dict(SHA3_256='9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258'),
+ 'NIST CSRC Sample #3 (SHA3-256)'
+ ),
+
+ # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'
+ '202122232425262728292a2b2c2d2e2f',
+ xl('Sample message for keylen<blocklen'),
+ dict(SHA3_384='d588a3c51f3f2d906e8298c1199aa8ff6296218127f6b38a90b6afe2c5617725bc99987f79b22a557b6520db710b7f42'),
+ 'NIST CSRC Sample #1 (SHA3-384)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '6061626364656667',
+ xl('Sample message for keylen=blocklen'),
+ dict(SHA3_384='a27d24b592e8c8cbf6d4ce6fc5bf62d8fc98bf2d486640d9eb8099e24047837f5f3bffbe92dcce90b4ed5b1e7e44fa90'),
+ 'NIST CSRC Sample #2 (SHA3-384)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '606162636465666768696a6b6c6d6e6f'\
+ '707172737475767778797a7b7c7d7e7f'\
+ '808182838485868788898a8b8c8d8e8f'\
+ '9091929394959697',
+ xl('Sample message for keylen>blocklen'),
+ dict(SHA3_384='e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac'),
+ 'NIST CSRC Sample #3 (SHA3-384)'
+ ),
+
+ # From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f',
+ xl('Sample message for keylen<blocklen'),
+ dict(SHA3_512='4efd629d6c71bf86162658f29943b1c308ce27cdfa6db0d9c3ce81763f9cbce5f7ebe9868031db1a8f8eb7b6b95e5c5e3f657a8996c86a2f6527e307f0213196'),
+ 'NIST CSRC Sample #1 (SHA3-512)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '4041424344454647',
+ xl('Sample message for keylen=blocklen'),
+ dict(SHA3_512='544e257ea2a3e5ea19a590e6a24b724ce6327757723fe2751b75bf007d80f6b360744bf1b7a88ea585f9765b47911976d3191cf83c039f5ffab0d29cc9d9b6da'),
+ 'NIST CSRC Sample #2 (SHA3-512)'
+ ),
+ (
+ '000102030405060708090a0b0c0d0e0f'\
+ '101112131415161718191a1b1c1d1e1f'\
+ '202122232425262728292a2b2c2d2e2f'\
+ '303132333435363738393a3b3c3d3e3f'\
+ '404142434445464748494a4b4c4d4e4f'\
+ '505152535455565758595a5b5c5d5e5f'\
+ '606162636465666768696a6b6c6d6e6f'\
+ '707172737475767778797a7b7c7d7e7f'\
+ '8081828384858687',
+ xl('Sample message for keylen>blocklen'),
+ dict(SHA3_512='5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915'),
+ 'NIST CSRC Sample #3 (SHA3-512)'
+ ),
+
+]
+
+
+class HMAC_Module_and_Instance_Test(unittest.TestCase):
+ """Test the HMAC construction and verify that it does not
+ matter if you initialize it with a hash module or
+ with an hash instance.
+
+ See https://bugs.launchpad.net/pycrypto/+bug/1209399
+ """
+
+ def __init__(self, hashmods):
+ """Initialize the test with a dictionary of hash modules
+ indexed by their names"""
+
+ unittest.TestCase.__init__(self)
+ self.hashmods = hashmods
+ self.description = ""
+
+ def shortDescription(self):
+ return self.description
+
+ def runTest(self):
+ key = b"\x90\x91\x92\x93" * 4
+ payload = b"\x00" * 100
+
+ for hashname, hashmod in self.hashmods.items():
+ if hashmod is None:
+ continue
+ self.description = "Test HMAC in combination with " + hashname
+ one = HMAC.new(key, payload, hashmod).digest()
+ two = HMAC.new(key, payload, hashmod.new()).digest()
+ self.assertEqual(one, two)
+
+
+class HMAC_None(unittest.TestCase):
+
+ def runTest(self):
+
+ key = b"\x04" * 20
+ one = HMAC.new(key, b"", SHA1).digest()
+ two = HMAC.new(key, None, SHA1).digest()
+ self.assertEqual(one, two)
+
+
+class ByteArrayTests(unittest.TestCase):
+
+ def runTest(self):
+
+ key = b"0" * 16
+ data = b"\x00\x01\x02"
+
+ # Data and key can be a bytearray (during initialization)
+ key_ba = bytearray(key)
+ data_ba = bytearray(data)
+
+ h1 = HMAC.new(key, data)
+ h2 = HMAC.new(key_ba, data_ba)
+ key_ba[:1] = b'\xFF'
+ data_ba[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a bytearray (during operation)
+ key_ba = bytearray(key)
+ data_ba = bytearray(data)
+
+ h1 = HMAC.new(key)
+ h2 = HMAC.new(key)
+ h1.update(data)
+ h2.update(data_ba)
+ data_ba[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class MemoryViewTests(unittest.TestCase):
+
+ def runTest(self):
+
+ key = b"0" * 16
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in (get_mv_ro, get_mv_rw):
+
+ # Data and key can be a memoryview (during initialization)
+ key_mv = get_mv(key)
+ data_mv = get_mv(data)
+
+ h1 = HMAC.new(key, data)
+ h2 = HMAC.new(key_mv, data_mv)
+ if not data_mv.readonly:
+ key_mv[:1] = b'\xFF'
+ data_mv[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a memoryview (during operation)
+ data_mv = get_mv(data)
+
+ h1 = HMAC.new(key)
+ h2 = HMAC.new(key)
+ h1.update(data)
+ h2.update(data_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+def get_tests(config={}):
+ global test_data
+ import types
+ from .common import make_mac_tests
+
+ # A test vector contains multiple results, each one for a
+ # different hash algorithm.
+ # Here we expand each test vector into multiple ones,
+ # and add the relevant parameters that will be passed to new()
+ exp_test_data = []
+ for row in test_data:
+ for modname in row[2].keys():
+ t = list(row)
+ t[2] = row[2][modname]
+ t.append(dict(digestmod=globals()[modname]))
+ exp_test_data.append(t)
+ tests = make_mac_tests(HMAC, "HMAC", exp_test_data)
+ tests.append(HMAC_Module_and_Instance_Test(hash_modules))
+ tests.append(HMAC_None())
+
+ tests.append(ByteArrayTests())
+ tests.append(MemoryViewTests())
+
+ return tests
+
+
+if __name__ == '__main__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_KMAC.py b/lib/Crypto/SelfTest/Hash/test_KMAC.py
new file mode 100644
index 0000000..8e9bf70
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_KMAC.py
@@ -0,0 +1,346 @@
+import unittest
+from binascii import unhexlify, hexlify
+
+from Crypto.Util.py3compat import tobytes
+from Crypto.Util.strxor import strxor_c
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import KMAC128, KMAC256
+
+
+class KMACTest(unittest.TestCase):
+
+ def new(self, *args, **kwargs):
+ return self.KMAC.new(key=b'X' * (self.minimum_key_bits // 8), *args, **kwargs)
+
+ def test_new_positive(self):
+
+ key = b'X' * 32
+
+ h = self.new()
+ for new_func in self.KMAC.new, h.new:
+
+ for dbytes in range(self.minimum_bytes, 128 + 1):
+ hobj = new_func(key=key, mac_len=dbytes)
+ self.assertEqual(hobj.digest_size, dbytes)
+
+ digest1 = new_func(key=key, data=b"\x90").digest()
+ digest2 = new_func(key=key).update(b"\x90").digest()
+ self.assertEqual(digest1, digest2)
+
+ new_func(data=b"A", key=key, custom=b"g")
+
+ hobj = h.new(key=key)
+ self.assertEqual(hobj.digest_size, self.default_bytes)
+
+ def test_new_negative(self):
+
+ h = self.new()
+ for new_func in self.KMAC.new, h.new:
+ self.assertRaises(ValueError, new_func, key=b'X'*32,
+ mac_len=0)
+ self.assertRaises(ValueError, new_func, key=b'X'*32,
+ mac_len=self.minimum_bytes - 1)
+ self.assertRaises(TypeError, new_func,
+ key=u"string")
+ self.assertRaises(TypeError, new_func,
+ data=u"string")
+
+ def test_default_digest_size(self):
+ digest = self.new(data=b'abc').digest()
+ self.assertEqual(len(digest), self.default_bytes)
+
+ def test_update(self):
+ pieces = [b"\x0A" * 200, b"\x14" * 300]
+ h = self.new()
+ h.update(pieces[0]).update(pieces[1])
+ digest = h.digest()
+ h = self.new()
+ h.update(pieces[0] + pieces[1])
+ self.assertEqual(h.digest(), digest)
+
+ def test_update_negative(self):
+ h = self.new()
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = self.new()
+ digest = h.digest()
+
+ # hexdigest does not change the state
+ self.assertEqual(h.digest(), digest)
+ # digest returns a byte string
+ self.assertTrue(isinstance(digest, type(b"digest")))
+
+ def test_update_after_digest(self):
+ msg = b"rrrrttt"
+
+ # Normally, update() cannot be done after digest()
+ h = self.new(mac_len=32, data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, dig1)
+
+ def test_hex_digest(self):
+ mac = self.new()
+ digest = mac.digest()
+ hexdigest = mac.hexdigest()
+
+ # hexdigest is equivalent to digest
+ self.assertEqual(hexlify(digest), tobytes(hexdigest))
+ # hexdigest does not change the state
+ self.assertEqual(mac.hexdigest(), hexdigest)
+ # hexdigest returns a string
+ self.assertTrue(isinstance(hexdigest, type("digest")))
+
+ def test_verify(self):
+ h = self.new()
+ mac = h.digest()
+ h.verify(mac)
+ wrong_mac = strxor_c(mac, 255)
+ self.assertRaises(ValueError, h.verify, wrong_mac)
+
+ def test_hexverify(self):
+ h = self.new()
+ mac = h.hexdigest()
+ h.hexverify(mac)
+ self.assertRaises(ValueError, h.hexverify, "4556")
+
+ def test_oid(self):
+
+ oid = "2.16.840.1.101.3.4.2." + self.oid_variant
+ h = self.new()
+ self.assertEqual(h.oid, oid)
+
+ def test_bytearray(self):
+
+ key = b'0' * 32
+ data = b"\x00\x01\x02"
+
+ # Data and key can be a bytearray (during initialization)
+ key_ba = bytearray(key)
+ data_ba = bytearray(data)
+
+ h1 = self.KMAC.new(data=data, key=key)
+ h2 = self.KMAC.new(data=data_ba, key=key_ba)
+ key_ba[:1] = b'\xFF'
+ data_ba[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a bytearray (during operation)
+ data_ba = bytearray(data)
+
+ h1 = self.new()
+ h2 = self.new()
+ h1.update(data)
+ h2.update(data_ba)
+ data_ba[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ def test_memoryview(self):
+
+ key = b'0' * 32
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in (get_mv_ro, get_mv_rw):
+
+ # Data and key can be a memoryview (during initialization)
+ key_mv = get_mv(key)
+ data_mv = get_mv(data)
+
+ h1 = self.KMAC.new(data=data, key=key)
+ h2 = self.KMAC.new(data=data_mv, key=key_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+ key_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a memoryview (during operation)
+ data_mv = get_mv(data)
+
+ h1 = self.new()
+ h2 = self.new()
+ h1.update(data)
+ h2.update(data_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class KMAC128Test(KMACTest):
+
+ KMAC = KMAC128
+
+ minimum_key_bits = 128
+
+ minimum_bytes = 8
+ default_bytes = 64
+
+ oid_variant = "19"
+
+
+class KMAC256Test(KMACTest):
+
+ KMAC = KMAC256
+
+ minimum_key_bits = 256
+
+ minimum_bytes = 8
+ default_bytes = 64
+
+ oid_variant = "20"
+
+
+class NISTExampleTestVectors(unittest.TestCase):
+
+ # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
+ test_data = [
+ (
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
+ "00 01 02 03",
+ "",
+ "E5 78 0B 0D 3E A6 F7 D3 A4 29 C5 70 6A A4 3A 00"
+ "FA DB D7 D4 96 28 83 9E 31 87 24 3F 45 6E E1 4E",
+ "Sample #1 NIST",
+ KMAC128
+ ),
+ (
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
+ "00 01 02 03",
+ "My Tagged Application",
+ "3B 1F BA 96 3C D8 B0 B5 9E 8C 1A 6D 71 88 8B 71"
+ "43 65 1A F8 BA 0A 70 70 C0 97 9E 28 11 32 4A A5",
+ "Sample #2 NIST",
+ KMAC128
+ ),
+ (
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
+ "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F"
+ "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F"
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F"
+ "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F"
+ "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F"
+ "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F"
+ "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F"
+ "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF"
+ "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF"
+ "C0 C1 C2 C3 C4 C5 C6 C7",
+ "My Tagged Application",
+ "1F 5B 4E 6C CA 02 20 9E 0D CB 5C A6 35 B8 9A 15"
+ "E2 71 EC C7 60 07 1D FD 80 5F AA 38 F9 72 92 30",
+ "Sample #3 NIST",
+ KMAC128
+ ),
+ (
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
+ "00 01 02 03",
+ "My Tagged Application",
+ "20 C5 70 C3 13 46 F7 03 C9 AC 36 C6 1C 03 CB 64"
+ "C3 97 0D 0C FC 78 7E 9B 79 59 9D 27 3A 68 D2 F7"
+ "F6 9D 4C C3 DE 9D 10 4A 35 16 89 F2 7C F6 F5 95"
+ "1F 01 03 F3 3F 4F 24 87 10 24 D9 C2 77 73 A8 DD",
+ "Sample #4 NIST",
+ KMAC256
+ ),
+ (
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
+ "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F"
+ "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F"
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F"
+ "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F"
+ "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F"
+ "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F"
+ "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F"
+ "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF"
+ "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF"
+ "C0 C1 C2 C3 C4 C5 C6 C7",
+ "",
+ "75 35 8C F3 9E 41 49 4E 94 97 07 92 7C EE 0A F2"
+ "0A 3F F5 53 90 4C 86 B0 8F 21 CC 41 4B CF D6 91"
+ "58 9D 27 CF 5E 15 36 9C BB FF 8B 9A 4C 2E B1 78"
+ "00 85 5D 02 35 FF 63 5D A8 25 33 EC 6B 75 9B 69",
+ "Sample #5 NIST",
+ KMAC256
+ ),
+ (
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
+ "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F"
+ "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F"
+ "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
+ "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F"
+ "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F"
+ "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F"
+ "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F"
+ "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F"
+ "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF"
+ "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF"
+ "C0 C1 C2 C3 C4 C5 C6 C7",
+ "My Tagged Application",
+ "B5 86 18 F7 1F 92 E1 D5 6C 1B 8C 55 DD D7 CD 18"
+ "8B 97 B4 CA 4D 99 83 1E B2 69 9A 83 7D A2 E4 D9"
+ "70 FB AC FD E5 00 33 AE A5 85 F1 A2 70 85 10 C3"
+ "2D 07 88 08 01 BD 18 28 98 FE 47 68 76 FC 89 65",
+ "Sample #6 NIST",
+ KMAC256
+ ),
+ ]
+
+ def setUp(self):
+ td = []
+ for key, data, custom, mac, text, module in self.test_data:
+ ni = (
+ unhexlify(key.replace(" ", "")),
+ unhexlify(data.replace(" ", "")),
+ custom.encode(),
+ unhexlify(mac.replace(" ", "")),
+ text,
+ module
+ )
+ td.append(ni)
+ self.test_data = td
+
+ def runTest(self):
+
+ for key, data, custom, mac, text, module in self.test_data:
+ h = module.new(data=data, key=key, custom=custom, mac_len=len(mac))
+ mac_tag = h.digest()
+ self.assertEqual(mac_tag, mac, msg=text)
+
+
+def get_tests(config={}):
+ tests = []
+
+ tests += list_test_cases(KMAC128Test)
+ tests += list_test_cases(KMAC256Test)
+ tests.append(NISTExampleTestVectors())
+
+ return tests
+
+
+if __name__ == '__main__':
+ def suite():
+ return unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_KangarooTwelve.py b/lib/Crypto/SelfTest/Hash/test_KangarooTwelve.py
new file mode 100644
index 0000000..49aeaad
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_KangarooTwelve.py
@@ -0,0 +1,324 @@
+# ===================================================================
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.KangarooTwelve"""
+
+import unittest
+from binascii import unhexlify
+
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import KangarooTwelve as K12
+from Crypto.Util.py3compat import b, bchr
+
+
+class KangarooTwelveTest(unittest.TestCase):
+
+ def test_length_encode(self):
+ self.assertEqual(K12._length_encode(0), b'\x00')
+ self.assertEqual(K12._length_encode(12), b'\x0C\x01')
+ self.assertEqual(K12._length_encode(65538), b'\x01\x00\x02\x03')
+
+ def test_new_positive(self):
+
+ xof1 = K12.new()
+ xof2 = K12.new(data=b("90"))
+ xof3 = K12.new().update(b("90"))
+
+ self.assertNotEqual(xof1.read(10), xof2.read(10))
+ xof3.read(10)
+ self.assertEqual(xof2.read(10), xof3.read(10))
+
+ xof1 = K12.new()
+ ref = xof1.read(10)
+ xof2 = K12.new(custom=b(""))
+ xof3 = K12.new(custom=b("foo"))
+
+ self.assertEqual(ref, xof2.read(10))
+ self.assertNotEqual(ref, xof3.read(10))
+
+ xof1 = K12.new(custom=b("foo"))
+ xof2 = K12.new(custom=b("foo"), data=b("90"))
+ xof3 = K12.new(custom=b("foo")).update(b("90"))
+
+ self.assertNotEqual(xof1.read(10), xof2.read(10))
+ xof3.read(10)
+ self.assertEqual(xof2.read(10), xof3.read(10))
+
+ def test_update(self):
+ pieces = [bchr(10) * 200, bchr(20) * 300]
+ h = K12.new()
+ h.update(pieces[0]).update(pieces[1])
+ digest = h.read(10)
+ h = K12.new()
+ h.update(pieces[0] + pieces[1])
+ self.assertEqual(h.read(10), digest)
+
+ def test_update_negative(self):
+ h = K12.new()
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = K12.new()
+ digest = h.read(90)
+
+ # read returns a byte string of the right length
+ self.assertTrue(isinstance(digest, type(b("digest"))))
+ self.assertEqual(len(digest), 90)
+
+ def test_update_after_read(self):
+ mac = K12.new()
+ mac.update(b("rrrr"))
+ mac.read(90)
+ self.assertRaises(TypeError, mac.update, b("ttt"))
+
+
+def txt2bin(txt):
+ clean = txt.replace(" ", "").replace("\n", "").replace("\r", "")
+ return unhexlify(clean)
+
+
+def ptn(n):
+ res = bytearray(n)
+ pattern = b"".join([bchr(x) for x in range(0, 0xFB)])
+ for base in range(0, n - 0xFB, 0xFB):
+ res[base:base + 0xFB] = pattern
+ remain = n % 0xFB
+ if remain:
+ base = (n // 0xFB) * 0xFB
+ res[base:] = pattern[:remain]
+ assert(len(res) == n)
+ return res
+
+
+def chunked(source, size):
+ for i in range(0, len(source), size):
+ yield source[i:i+size]
+
+
+# https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt
+class KangarooTwelveTV(unittest.TestCase):
+
+ def test_zero_1(self):
+ tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51
+ 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5"""
+
+ btv = txt2bin(tv)
+ res = K12.new().read(32)
+ self.assertEqual(res, btv)
+
+ def test_zero_2(self):
+ tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51
+ 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5
+ 42 69 C0 56 B8 C8 2E 48 27 60 38 B6 D2 92 96 6C
+ C0 7A 3D 46 45 27 2E 31 FF 38 50 81 39 EB 0A 71"""
+
+ btv = txt2bin(tv)
+ res = K12.new().read(64)
+ self.assertEqual(res, btv)
+
+ def test_zero_3(self):
+ tv = """E8 DC 56 36 42 F7 22 8C 84 68 4C 89 84 05 D3 A8
+ 34 79 91 58 C0 79 B1 28 80 27 7A 1D 28 E2 FF 6D"""
+
+ btv = txt2bin(tv)
+ res = K12.new().read(10032)
+ self.assertEqual(res[-32:], btv)
+
+ def test_ptn_1(self):
+ tv = """2B DA 92 45 0E 8B 14 7F 8A 7C B6 29 E7 84 A0 58
+ EF CA 7C F7 D8 21 8E 02 D3 45 DF AA 65 24 4A 1F"""
+
+ btv = txt2bin(tv)
+ res = K12.new(data=ptn(1)).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_17(self):
+ tv = """6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B
+ 0F 37 12 05 F6 A9 A9 3A 27 3F 51 DF 37 12 28 88"""
+
+ btv = txt2bin(tv)
+ res = K12.new(data=ptn(17)).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_17_2(self):
+ tv = """0C 31 5E BC DE DB F6 14 26 DE 7D CF 8F B7 25 D1
+ E7 46 75 D7 F5 32 7A 50 67 F3 67 B1 08 EC B6 7C"""
+
+ btv = txt2bin(tv)
+ res = K12.new(data=ptn(17**2)).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_17_3(self):
+ tv = """CB 55 2E 2E C7 7D 99 10 70 1D 57 8B 45 7D DF 77
+ 2C 12 E3 22 E4 EE 7F E4 17 F9 2C 75 8F 0D 59 D0"""
+
+ btv = txt2bin(tv)
+ res = K12.new(data=ptn(17**3)).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_17_4(self):
+ tv = """87 01 04 5E 22 20 53 45 FF 4D DA 05 55 5C BB 5C
+ 3A F1 A7 71 C2 B8 9B AE F3 7D B4 3D 99 98 B9 FE"""
+
+ btv = txt2bin(tv)
+ data = ptn(17**4)
+
+ # All at once
+ res = K12.new(data=data).read(32)
+ self.assertEqual(res, btv)
+
+ # Byte by byte
+ k12 = K12.new()
+ for x in data:
+ k12.update(bchr(x))
+ res = k12.read(32)
+ self.assertEqual(res, btv)
+
+ # Chunks of various prime sizes
+ for chunk_size in (13, 17, 19, 23, 31):
+ k12 = K12.new()
+ for x in chunked(data, chunk_size):
+ k12.update(x)
+ res = k12.read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_17_5(self):
+ tv = """84 4D 61 09 33 B1 B9 96 3C BD EB 5A E3 B6 B0 5C
+ C7 CB D6 7C EE DF 88 3E B6 78 A0 A8 E0 37 16 82"""
+
+ btv = txt2bin(tv)
+ data = ptn(17**5)
+
+ # All at once
+ res = K12.new(data=data).read(32)
+ self.assertEqual(res, btv)
+
+ # Chunks
+ k12 = K12.new()
+ for chunk in chunked(data, 8192):
+ k12.update(chunk)
+ res = k12.read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_17_6(self):
+ tv = """3C 39 07 82 A8 A4 E8 9F A6 36 7F 72 FE AA F1 32
+ 55 C8 D9 58 78 48 1D 3C D8 CE 85 F5 8E 88 0A F8"""
+
+ btv = txt2bin(tv)
+ data = ptn(17**6)
+
+ # All at once
+ res = K12.new(data=data).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_c_1(self):
+ tv = """FA B6 58 DB 63 E9 4A 24 61 88 BF 7A F6 9A 13 30
+ 45 F4 6E E9 84 C5 6E 3C 33 28 CA AF 1A A1 A5 83"""
+
+ btv = txt2bin(tv)
+ custom = ptn(1)
+
+ # All at once
+ res = K12.new(custom=custom).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_c_41(self):
+ tv = """D8 48 C5 06 8C ED 73 6F 44 62 15 9B 98 67 FD 4C
+ 20 B8 08 AC C3 D5 BC 48 E0 B0 6B A0 A3 76 2E C4"""
+
+ btv = txt2bin(tv)
+ custom = ptn(41)
+
+ # All at once
+ res = K12.new(data=b'\xFF', custom=custom).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_c_41_2(self):
+ tv = """C3 89 E5 00 9A E5 71 20 85 4C 2E 8C 64 67 0A C0
+ 13 58 CF 4C 1B AF 89 44 7A 72 42 34 DC 7C ED 74"""
+
+ btv = txt2bin(tv)
+ custom = ptn(41**2)
+
+ # All at once
+ res = K12.new(data=b'\xFF' * 3, custom=custom).read(32)
+ self.assertEqual(res, btv)
+
+ def test_ptn_c_41_3(self):
+ tv = """75 D2 F8 6A 2E 64 45 66 72 6B 4F BC FC 56 57 B9
+ DB CF 07 0C 7B 0D CA 06 45 0A B2 91 D7 44 3B CF"""
+
+ btv = txt2bin(tv)
+ custom = ptn(41**3)
+
+ # All at once
+ res = K12.new(data=b'\xFF' * 7, custom=custom).read(32)
+ self.assertEqual(res, btv)
+
+ ###
+
+ def test_1(self):
+ tv = "fd608f91d81904a9916e78a18f65c157a78d63f93d8f6367db0524526a5ea2bb"
+
+ btv = txt2bin(tv)
+ res = K12.new(data=b'', custom=ptn(100)).read(32)
+ self.assertEqual(res, btv)
+
+ def test_2(self):
+ tv4 = "5a4ec9a649f81916d4ce1553492962f7868abf8dd1ceb2f0cb3682ea95cda6a6"
+ tv3 = "441688fe4fe4ae9425eb3105eb445eb2b3a6f67b66eff8e74ebfbc49371f6d4c"
+ tv2 = "17269a57759af0214c84a0fd9bc851f4d95f80554cfed4e7da8a6ee1ff080131"
+ tv1 = "33826990c09dc712ba7224f0d9be319e2720de95a4c1afbd2211507dae1c703a"
+ tv0 = "9f4d3aba908ddc096e4d3a71da954f917b9752f05052b9d26d916a6fbc75bf3e"
+
+ res = K12.new(data=b'A' * (8192 - 4), custom=b'B').read(32)
+ self.assertEqual(res, txt2bin(tv4))
+
+ res = K12.new(data=b'A' * (8192 - 3), custom=b'B').read(32)
+ self.assertEqual(res, txt2bin(tv3))
+
+ res = K12.new(data=b'A' * (8192 - 2), custom=b'B').read(32)
+ self.assertEqual(res, txt2bin(tv2))
+
+ res = K12.new(data=b'A' * (8192 - 1), custom=b'B').read(32)
+ self.assertEqual(res, txt2bin(tv1))
+
+ res = K12.new(data=b'A' * (8192 - 0), custom=b'B').read(32)
+ self.assertEqual(res, txt2bin(tv0))
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(KangarooTwelveTest)
+ tests += list_test_cases(KangarooTwelveTV)
+ return tests
+
+
+if __name__ == '__main__':
+ def suite():
+ return unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_MD2.py b/lib/Crypto/SelfTest/Hash/test_MD2.py
new file mode 100644
index 0000000..9375168
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_MD2.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/MD2.py: Self-test for the MD2 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.MD2"""
+
+from Crypto.Util.py3compat import *
+
+# This is a list of (expected_result, input[, description]) tuples.
+test_data = [
+ # Test vectors from RFC 1319
+ ('8350e5a3e24c153df2275c9f80692773', '', "'' (empty string)"),
+ ('32ec01ec4a6dac72c0ab96fb34c0b5d1', 'a'),
+ ('da853b0d3f88d99b30283a69e6ded6bb', 'abc'),
+ ('ab4f496bfb2a530b219ff33031fe06b0', 'message digest'),
+
+ ('4e8ddff3650292ab5a4108c3aa47940b', 'abcdefghijklmnopqrstuvwxyz',
+ 'a-z'),
+
+ ('da33def2a42df13975352846c30338cd',
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
+ 'A-Z, a-z, 0-9'),
+
+ ('d5976f79d83d3a0dc9806c3c66f3efd8',
+ '1234567890123456789012345678901234567890123456'
+ + '7890123456789012345678901234567890',
+ "'1234567890' * 8"),
+]
+
+def get_tests(config={}):
+ from Crypto.Hash import MD2
+ from .common import make_hash_tests
+ return make_hash_tests(MD2, "MD2", test_data,
+ digest_size=16,
+ oid="1.2.840.113549.2.2")
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_MD4.py b/lib/Crypto/SelfTest/Hash/test_MD4.py
new file mode 100644
index 0000000..17b48a7
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_MD4.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/MD4.py: Self-test for the MD4 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.MD4"""
+
+__revision__ = "$Id$"
+
+from Crypto.Util.py3compat import *
+
+# This is a list of (expected_result, input[, description]) tuples.
+test_data = [
+ # Test vectors from RFC 1320
+ ('31d6cfe0d16ae931b73c59d7e0c089c0', '', "'' (empty string)"),
+ ('bde52cb31de33e46245e05fbdbd6fb24', 'a'),
+ ('a448017aaf21d8525fc10ae87aa6729d', 'abc'),
+ ('d9130a8164549fe818874806e1c7014b', 'message digest'),
+
+ ('d79e1c308aa5bbcdeea8ed63df412da9', 'abcdefghijklmnopqrstuvwxyz',
+ 'a-z'),
+
+ ('043f8582f241db351ce627e153e7f0e4',
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
+ 'A-Z, a-z, 0-9'),
+
+ ('e33b4ddc9c38f2199c3e7b164fcc0536',
+ '1234567890123456789012345678901234567890123456'
+ + '7890123456789012345678901234567890',
+ "'1234567890' * 8"),
+]
+
+def get_tests(config={}):
+ from Crypto.Hash import MD4
+ from .common import make_hash_tests
+ return make_hash_tests(MD4, "MD4", test_data,
+ digest_size=16,
+ oid="1.2.840.113549.2.4")
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_MD5.py b/lib/Crypto/SelfTest/Hash/test_MD5.py
new file mode 100644
index 0000000..830ace7
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_MD5.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/MD5.py: Self-test for the MD5 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.MD5"""
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash import MD5
+from binascii import unhexlify
+import unittest
+from Crypto.SelfTest.st_common import list_test_cases
+
+
+# This is a list of (expected_result, input[, description]) tuples.
+test_data = [
+ # Test vectors from RFC 1321
+ ('d41d8cd98f00b204e9800998ecf8427e', '', "'' (empty string)"),
+ ('0cc175b9c0f1b6a831c399e269772661', 'a'),
+ ('900150983cd24fb0d6963f7d28e17f72', 'abc'),
+ ('f96b697d7cb7938d525a2f31aaf161d0', 'message digest'),
+
+ ('c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz',
+ 'a-z'),
+
+ ('d174ab98d277d9f5a5611c2c9f419d9f',
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
+ 'A-Z, a-z, 0-9'),
+
+ ('57edf4a22be3c955ac49da2e2107b67a',
+ '1234567890123456789012345678901234567890123456'
+ + '7890123456789012345678901234567890',
+ "'1234567890' * 8"),
+
+ # https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors
+ ('57EDF4A22BE3C955AC49DA2E2107B67A', '1234567890' * 8, 'Set 1, vector #7'),
+ ('7707D6AE4E027C70EEA2A935C2296F21', 'a'*1000000, 'Set 1, vector #8'),
+]
+
+
+class Md5IterTest(unittest.TestCase):
+
+ def runTest(self):
+ message = b("\x00") * 16
+ result1 = "4AE71336E44BF9BF79D2752E234818A5".lower()
+ result2 = "1A83F51285E4D89403D00C46EF8508FE".lower()
+
+ h = MD5.new(message)
+ message = h.digest()
+ self.assertEqual(h.hexdigest(), result1)
+
+ for _ in range(99999):
+ h = MD5.new(message)
+ message = h.digest()
+
+ self.assertEqual(h.hexdigest(), result2)
+
+
+def get_tests(config={}):
+ from .common import make_hash_tests
+
+ tests = make_hash_tests(MD5, "MD5", test_data,
+ digest_size=16,
+ oid="1.2.840.113549.2.5")
+ if config.get('slow_tests'):
+ tests += [ Md5IterTest() ]
+ return tests
+
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_Poly1305.py b/lib/Crypto/SelfTest/Hash/test_Poly1305.py
new file mode 100644
index 0000000..0612d4e
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_Poly1305.py
@@ -0,0 +1,542 @@
+#
+# SelfTest/Hash/test_Poly1305.py: Self-test for the Poly1305 module
+#
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash._Poly1305"""
+
+import json
+import unittest
+from binascii import unhexlify, hexlify
+
+from .common import make_mac_tests
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import Poly1305
+from Crypto.Cipher import AES, ChaCha20
+
+from Crypto.Util.py3compat import tobytes
+from Crypto.Util.strxor import strxor_c
+
+# This is a list of (r+s keypair, data, result, description, keywords) tuples.
+test_data_basic = [
+ (
+ "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
+ hexlify(b"Cryptographic Forum Research Group").decode(),
+ "a8061dc1305136c6c22b8baf0c0127a9",
+ "RFC7539"
+ ),
+ (
+ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "49ec78090e481ec6c26b33b91ccc0307",
+ "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 A",
+ ),
+ (
+ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+ "48656c6c6f20776f726c6421",
+ "a6f745008f81c916a20dcc74eef2b2f0",
+ "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 B",
+ ),
+ (
+ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+ "",
+ "6b657920666f7220506f6c7931333035",
+ "Generated with pure Python",
+ ),
+ (
+ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+ "FF",
+ "f7e4e0ef4c46d106219da3d1bdaeb3ff",
+ "Generated with pure Python",
+ ),
+ (
+ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+ "FF00",
+ "7471eceeb22988fc936da1d6e838b70e",
+ "Generated with pure Python",
+ ),
+ (
+ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+ "AA" * 17,
+ "32590bc07cb2afaccca3f67f122975fe",
+ "Generated with pure Python",
+ ),
+ (
+ "00" * 32,
+ "00" * 64,
+ "00" * 16,
+ "RFC7539 A.3 #1",
+ ),
+ (
+ "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
+ hexlify(
+ b"Any submission t"
+ b"o the IETF inten"
+ b"ded by the Contr"
+ b"ibutor for publi"
+ b"cation as all or"
+ b" part of an IETF"
+ b" Internet-Draft "
+ b"or RFC and any s"
+ b"tatement made wi"
+ b"thin the context"
+ b" of an IETF acti"
+ b"vity is consider"
+ b"ed an \"IETF Cont"
+ b"ribution\". Such "
+ b"statements inclu"
+ b"de oral statemen"
+ b"ts in IETF sessi"
+ b"ons, as well as "
+ b"written and elec"
+ b"tronic communica"
+ b"tions made at an"
+ b"y time or place,"
+ b" which are addre"
+ b"ssed to").decode(),
+ "36e5f6b5c5e06070f0efca96227a863e",
+ "RFC7539 A.3 #2",
+ ),
+ (
+ "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
+ hexlify(
+ b"Any submission t"
+ b"o the IETF inten"
+ b"ded by the Contr"
+ b"ibutor for publi"
+ b"cation as all or"
+ b" part of an IETF"
+ b" Internet-Draft "
+ b"or RFC and any s"
+ b"tatement made wi"
+ b"thin the context"
+ b" of an IETF acti"
+ b"vity is consider"
+ b"ed an \"IETF Cont"
+ b"ribution\". Such "
+ b"statements inclu"
+ b"de oral statemen"
+ b"ts in IETF sessi"
+ b"ons, as well as "
+ b"written and elec"
+ b"tronic communica"
+ b"tions made at an"
+ b"y time or place,"
+ b" which are addre"
+ b"ssed to").decode(),
+ "f3477e7cd95417af89a6b8794c310cf0",
+ "RFC7539 A.3 #3",
+ ),
+ (
+ "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
+ "2754776173206272696c6c69672c2061"
+ "6e642074686520736c6974687920746f"
+ "7665730a446964206779726520616e64"
+ "2067696d626c6520696e207468652077"
+ "6162653a0a416c6c206d696d73792077"
+ "6572652074686520626f726f676f7665"
+ "732c0a416e6420746865206d6f6d6520"
+ "7261746873206f757467726162652e",
+ "4541669a7eaaee61e708dc7cbcc5eb62",
+ "RFC7539 A.3 #4",
+ ),
+ (
+ "02" + "00" * 31,
+ "FF" * 16,
+ "03" + "00" * 15,
+ "RFC7539 A.3 #5",
+ ),
+ (
+ "02" + "00" * 15 + "FF" * 16,
+ "02" + "00" * 15,
+ "03" + "00" * 15,
+ "RFC7539 A.3 #6",
+ ),
+ (
+ "01" + "00" * 31,
+ "FF" * 16 + "F0" + "FF" * 15 + "11" + "00" * 15,
+ "05" + "00" * 15,
+ "RFC7539 A.3 #7",
+ ),
+ (
+ "01" + "00" * 31,
+ "FF" * 16 + "FB" + "FE" * 15 + "01" * 16,
+ "00" * 16,
+ "RFC7539 A.3 #8",
+ ),
+ (
+ "02" + "00" * 31,
+ "FD" + "FF" * 15,
+ "FA" + "FF" * 15,
+ "RFC7539 A.3 #9",
+ ),
+ (
+ "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00"
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
+ "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00"
+ "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00"
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
+ "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
+ "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00",
+ "RFC7539 A.3 #10",
+ ),
+ (
+ "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00"
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
+ "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00"
+ "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00"
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
+ "13" + "00" * 15,
+ "RFC7539 A.3 #11",
+ ),
+]
+
+# This is a list of (key(k+r), data, result, description, keywords) tuples.
+test_data_aes = [
+ (
+ "ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700",
+ "f3f6",
+ "f4c633c3044fc145f84f335cb81953de",
+ "http://cr.yp.to/mac/poly1305-20050329.pdf",
+ { 'cipher':AES, 'nonce':unhexlify("fb447350c4e868c52ac3275cf9d4327e") }
+ ),
+ (
+ "75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403",
+ "",
+ "dd3fab2251f11ac759f0887129cc2ee7",
+ "http://cr.yp.to/mac/poly1305-20050329.pdf",
+ { 'cipher':AES, 'nonce':unhexlify("61ee09218d29b0aaed7e154a2c5509cc") }
+ ),
+ (
+ "6acb5f61a7176dd320c5c1eb2edcdc7448443d0bb0d21109c89a100b5ce2c208",
+ "663cea190ffb83d89593f3f476b6bc24"
+ "d7e679107ea26adb8caf6652d0656136",
+ "0ee1c16bb73f0f4fd19881753c01cdbe",
+ "http://cr.yp.to/mac/poly1305-20050329.pdf",
+ { 'cipher':AES, 'nonce':unhexlify("ae212a55399729595dea458bc621ff0e") }
+ ),
+ (
+ "e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207",
+ "ab0812724a7f1e342742cbed374d94d1"
+ "36c6b8795d45b3819830f2c04491faf0"
+ "990c62e48b8018b2c3e4a0fa3134cb67"
+ "fa83e158c994d961c4cb21095c1bf9",
+ "5154ad0d2cb26e01274fc51148491f1b",
+ "http://cr.yp.to/mac/poly1305-20050329.pdf",
+ { 'cipher':AES, 'nonce':unhexlify("9ae831e743978d3a23527c7128149e3a") }
+ ),
+]
+
+test_data_chacha20 = [
+ (
+ "00" * 32,
+ "FF" * 15,
+ "13cc5bbadc36b03a5163928f0bcb65aa",
+ "RFC7539 A.4 #1",
+ { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 12) }
+ ),
+ (
+ "00" * 31 + "01",
+ "FF" * 15,
+ "0baf33c1d6df211bdd50a6767e98e00a",
+ "RFC7539 A.4 #2",
+ { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") }
+ ),
+ (
+ "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0"
+ "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0",
+ "FF" * 15,
+ "e8b4c6db226cd8939e65e02eebf834ce",
+ "RFC7539 A.4 #3",
+ { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") }
+ ),
+ (
+ "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0"
+ "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0",
+ "f3 33 88 86 00 00 00 00 00 00 4e 91 00 00 00 00"
+ "64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd"
+ "5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2"
+ "4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0"
+ "bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf"
+ "33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81"
+ "14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55"
+ "97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38"
+ "36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4"
+ "b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9"
+ "90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e"
+ "af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a"
+ "0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a"
+ "0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e"
+ "ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10"
+ "49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30"
+ "30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29"
+ "a6 ad 5c b4 02 2b 02 70 9b 00 00 00 00 00 00 00"
+ "0c 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00",
+ "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38",
+ "RFC7539 A.5",
+ { 'cipher':ChaCha20, 'nonce':unhexlify("000000000102030405060708") }
+ ),
+]
+
+
+class Poly1305Test_AES(unittest.TestCase):
+
+ key = b'\x11' * 32
+
+ def test_new_positive(self):
+
+ data = b'r' * 100
+
+ h1 = Poly1305.new(key=self.key, cipher=AES)
+ self.assertEqual(h1.digest_size, 16)
+ self.assertEqual(len(h1.nonce), 16)
+ d1 = h1.update(data).digest()
+ self.assertEqual(len(d1), 16)
+
+ h2 = Poly1305.new(key=self.key, nonce=h1.nonce, data=data, cipher=AES)
+ d2 = h2.digest()
+ self.assertEqual(h1.nonce, h2.nonce)
+ self.assertEqual(d1, d2)
+
+ def test_new_negative(self):
+ from Crypto.Cipher import DES3
+
+ self.assertRaises(ValueError, Poly1305.new, key=self.key[:31], cipher=AES)
+ self.assertRaises(ValueError, Poly1305.new, key=self.key, cipher=DES3)
+ self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 15, cipher=AES)
+ self.assertRaises(TypeError, Poly1305.new, key=u"2" * 32, cipher=AES)
+ self.assertRaises(TypeError, Poly1305.new, key=self.key, data=u"2" * 100, cipher=AES)
+
+ def test_update(self):
+ pieces = [b"\x0A" * 200, b"\x14" * 300]
+ h1 = Poly1305.new(key=self.key, cipher=AES)
+ h1.update(pieces[0]).update(pieces[1])
+ d1 = h1.digest()
+
+ h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce)
+ h2.update(pieces[0] + pieces[1])
+ d2 = h2.digest()
+ self.assertEqual(d1, d2)
+
+ def test_update_negative(self):
+ h = Poly1305.new(key=self.key, cipher=AES)
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = Poly1305.new(key=self.key, cipher=AES)
+ digest = h.digest()
+
+ # hexdigest does not change the state
+ self.assertEqual(h.digest(), digest)
+ # digest returns a byte string
+ self.assertTrue(isinstance(digest, type(b"digest")))
+
+ def test_update_after_digest(self):
+ msg=b"rrrrttt"
+
+ # Normally, update() cannot be done after digest()
+ h = Poly1305.new(key=self.key, data=msg[:4], cipher=AES)
+ h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+
+ def test_hex_digest(self):
+ mac = Poly1305.new(key=self.key, cipher=AES)
+ digest = mac.digest()
+ hexdigest = mac.hexdigest()
+
+ # hexdigest is equivalent to digest
+ self.assertEqual(hexlify(digest), tobytes(hexdigest))
+ # hexdigest does not change the state
+ self.assertEqual(mac.hexdigest(), hexdigest)
+ # hexdigest returns a string
+ self.assertTrue(isinstance(hexdigest, type("digest")))
+
+ def test_verify(self):
+ h = Poly1305.new(key=self.key, cipher=AES)
+ mac = h.digest()
+ h.verify(mac)
+ wrong_mac = strxor_c(mac, 255)
+ self.assertRaises(ValueError, h.verify, wrong_mac)
+
+ def test_hexverify(self):
+ h = Poly1305.new(key=self.key, cipher=AES)
+ mac = h.hexdigest()
+ h.hexverify(mac)
+ self.assertRaises(ValueError, h.hexverify, "4556")
+
+ def test_bytearray(self):
+
+ data = b"\x00\x01\x02"
+ h0 = Poly1305.new(key=self.key, data=data, cipher=AES)
+ d_ref = h0.digest()
+
+ # Data and key can be a bytearray (during initialization)
+ key_ba = bytearray(self.key)
+ data_ba = bytearray(data)
+
+ h1 = Poly1305.new(key=self.key, data=data, cipher=AES, nonce=h0.nonce)
+ h2 = Poly1305.new(key=key_ba, data=data_ba, cipher=AES, nonce=h0.nonce)
+ key_ba[:1] = b'\xFF'
+ data_ba[:1] = b'\xEE'
+
+ self.assertEqual(h1.digest(), d_ref)
+ self.assertEqual(h2.digest(), d_ref)
+
+ # Data can be a bytearray (during operation)
+ data_ba = bytearray(data)
+
+ h1 = Poly1305.new(key=self.key, cipher=AES)
+ h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce)
+ h1.update(data)
+ h2.update(data_ba)
+ data_ba[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ def test_memoryview(self):
+
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in (get_mv_ro, get_mv_rw):
+
+ # Data and key can be a memoryview (during initialization)
+ key_mv = get_mv(self.key)
+ data_mv = get_mv(data)
+
+ h1 = Poly1305.new(key=self.key, data=data, cipher=AES)
+ h2 = Poly1305.new(key=key_mv, data=data_mv, cipher=AES,
+ nonce=h1.nonce)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+ key_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ # Data can be a memoryview (during operation)
+ data_mv = get_mv(data)
+
+ h1 = Poly1305.new(key=self.key, cipher=AES)
+ h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce)
+ h1.update(data)
+ h2.update(data_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class Poly1305Test_ChaCha20(unittest.TestCase):
+
+ key = b'\x11' * 32
+
+ def test_new_positive(self):
+ data = b'r' * 100
+
+ h1 = Poly1305.new(key=self.key, cipher=ChaCha20)
+ self.assertEqual(h1.digest_size, 16)
+ self.assertEqual(len(h1.nonce), 12)
+
+ h2 = Poly1305.new(key=self.key, cipher=ChaCha20, nonce = b'8' * 8)
+ self.assertEqual(len(h2.nonce), 8)
+ self.assertEqual(h2.nonce, b'8' * 8)
+
+ def test_new_negative(self):
+
+ self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 7, cipher=ChaCha20)
+
+
+#
+# make_mac_tests() expect a new() function with signature new(key, data,
+# **kwargs), and we need to adapt Poly1305's, as it only uses keywords
+#
+class Poly1305_New(object):
+
+ @staticmethod
+ def new(key, *data, **kwds):
+ _kwds = dict(kwds)
+ if len(data) == 1:
+ _kwds['data'] = data[0]
+ _kwds['key'] = key
+ return Poly1305.new(**_kwds)
+
+
+class Poly1305_Basic(object):
+
+ @staticmethod
+ def new(key, *data, **kwds):
+ from Crypto.Hash.Poly1305 import Poly1305_MAC
+
+ if len(data) == 1:
+ msg = data[0]
+ else:
+ msg = None
+
+ return Poly1305_MAC(key[:16], key[16:], msg)
+
+
+class Poly1305AES_MC(unittest.TestCase):
+
+ def runTest(self):
+ tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e")
+
+ msg = b''
+ for msg_len in range(5000 + 1):
+ key = tag + strxor_c(tag, 0xFF)
+ nonce = tag[::-1]
+ if msg_len > 0:
+ msg = msg + tobytes(tag[0])
+ auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg)
+ tag = auth.digest()
+
+ # Compare against output of original DJB's poly1305aes-20050218
+ self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper())
+
+
+def get_tests(config={}):
+ tests = make_mac_tests(Poly1305_Basic, "Poly1305", test_data_basic)
+ tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_aes)
+ tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_chacha20)
+ tests += [ Poly1305AES_MC() ]
+ tests += list_test_cases(Poly1305Test_AES)
+ tests += list_test_cases(Poly1305Test_ChaCha20)
+ return tests
+
+
+if __name__ == '__main__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_RIPEMD160.py b/lib/Crypto/SelfTest/Hash/test_RIPEMD160.py
new file mode 100644
index 0000000..153c570
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_RIPEMD160.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_RIPEMD160.py: Self-test for the RIPEMD-160 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+#"""Self-test suite for Crypto.Hash.RIPEMD160"""
+
+from Crypto.Util.py3compat import *
+
+# This is a list of (expected_result, input[, description]) tuples.
+test_data = [
+ # Test vectors downloaded 2008-09-12 from
+ # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+ ('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"),
+ ('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'),
+ ('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'),
+ ('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'),
+
+ ('f71c27109c692c1b56bbdceb5b9d2865b3708dbc',
+ 'abcdefghijklmnopqrstuvwxyz',
+ 'a-z'),
+
+ ('12a053384a9c0c88e405a06c27dcf49ada62eb2b',
+ 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
+ 'abcdbcd...pnopq'),
+
+ ('b0e20b6e3116640286ed3a87a5713079b21f5189',
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
+ 'A-Z, a-z, 0-9'),
+
+ ('9b752e45573d4b39f4dbd3323cab82bf63326bfb',
+ '1234567890' * 8,
+ "'1234567890' * 8"),
+
+ ('52783243c1697bdbe16d37f97f68f08325dc1528',
+ 'a' * 10**6,
+ '"a" * 10**6'),
+]
+
+def get_tests(config={}):
+ from Crypto.Hash import RIPEMD160
+ from .common import make_hash_tests
+ return make_hash_tests(RIPEMD160, "RIPEMD160", test_data,
+ digest_size=20,
+ oid="1.3.36.3.2.1")
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA1.py b/lib/Crypto/SelfTest/Hash/test_SHA1.py
new file mode 100644
index 0000000..a883a44
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA1.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/SHA1.py: Self-test for the SHA-1 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA"""
+
+from binascii import hexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+
+# Test vectors from various sources
+# This is a list of (expected_result, input[, description]) tuples.
+test_data_various = [
+ # FIPS PUB 180-2, A.1 - "One-Block Message"
+ ('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'),
+
+ # FIPS PUB 180-2, A.2 - "Multi-Block Message"
+ ('84983e441c3bd26ebaae4aa1f95129e5e54670f1',
+ 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
+
+ # FIPS PUB 180-2, A.3 - "Long Message"
+# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f',
+# 'a' * 10**6,
+# '"a" * 10**6'),
+
+ # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits)
+ ('dea356a2cddd90c7a7ecedc5ebb563934f460452',
+ '01234567' * 80,
+ '"01234567" * 80'),
+]
+
+def get_tests(config={}):
+ from Crypto.Hash import SHA1
+ from .common import make_hash_tests
+
+ tests = []
+
+ test_vectors = load_test_vectors(("Hash", "SHA1"),
+ "SHA1ShortMsg.rsp",
+ "KAT SHA-1",
+ { "len" : lambda x: int(x) } ) or []
+
+ test_data = test_data_various[:]
+ for tv in test_vectors:
+ try:
+ if tv.startswith('['):
+ continue
+ except AttributeError:
+ pass
+ if tv.len == 0:
+ tv.msg = b""
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests = make_hash_tests(SHA1, "SHA1", test_data,
+ digest_size=20,
+ oid="1.3.14.3.2.26")
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA224.py b/lib/Crypto/SelfTest/Hash/test_SHA224.py
new file mode 100644
index 0000000..cf81ad9
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA224.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA224.py: Self-test for the SHA-224 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA224"""
+
+# Test vectors from various sources
+# This is a list of (expected_result, input[, description]) tuples.
+test_data = [
+
+ # RFC 3874: Section 3.1, "Test Vector #1
+ ('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', 'abc'),
+
+ # RFC 3874: Section 3.2, "Test Vector #2
+ ('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
+
+ # RFC 3874: Section 3.3, "Test Vector #3
+ ('20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67', 'a' * 10**6, "'a' * 10**6"),
+
+ # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
+ ('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f', ''),
+
+ ('49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b',
+ 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
+
+ ('58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1',
+ 'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern'),
+
+]
+
+def get_tests(config={}):
+ from Crypto.Hash import SHA224
+ from .common import make_hash_tests
+ return make_hash_tests(SHA224, "SHA224", test_data,
+ digest_size=28,
+ oid='2.16.840.1.101.3.4.2.4')
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA256.py b/lib/Crypto/SelfTest/Hash/test_SHA256.py
new file mode 100644
index 0000000..bb99326
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA256.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA256.py: Self-test for the SHA-256 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA256"""
+
+import unittest
+from Crypto.Util.py3compat import *
+
+class LargeSHA256Test(unittest.TestCase):
+ def runTest(self):
+ """SHA256: 512/520 MiB test"""
+ from Crypto.Hash import SHA256
+ zeros = bchr(0x00) * (1024*1024)
+
+ h = SHA256.new(zeros)
+ for i in range(511):
+ h.update(zeros)
+
+ # This test vector is from PyCrypto's old testdata.py file.
+ self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB
+
+ for i in range(8):
+ h.update(zeros)
+
+ # This test vector is from PyCrypto's old testdata.py file.
+ self.assertEqual('abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e', h.hexdigest()) # 520 MiB
+
+def get_tests(config={}):
+ # Test vectors from FIPS PUB 180-2
+ # This is a list of (expected_result, input[, description]) tuples.
+ test_data = [
+ # FIPS PUB 180-2, B.1 - "One-Block Message"
+ ('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
+ 'abc'),
+
+ # FIPS PUB 180-2, B.2 - "Multi-Block Message"
+ ('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1',
+ 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
+
+ # FIPS PUB 180-2, B.3 - "Long Message"
+ ('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0',
+ 'a' * 10**6,
+ '"a" * 10**6'),
+
+ # Test for an old PyCrypto bug.
+ ('f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103',
+ 'This message is precisely 55 bytes long, to test a bug.',
+ 'Length = 55 (mod 64)'),
+
+ # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
+ ('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ''),
+
+ ('d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8',
+ 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
+ ]
+
+ from Crypto.Hash import SHA256
+ from .common import make_hash_tests
+ tests = make_hash_tests(SHA256, "SHA256", test_data,
+ digest_size=32,
+ oid="2.16.840.1.101.3.4.2.1")
+
+ if config.get('slow_tests'):
+ tests += [LargeSHA256Test()]
+
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA384.py b/lib/Crypto/SelfTest/Hash/test_SHA384.py
new file mode 100644
index 0000000..c682eb4
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA384.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA.py: Self-test for the SHA-384 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA384"""
+
+# Test vectors from various sources
+# This is a list of (expected_result, input[, description]) tuples.
+test_data = [
+
+ # RFC 4634: Section Page 8.4, "Test 1"
+ ('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', 'abc'),
+
+ # RFC 4634: Section Page 8.4, "Test 2.2"
+ ('09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'),
+
+ # RFC 4634: Section Page 8.4, "Test 3"
+ ('9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985', 'a' * 10**6, "'a' * 10**6"),
+
+ # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
+ ('38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ''),
+
+ # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
+ ('71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677',
+ 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
+
+]
+
+def get_tests(config={}):
+ from Crypto.Hash import SHA384
+ from .common import make_hash_tests
+ return make_hash_tests(SHA384, "SHA384", test_data,
+ digest_size=48,
+ oid='2.16.840.1.101.3.4.2.2')
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA3_224.py b/lib/Crypto/SelfTest/Hash/test_SHA3_224.py
new file mode 100644
index 0000000..f92147a
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA3_224.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA3_224.py: Self-test for the SHA-3/224 hash function
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA3_224"""
+
+import unittest
+from binascii import hexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+from Crypto.Hash import SHA3_224 as SHA3
+from Crypto.Util.py3compat import b
+
+
+class APITest(unittest.TestCase):
+
+ def test_update_after_digest(self):
+ msg=b("rrrrttt")
+
+ # Normally, update() cannot be done after digest()
+ h = SHA3.new(data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = SHA3.new(data=msg).digest()
+
+ # With the proper flag, it is allowed
+ h = SHA3.new(data=msg[:4], update_after_digest=True)
+ self.assertEqual(h.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h.update(msg[4:])
+ self.assertEqual(h.digest(), dig2)
+
+
+def get_tests(config={}):
+ from .common import make_hash_tests
+
+ tests = []
+
+ test_vectors = load_test_vectors(("Hash", "SHA3"),
+ "ShortMsgKAT_SHA3-224.txt",
+ "KAT SHA-3 224",
+ { "len" : lambda x: int(x) } ) or []
+
+ test_data = []
+ for tv in test_vectors:
+ if tv.len == 0:
+ tv.msg = b("")
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests += make_hash_tests(SHA3, "SHA3_224", test_data,
+ digest_size=SHA3.digest_size,
+ oid="2.16.840.1.101.3.4.2.7")
+ tests += list_test_cases(APITest)
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA3_256.py b/lib/Crypto/SelfTest/Hash/test_SHA3_256.py
new file mode 100644
index 0000000..432c932
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA3_256.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA3_256.py: Self-test for the SHA-3/256 hash function
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA3_256"""
+
+import unittest
+from binascii import hexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+from Crypto.Hash import SHA3_256 as SHA3
+from Crypto.Util.py3compat import b
+
+
+class APITest(unittest.TestCase):
+
+ def test_update_after_digest(self):
+ msg=b("rrrrttt")
+
+ # Normally, update() cannot be done after digest()
+ h = SHA3.new(data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = SHA3.new(data=msg).digest()
+
+ # With the proper flag, it is allowed
+ h = SHA3.new(data=msg[:4], update_after_digest=True)
+ self.assertEqual(h.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h.update(msg[4:])
+ self.assertEqual(h.digest(), dig2)
+
+
+def get_tests(config={}):
+ from .common import make_hash_tests
+
+ tests = []
+
+ test_vectors = load_test_vectors(("Hash", "SHA3"),
+ "ShortMsgKAT_SHA3-256.txt",
+ "KAT SHA-3 256",
+ { "len" : lambda x: int(x) } ) or []
+
+ test_data = []
+ for tv in test_vectors:
+ if tv.len == 0:
+ tv.msg = b("")
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+
+ tests += make_hash_tests(SHA3, "SHA3_256", test_data,
+ digest_size=SHA3.digest_size,
+ oid="2.16.840.1.101.3.4.2.8")
+ tests += list_test_cases(APITest)
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA3_384.py b/lib/Crypto/SelfTest/Hash/test_SHA3_384.py
new file mode 100644
index 0000000..b0ba1bf
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA3_384.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA3_384.py: Self-test for the SHA-3/384 hash function
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA3_384"""
+
+import unittest
+from binascii import hexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+from Crypto.Hash import SHA3_384 as SHA3
+from Crypto.Util.py3compat import b
+
+
+class APITest(unittest.TestCase):
+
+ def test_update_after_digest(self):
+ msg=b("rrrrttt")
+
+ # Normally, update() cannot be done after digest()
+ h = SHA3.new(data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = SHA3.new(data=msg).digest()
+
+ # With the proper flag, it is allowed
+ h = SHA3.new(data=msg[:4], update_after_digest=True)
+ self.assertEqual(h.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h.update(msg[4:])
+ self.assertEqual(h.digest(), dig2)
+
+
+def get_tests(config={}):
+ from .common import make_hash_tests
+
+ tests = []
+
+ test_vectors = load_test_vectors(("Hash", "SHA3"),
+ "ShortMsgKAT_SHA3-384.txt",
+ "KAT SHA-3 384",
+ { "len" : lambda x: int(x) } ) or []
+
+ test_data = []
+ for tv in test_vectors:
+ if tv.len == 0:
+ tv.msg = b("")
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests += make_hash_tests(SHA3, "SHA3_384", test_data,
+ digest_size=SHA3.digest_size,
+ oid="2.16.840.1.101.3.4.2.9")
+ tests += list_test_cases(APITest)
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA3_512.py b/lib/Crypto/SelfTest/Hash/test_SHA3_512.py
new file mode 100644
index 0000000..7d1007a
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA3_512.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA3_512.py: Self-test for the SHA-3/512 hash function
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA3_512"""
+
+import unittest
+from binascii import hexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+from Crypto.Hash import SHA3_512 as SHA3
+from Crypto.Util.py3compat import b
+
+
+class APITest(unittest.TestCase):
+
+ def test_update_after_digest(self):
+ msg=b("rrrrttt")
+
+ # Normally, update() cannot be done after digest()
+ h = SHA3.new(data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = SHA3.new(data=msg).digest()
+
+ # With the proper flag, it is allowed
+ h = SHA3.new(data=msg[:4], update_after_digest=True)
+ self.assertEqual(h.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h.update(msg[4:])
+ self.assertEqual(h.digest(), dig2)
+
+
+def get_tests(config={}):
+ from .common import make_hash_tests
+
+ tests = []
+
+ test_vectors = load_test_vectors(("Hash", "SHA3"),
+ "ShortMsgKAT_SHA3-512.txt",
+ "KAT SHA-3 512",
+ { "len" : lambda x: int(x) } ) or []
+
+ test_data = []
+ for tv in test_vectors:
+ if tv.len == 0:
+ tv.msg = b("")
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests += make_hash_tests(SHA3, "SHA3_512", test_data,
+ digest_size=SHA3.digest_size,
+ oid="2.16.840.1.101.3.4.2.10")
+ tests += list_test_cases(APITest)
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_SHA512.py b/lib/Crypto/SelfTest/Hash/test_SHA512.py
new file mode 100644
index 0000000..20961ac
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHA512.py
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Hash/test_SHA512.py: Self-test for the SHA-512 hash function
+#
+# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHA512"""
+
+from binascii import hexlify
+
+from Crypto.Hash import SHA512
+from .common import make_hash_tests
+from Crypto.SelfTest.loader import load_test_vectors
+
+# Test vectors from various sources
+# This is a list of (expected_result, input[, description]) tuples.
+test_data_512_other = [
+
+ # RFC 4634: Section Page 8.4, "Test 1"
+ ('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc'),
+
+ # RFC 4634: Section Page 8.4, "Test 2.1"
+ ('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'),
+
+ # RFC 4634: Section Page 8.4, "Test 3"
+ ('e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b', 'a' * 10**6, "'a' * 10**6"),
+
+ # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
+ ('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', ''),
+
+ ('af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c', 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
+]
+
+
+def get_tests_SHA512():
+
+ test_vectors = load_test_vectors(("Hash", "SHA2"),
+ "SHA512ShortMsg.rsp",
+ "KAT SHA-512",
+ {"len": lambda x: int(x)}) or []
+
+ test_data = test_data_512_other[:]
+ for tv in test_vectors:
+ try:
+ if tv.startswith('['):
+ continue
+ except AttributeError:
+ pass
+ if tv.len == 0:
+ tv.msg = b""
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests = make_hash_tests(SHA512, "SHA512", test_data,
+ digest_size=64,
+ oid="2.16.840.1.101.3.4.2.3")
+ return tests
+
+
+def get_tests_SHA512_224():
+
+ test_vectors = load_test_vectors(("Hash", "SHA2"),
+ "SHA512_224ShortMsg.rsp",
+ "KAT SHA-512/224",
+ {"len": lambda x: int(x)}) or []
+
+ test_data = []
+ for tv in test_vectors:
+ try:
+ if tv.startswith('['):
+ continue
+ except AttributeError:
+ pass
+ if tv.len == 0:
+ tv.msg = b""
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests = make_hash_tests(SHA512, "SHA512/224", test_data,
+ digest_size=28,
+ oid="2.16.840.1.101.3.4.2.5",
+ extra_params={ "truncate" : "224" })
+ return tests
+
+
+def get_tests_SHA512_256():
+
+ test_vectors = load_test_vectors(("Hash", "SHA2"),
+ "SHA512_256ShortMsg.rsp",
+ "KAT SHA-512/256",
+ {"len": lambda x: int(x)}) or []
+
+ test_data = []
+ for tv in test_vectors:
+ try:
+ if tv.startswith('['):
+ continue
+ except AttributeError:
+ pass
+ if tv.len == 0:
+ tv.msg = b""
+ test_data.append((hexlify(tv.md), tv.msg, tv.desc))
+
+ tests = make_hash_tests(SHA512, "SHA512/256", test_data,
+ digest_size=32,
+ oid="2.16.840.1.101.3.4.2.6",
+ extra_params={ "truncate" : "256" })
+ return tests
+
+
+def get_tests(config={}):
+
+ tests = []
+ tests += get_tests_SHA512()
+ tests += get_tests_SHA512_224()
+ tests += get_tests_SHA512_256()
+ return tests
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/SelfTest/Hash/test_SHAKE.py b/lib/Crypto/SelfTest/Hash/test_SHAKE.py
new file mode 100644
index 0000000..29bd34e
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_SHAKE.py
@@ -0,0 +1,143 @@
+# ===================================================================
+#
+# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.SHAKE128 and SHAKE256"""
+
+import unittest
+from binascii import hexlify, unhexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import SHAKE128, SHAKE256
+from Crypto.Util.py3compat import b, bchr, bord, tobytes
+
+class SHAKETest(unittest.TestCase):
+
+ def test_new_positive(self):
+
+ xof1 = self.shake.new()
+ xof2 = self.shake.new(data=b("90"))
+ xof3 = self.shake.new().update(b("90"))
+
+ self.assertNotEqual(xof1.read(10), xof2.read(10))
+ xof3.read(10)
+ self.assertEqual(xof2.read(10), xof3.read(10))
+
+ def test_update(self):
+ pieces = [bchr(10) * 200, bchr(20) * 300]
+ h = self.shake.new()
+ h.update(pieces[0]).update(pieces[1])
+ digest = h.read(10)
+ h = self.shake.new()
+ h.update(pieces[0] + pieces[1])
+ self.assertEqual(h.read(10), digest)
+
+ def test_update_negative(self):
+ h = self.shake.new()
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = self.shake.new()
+ digest = h.read(90)
+
+ # read returns a byte string of the right length
+ self.assertTrue(isinstance(digest, type(b("digest"))))
+ self.assertEqual(len(digest), 90)
+
+ def test_update_after_read(self):
+ mac = self.shake.new()
+ mac.update(b("rrrr"))
+ mac.read(90)
+ self.assertRaises(TypeError, mac.update, b("ttt"))
+
+
+class SHAKE128Test(SHAKETest):
+ shake = SHAKE128
+
+
+class SHAKE256Test(SHAKETest):
+ shake = SHAKE256
+
+
+class SHAKEVectors(unittest.TestCase):
+ pass
+
+
+test_vectors_128 = load_test_vectors(("Hash", "SHA3"),
+ "ShortMsgKAT_SHAKE128.txt",
+ "Short Messages KAT SHAKE128",
+ { "len" : lambda x: int(x) } ) or []
+
+for idx, tv in enumerate(test_vectors_128):
+ if tv.len == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+
+ def new_test(self, data=data, result=tv.md):
+ hobj = SHAKE128.new(data=data)
+ digest = hobj.read(len(result))
+ self.assertEqual(digest, result)
+
+ setattr(SHAKEVectors, "test_128_%d" % idx, new_test)
+
+
+test_vectors_256 = load_test_vectors(("Hash", "SHA3"),
+ "ShortMsgKAT_SHAKE256.txt",
+ "Short Messages KAT SHAKE256",
+ { "len" : lambda x: int(x) } ) or []
+
+for idx, tv in enumerate(test_vectors_256):
+ if tv.len == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+
+ def new_test(self, data=data, result=tv.md):
+ hobj = SHAKE256.new(data=data)
+ digest = hobj.read(len(result))
+ self.assertEqual(digest, result)
+
+ setattr(SHAKEVectors, "test_256_%d" % idx, new_test)
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(SHAKE128Test)
+ tests += list_test_cases(SHAKE256Test)
+ tests += list_test_cases(SHAKEVectors)
+ return tests
+
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_TupleHash.py b/lib/Crypto/SelfTest/Hash/test_TupleHash.py
new file mode 100644
index 0000000..803dc72
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_TupleHash.py
@@ -0,0 +1,286 @@
+import unittest
+from binascii import unhexlify, hexlify
+
+from Crypto.Util.py3compat import tobytes
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import TupleHash128, TupleHash256
+
+
+class TupleHashTest(unittest.TestCase):
+
+ def new(self, *args, **kwargs):
+ return self.TupleHash.new(*args, **kwargs)
+
+ def test_new_positive(self):
+
+ h = self.new()
+ for new_func in self.TupleHash.new, h.new:
+
+ for dbits in range(64, 1024 + 1, 8):
+ hobj = new_func(digest_bits=dbits)
+ self.assertEqual(hobj.digest_size * 8, dbits)
+
+ for dbytes in range(8, 128 + 1):
+ hobj = new_func(digest_bytes=dbytes)
+ self.assertEqual(hobj.digest_size, dbytes)
+
+ hobj = h.new()
+ self.assertEqual(hobj.digest_size, self.default_bytes)
+
+ def test_new_negative(self):
+
+ h = self.new()
+ for new_func in self.TupleHash.new, h.new:
+ self.assertRaises(TypeError, new_func,
+ digest_bytes=self.minimum_bytes,
+ digest_bits=self.minimum_bits)
+ self.assertRaises(ValueError, new_func, digest_bytes=0)
+ self.assertRaises(ValueError, new_func,
+ digest_bits=self.minimum_bits + 7)
+ self.assertRaises(ValueError, new_func,
+ digest_bits=self.minimum_bits - 8)
+ self.assertRaises(ValueError, new_func,
+ digest_bits=self.minimum_bytes - 1)
+
+ def test_default_digest_size(self):
+ digest = self.new().digest()
+ self.assertEqual(len(digest), self.default_bytes)
+
+ def test_update(self):
+ h = self.new()
+ h.update(b'')
+ h.digest()
+
+ h = self.new()
+ h.update(b'')
+ h.update(b'STRING1')
+ h.update(b'STRING2')
+ mac1 = h.digest()
+
+ h = self.new()
+ h.update(b'STRING1')
+ h.update(b'STRING2')
+ mac2 = h.digest()
+
+ self.assertNotEqual(mac1, mac2)
+
+ def test_update_negative(self):
+ h = self.new()
+ self.assertRaises(TypeError, h.update, u"string")
+ self.assertRaises(TypeError, h.update, None)
+
+ def test_digest(self):
+ h = self.new()
+ digest = h.digest()
+
+ # hexdigest does not change the state
+ self.assertEqual(h.digest(), digest)
+ # digest returns a byte string
+ self.assertTrue(isinstance(digest, type(b"digest")))
+
+ def test_update_after_digest(self):
+ msg = b"rrrrttt"
+
+ # Normally, update() cannot be done after digest()
+ h = self.new()
+ h.update(msg)
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, dig1)
+
+ def test_hex_digest(self):
+ mac = self.new()
+ digest = mac.digest()
+ hexdigest = mac.hexdigest()
+
+ # hexdigest is equivalent to digest
+ self.assertEqual(hexlify(digest), tobytes(hexdigest))
+ # hexdigest does not change the state
+ self.assertEqual(mac.hexdigest(), hexdigest)
+ # hexdigest returns a string
+ self.assertTrue(isinstance(hexdigest, type("digest")))
+
+ def test_bytearray(self):
+
+ data = b"\x00\x01\x02"
+
+ # Data can be a bytearray (during operation)
+ data_ba = bytearray(data)
+
+ h1 = self.new()
+ h2 = self.new()
+ h1.update(data)
+ h2.update(data_ba)
+ data_ba[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+ def test_memoryview(self):
+
+ data = b"\x00\x01\x02"
+
+ def get_mv_ro(data):
+ return memoryview(data)
+
+ def get_mv_rw(data):
+ return memoryview(bytearray(data))
+
+ for get_mv in (get_mv_ro, get_mv_rw):
+
+ # Data can be a memoryview (during operation)
+ data_mv = get_mv(data)
+
+ h1 = self.new()
+ h2 = self.new()
+ h1.update(data)
+ h2.update(data_mv)
+ if not data_mv.readonly:
+ data_mv[:1] = b'\xFF'
+
+ self.assertEqual(h1.digest(), h2.digest())
+
+
+class TupleHash128Test(TupleHashTest):
+
+ TupleHash = TupleHash128
+
+ minimum_bytes = 8
+ default_bytes = 64
+
+ minimum_bits = 64
+ default_bits = 512
+
+
+class TupleHash256Test(TupleHashTest):
+
+ TupleHash = TupleHash256
+
+ minimum_bytes = 8
+ default_bytes = 64
+
+ minimum_bits = 64
+ default_bits = 512
+
+
+class NISTExampleTestVectors(unittest.TestCase):
+
+ # http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TupleHash_samples.pdf
+ test_data = [
+ (
+ (
+ "00 01 02",
+ "10 11 12 13 14 15",
+ ),
+ "",
+ "C5 D8 78 6C 1A FB 9B 82 11 1A B3 4B 65 B2 C0 04"
+ "8F A6 4E 6D 48 E2 63 26 4C E1 70 7D 3F FC 8E D1",
+ "KMAC128 Sample #1 NIST",
+ TupleHash128
+ ),
+ (
+ (
+ "00 01 02",
+ "10 11 12 13 14 15",
+ ),
+ "My Tuple App",
+ "75 CD B2 0F F4 DB 11 54 E8 41 D7 58 E2 41 60 C5"
+ "4B AE 86 EB 8C 13 E7 F5 F4 0E B3 55 88 E9 6D FB",
+ "KMAC128 Sample #2 NIST",
+ TupleHash128
+ ),
+ (
+ (
+ "00 01 02",
+ "10 11 12 13 14 15",
+ "20 21 22 23 24 25 26 27 28",
+ ),
+ "My Tuple App",
+ "E6 0F 20 2C 89 A2 63 1E DA 8D 4C 58 8C A5 FD 07"
+ "F3 9E 51 51 99 8D EC CF 97 3A DB 38 04 BB 6E 84",
+ "KMAC128 Sample #3 NIST",
+ TupleHash128
+ ),
+ (
+ (
+ "00 01 02",
+ "10 11 12 13 14 15",
+ ),
+ "",
+ "CF B7 05 8C AC A5 E6 68 F8 1A 12 A2 0A 21 95 CE"
+ "97 A9 25 F1 DB A3 E7 44 9A 56 F8 22 01 EC 60 73"
+ "11 AC 26 96 B1 AB 5E A2 35 2D F1 42 3B DE 7B D4"
+ "BB 78 C9 AE D1 A8 53 C7 86 72 F9 EB 23 BB E1 94",
+ "KMAC256 Sample #4 NIST",
+ TupleHash256
+ ),
+ (
+ (
+ "00 01 02",
+ "10 11 12 13 14 15",
+ ),
+ "My Tuple App",
+ "14 7C 21 91 D5 ED 7E FD 98 DB D9 6D 7A B5 A1 16"
+ "92 57 6F 5F E2 A5 06 5F 3E 33 DE 6B BA 9F 3A A1"
+ "C4 E9 A0 68 A2 89 C6 1C 95 AA B3 0A EE 1E 41 0B"
+ "0B 60 7D E3 62 0E 24 A4 E3 BF 98 52 A1 D4 36 7E",
+ "KMAC256 Sample #5 NIST",
+ TupleHash256
+ ),
+ (
+ (
+ "00 01 02",
+ "10 11 12 13 14 15",
+ "20 21 22 23 24 25 26 27 28",
+ ),
+ "My Tuple App",
+ "45 00 0B E6 3F 9B 6B FD 89 F5 47 17 67 0F 69 A9"
+ "BC 76 35 91 A4 F0 5C 50 D6 88 91 A7 44 BC C6 E7"
+ "D6 D5 B5 E8 2C 01 8D A9 99 ED 35 B0 BB 49 C9 67"
+ "8E 52 6A BD 8E 85 C1 3E D2 54 02 1D B9 E7 90 CE",
+ "KMAC256 Sample #6 NIST",
+ TupleHash256
+ ),
+
+
+
+ ]
+
+ def setUp(self):
+ td = []
+ for tv_in in self.test_data:
+ tv_out = [None] * len(tv_in)
+
+ tv_out[0] = []
+ for string in tv_in[0]:
+ tv_out[0].append(unhexlify(string.replace(" ", "")))
+
+ tv_out[1] = tobytes(tv_in[1]) # Custom
+ tv_out[2] = unhexlify(tv_in[2].replace(" ", ""))
+ tv_out[3] = tv_in[3]
+ tv_out[4] = tv_in[4]
+ td.append(tv_out)
+ self.test_data = td
+
+ def runTest(self):
+
+ for data, custom, digest, text, module in self.test_data:
+ hd = module.new(custom=custom, digest_bytes=len(digest))
+ for string in data:
+ hd.update(string)
+ self.assertEqual(hd.digest(), digest, msg=text)
+
+
+def get_tests(config={}):
+ tests = []
+
+ tests += list_test_cases(TupleHash128Test)
+ tests += list_test_cases(TupleHash256Test)
+ tests.append(NISTExampleTestVectors())
+
+ return tests
+
+
+if __name__ == '__main__':
+ def suite():
+ return unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_cSHAKE.py b/lib/Crypto/SelfTest/Hash/test_cSHAKE.py
new file mode 100644
index 0000000..72ad341
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_cSHAKE.py
@@ -0,0 +1,178 @@
+# ===================================================================
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.cSHAKE128 and cSHAKE256"""
+
+import unittest
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import cSHAKE128, cSHAKE256, SHAKE128, SHAKE256
+from Crypto.Util.py3compat import b, bchr, tobytes
+
+
+class cSHAKETest(unittest.TestCase):
+
+ def test_left_encode(self):
+ from Crypto.Hash.cSHAKE128 import _left_encode
+ self.assertEqual(_left_encode(0), b'\x01\x00')
+ self.assertEqual(_left_encode(1), b'\x01\x01')
+ self.assertEqual(_left_encode(256), b'\x02\x01\x00')
+
+ def test_bytepad(self):
+ from Crypto.Hash.cSHAKE128 import _bytepad
+ self.assertEqual(_bytepad(b'', 4), b'\x01\x04\x00\x00')
+ self.assertEqual(_bytepad(b'A', 4), b'\x01\x04A\x00')
+ self.assertEqual(_bytepad(b'AA', 4), b'\x01\x04AA')
+ self.assertEqual(_bytepad(b'AAA', 4), b'\x01\x04AAA\x00\x00\x00')
+ self.assertEqual(_bytepad(b'AAAA', 4), b'\x01\x04AAAA\x00\x00')
+ self.assertEqual(_bytepad(b'AAAAA', 4), b'\x01\x04AAAAA\x00')
+ self.assertEqual(_bytepad(b'AAAAAA', 4), b'\x01\x04AAAAAA')
+ self.assertEqual(_bytepad(b'AAAAAAA', 4), b'\x01\x04AAAAAAA\x00\x00\x00')
+
+ def test_new_positive(self):
+
+ xof1 = self.cshake.new()
+ xof2 = self.cshake.new(data=b("90"))
+ xof3 = self.cshake.new().update(b("90"))
+
+ self.assertNotEqual(xof1.read(10), xof2.read(10))
+ xof3.read(10)
+ self.assertEqual(xof2.read(10), xof3.read(10))
+
+ xof1 = self.cshake.new()
+ ref = xof1.read(10)
+ xof2 = self.cshake.new(custom=b(""))
+ xof3 = self.cshake.new(custom=b("foo"))
+
+ self.assertEqual(ref, xof2.read(10))
+ self.assertNotEqual(ref, xof3.read(10))
+
+ xof1 = self.cshake.new(custom=b("foo"))
+ xof2 = self.cshake.new(custom=b("foo"), data=b("90"))
+ xof3 = self.cshake.new(custom=b("foo")).update(b("90"))
+
+ self.assertNotEqual(xof1.read(10), xof2.read(10))
+ xof3.read(10)
+ self.assertEqual(xof2.read(10), xof3.read(10))
+
+ def test_update(self):
+ pieces = [bchr(10) * 200, bchr(20) * 300]
+ h = self.cshake.new()
+ h.update(pieces[0]).update(pieces[1])
+ digest = h.read(10)
+ h = self.cshake.new()
+ h.update(pieces[0] + pieces[1])
+ self.assertEqual(h.read(10), digest)
+
+ def test_update_negative(self):
+ h = self.cshake.new()
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = self.cshake.new()
+ digest = h.read(90)
+
+ # read returns a byte string of the right length
+ self.assertTrue(isinstance(digest, type(b("digest"))))
+ self.assertEqual(len(digest), 90)
+
+ def test_update_after_read(self):
+ mac = self.cshake.new()
+ mac.update(b("rrrr"))
+ mac.read(90)
+ self.assertRaises(TypeError, mac.update, b("ttt"))
+
+ def test_shake(self):
+ # When no customization string is passed, results must match SHAKE
+ for digest_len in range(64):
+ xof1 = self.cshake.new(b'TEST')
+ xof2 = self.shake.new(b'TEST')
+ self.assertEqual(xof1.read(digest_len), xof2.read(digest_len))
+
+
+class cSHAKE128Test(cSHAKETest):
+ cshake = cSHAKE128
+ shake = SHAKE128
+
+
+class cSHAKE256Test(cSHAKETest):
+ cshake = cSHAKE256
+ shake = SHAKE256
+
+
+class cSHAKEVectors(unittest.TestCase):
+ pass
+
+
+vector_files = [("ShortMsgSamples_cSHAKE128.txt", "Short Message Samples cSHAKE128", "128_cshake", cSHAKE128),
+ ("ShortMsgSamples_cSHAKE256.txt", "Short Message Samples cSHAKE256", "256_cshake", cSHAKE256),
+ ("CustomMsgSamples_cSHAKE128.txt", "Custom Message Samples cSHAKE128", "custom_128_cshake", cSHAKE128),
+ ("CustomMsgSamples_cSHAKE256.txt", "Custom Message Samples cSHAKE256", "custom_256_cshake", cSHAKE256),
+ ]
+
+for file, descr, tag, test_class in vector_files:
+
+ test_vectors = load_test_vectors(("Hash", "SHA3"), file, descr,
+ {"len": lambda x: int(x),
+ "nlen": lambda x: int(x),
+ "slen": lambda x: int(x)}) or []
+
+ for idx, tv in enumerate(test_vectors):
+ if getattr(tv, "len", 0) == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+ assert(tv.len == len(tv.msg)*8)
+ if getattr(tv, "nlen", 0) != 0:
+ raise ValueError("Unsupported cSHAKE test vector")
+ if getattr(tv, "slen", 0) == 0:
+ custom = b("")
+ else:
+ custom = tobytes(tv.s)
+ assert(tv.slen == len(tv.s)*8)
+
+ def new_test(self, data=data, result=tv.md, custom=custom, test_class=test_class):
+ hobj = test_class.new(data=data, custom=custom)
+ digest = hobj.read(len(result))
+ self.assertEqual(digest, result)
+
+ setattr(cSHAKEVectors, "test_%s_%d" % (tag, idx), new_test)
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(cSHAKE128Test)
+ tests += list_test_cases(cSHAKE256Test)
+ tests += list_test_cases(cSHAKEVectors)
+ return tests
+
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/Hash/test_keccak.py b/lib/Crypto/SelfTest/Hash/test_keccak.py
new file mode 100644
index 0000000..54cdf27
--- /dev/null
+++ b/lib/Crypto/SelfTest/Hash/test_keccak.py
@@ -0,0 +1,250 @@
+# ===================================================================
+#
+# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Self-test suite for Crypto.Hash.keccak"""
+
+import unittest
+from binascii import hexlify, unhexlify
+
+from Crypto.SelfTest.loader import load_test_vectors
+from Crypto.SelfTest.st_common import list_test_cases
+
+from Crypto.Hash import keccak
+from Crypto.Util.py3compat import b, tobytes, bchr
+
+class KeccakTest(unittest.TestCase):
+
+ def test_new_positive(self):
+
+ for digest_bits in (224, 256, 384, 512):
+ hobj = keccak.new(digest_bits=digest_bits)
+ self.assertEqual(hobj.digest_size, digest_bits // 8)
+
+ hobj2 = hobj.new()
+ self.assertEqual(hobj2.digest_size, digest_bits // 8)
+
+ for digest_bytes in (28, 32, 48, 64):
+ hobj = keccak.new(digest_bytes=digest_bytes)
+ self.assertEqual(hobj.digest_size, digest_bytes)
+
+ hobj2 = hobj.new()
+ self.assertEqual(hobj2.digest_size, digest_bytes)
+
+ def test_new_positive2(self):
+
+ digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest()
+ digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest()
+ self.assertEqual(digest1, digest2)
+
+ def test_new_negative(self):
+
+ # keccak.new needs digest size
+ self.assertRaises(TypeError, keccak.new)
+
+ h = keccak.new(digest_bits=512)
+
+ # Either bits or bytes can be specified
+ self.assertRaises(TypeError, keccak.new,
+ digest_bytes=64,
+ digest_bits=512)
+
+ # Range
+ self.assertRaises(ValueError, keccak.new, digest_bytes=0)
+ self.assertRaises(ValueError, keccak.new, digest_bytes=1)
+ self.assertRaises(ValueError, keccak.new, digest_bytes=65)
+ self.assertRaises(ValueError, keccak.new, digest_bits=0)
+ self.assertRaises(ValueError, keccak.new, digest_bits=1)
+ self.assertRaises(ValueError, keccak.new, digest_bits=513)
+
+ def test_update(self):
+ pieces = [bchr(10) * 200, bchr(20) * 300]
+ h = keccak.new(digest_bytes=64)
+ h.update(pieces[0]).update(pieces[1])
+ digest = h.digest()
+ h = keccak.new(digest_bytes=64)
+ h.update(pieces[0] + pieces[1])
+ self.assertEqual(h.digest(), digest)
+
+ def test_update_negative(self):
+ h = keccak.new(digest_bytes=64)
+ self.assertRaises(TypeError, h.update, u"string")
+
+ def test_digest(self):
+ h = keccak.new(digest_bytes=64)
+ digest = h.digest()
+
+ # hexdigest does not change the state
+ self.assertEqual(h.digest(), digest)
+ # digest returns a byte string
+ self.assertTrue(isinstance(digest, type(b("digest"))))
+
+ def test_hex_digest(self):
+ mac = keccak.new(digest_bits=512)
+ digest = mac.digest()
+ hexdigest = mac.hexdigest()
+
+ # hexdigest is equivalent to digest
+ self.assertEqual(hexlify(digest), tobytes(hexdigest))
+ # hexdigest does not change the state
+ self.assertEqual(mac.hexdigest(), hexdigest)
+ # hexdigest returns a string
+ self.assertTrue(isinstance(hexdigest, type("digest")))
+
+ def test_update_after_digest(self):
+ msg=b("rrrrttt")
+
+ # Normally, update() cannot be done after digest()
+ h = keccak.new(digest_bits=512, data=msg[:4])
+ dig1 = h.digest()
+ self.assertRaises(TypeError, h.update, msg[4:])
+ dig2 = keccak.new(digest_bits=512, data=msg).digest()
+
+ # With the proper flag, it is allowed
+ h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True)
+ self.assertEqual(h.digest(), dig1)
+ # ... and the subsequent digest applies to the entire message
+ # up to that point
+ h.update(msg[4:])
+ self.assertEqual(h.digest(), dig2)
+
+
+class KeccakVectors(unittest.TestCase):
+ pass
+
+ # TODO: add ExtremelyLong tests
+
+
+test_vectors_224 = load_test_vectors(("Hash", "keccak"),
+ "ShortMsgKAT_224.txt",
+ "Short Messages KAT 224",
+ {"len": lambda x: int(x)}) or []
+
+test_vectors_224 += load_test_vectors(("Hash", "keccak"),
+ "LongMsgKAT_224.txt",
+ "Long Messages KAT 224",
+ {"len": lambda x: int(x)}) or []
+
+for idx, tv in enumerate(test_vectors_224):
+ if tv.len == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+
+ def new_test(self, data=data, result=tv.md):
+ hobj = keccak.new(digest_bits=224, data=data)
+ self.assertEqual(hobj.digest(), result)
+
+ setattr(KeccakVectors, "test_224_%d" % idx, new_test)
+
+# ---
+
+test_vectors_256 = load_test_vectors(("Hash", "keccak"),
+ "ShortMsgKAT_256.txt",
+ "Short Messages KAT 256",
+ { "len" : lambda x: int(x) } ) or []
+
+test_vectors_256 += load_test_vectors(("Hash", "keccak"),
+ "LongMsgKAT_256.txt",
+ "Long Messages KAT 256",
+ { "len" : lambda x: int(x) } ) or []
+
+for idx, tv in enumerate(test_vectors_256):
+ if tv.len == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+
+ def new_test(self, data=data, result=tv.md):
+ hobj = keccak.new(digest_bits=256, data=data)
+ self.assertEqual(hobj.digest(), result)
+
+ setattr(KeccakVectors, "test_256_%d" % idx, new_test)
+
+
+# ---
+
+test_vectors_384 = load_test_vectors(("Hash", "keccak"),
+ "ShortMsgKAT_384.txt",
+ "Short Messages KAT 384",
+ {"len": lambda x: int(x)}) or []
+
+test_vectors_384 += load_test_vectors(("Hash", "keccak"),
+ "LongMsgKAT_384.txt",
+ "Long Messages KAT 384",
+ {"len": lambda x: int(x)}) or []
+
+for idx, tv in enumerate(test_vectors_384):
+ if tv.len == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+
+ def new_test(self, data=data, result=tv.md):
+ hobj = keccak.new(digest_bits=384, data=data)
+ self.assertEqual(hobj.digest(), result)
+
+ setattr(KeccakVectors, "test_384_%d" % idx, new_test)
+
+# ---
+
+test_vectors_512 = load_test_vectors(("Hash", "keccak"),
+ "ShortMsgKAT_512.txt",
+ "Short Messages KAT 512",
+ {"len": lambda x: int(x)}) or []
+
+test_vectors_512 += load_test_vectors(("Hash", "keccak"),
+ "LongMsgKAT_512.txt",
+ "Long Messages KAT 512",
+ {"len": lambda x: int(x)}) or []
+
+for idx, tv in enumerate(test_vectors_512):
+ if tv.len == 0:
+ data = b("")
+ else:
+ data = tobytes(tv.msg)
+
+ def new_test(self, data=data, result=tv.md):
+ hobj = keccak.new(digest_bits=512, data=data)
+ self.assertEqual(hobj.digest(), result)
+
+ setattr(KeccakVectors, "test_512_%d" % idx, new_test)
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(KeccakTest)
+ tests += list_test_cases(KeccakVectors)
+ return tests
+
+
+if __name__ == '__main__':
+ import unittest
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')