second commit

This commit is contained in:
2024-12-27 22:31:23 +09:00
parent 2353324570
commit 10a0f110ca
8819 changed files with 1307198 additions and 28 deletions

View File

@ -0,0 +1,62 @@
# -*- 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)
from Crypto.SelfTest.Hash import test_TurboSHAKE; tests += test_TurboSHAKE.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:

View File

@ -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:

View File

@ -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')

View File

@ -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')

View File

@ -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')

View File

@ -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')

View File

@ -0,0 +1,367 @@
# ===================================================================
# 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]
class KangarooTwelveTV(unittest.TestCase):
# https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt
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)
# https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/
def test_ptn_8191(self):
tv = """1B 57 76 36 F7 23 64 3E 99 0C C7 D6 A6 59 83 74
36 FD 6A 10 36 26 60 0E B8 30 1C D1 DB E5 53 D6"""
btv = txt2bin(tv)
# All at once
res = K12.new(data=ptn(8191)).read(32)
self.assertEqual(res, btv)
def test_ptn_8192(self):
tv = """48 F2 56 F6 77 2F 9E DF B6 A8 B6 61 EC 92 DC 93
B9 5E BD 05 A0 8A 17 B3 9A E3 49 08 70 C9 26 C3"""
btv = txt2bin(tv)
# All at once
res = K12.new(data=ptn(8192)).read(32)
self.assertEqual(res, btv)
def test_ptn_8192_8189(self):
tv = """3E D1 2F 70 FB 05 DD B5 86 89 51 0A B3 E4 D2 3C
6C 60 33 84 9A A0 1E 1D 8C 22 0A 29 7F ED CD 0B"""
btv = txt2bin(tv)
# All at once
res = K12.new(data=ptn(8192), custom=ptn(8189)).read(32)
self.assertEqual(res, btv)
def test_ptn_8192_8190(self):
tv = """6A 7C 1B 6A 5C D0 D8 C9 CA 94 3A 4A 21 6C C6 46
04 55 9A 2E A4 5F 78 57 0A 15 25 3D 67 BA 00 AE"""
btv = txt2bin(tv)
# All at once
res = K12.new(data=ptn(8192), custom=ptn(8190)).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')

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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')

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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')

View File

@ -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')

View File

@ -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')

View File

@ -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')

View File

@ -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:

View File

@ -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')

View File

@ -0,0 +1,302 @@
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)
h = self.new()
h.update(b'STRING1', b'STRING2')
self.assertEqual(mac2, h.digest())
h = self.new()
t = b'STRING1', b'STRING2'
h.update(*t)
self.assertEqual(mac2, h.digest())
def test_update_negative(self):
h = self.new()
self.assertRaises(TypeError, h.update, u"string")
self.assertRaises(TypeError, h.update, None)
self.assertRaises(TypeError, h.update, (b'STRING1', b'STRING2'))
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:
hd1 = module.new(custom=custom, digest_bytes=len(digest))
hd2 = module.new(custom=custom, digest_bytes=len(digest))
# Call update() for each element
for string in data:
hd1.update(string)
# One single update for all elements
hd2.update(*data)
self.assertEqual(hd1.digest(), digest, msg=text)
self.assertEqual(hd2.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')

View File

@ -0,0 +1,468 @@
"""Self-test suite for Crypto.Hash.TurboSHAKE128 and TurboSHAKE256"""
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import TurboSHAKE128, TurboSHAKE256
from Crypto.Util.py3compat import bchr
class TurboSHAKETest(unittest.TestCase):
def test_new_positive(self):
xof1 = self.TurboSHAKE.new()
xof1.update(b'90')
xof2 = self.TurboSHAKE.new(domain=0x1F)
xof2.update(b'90')
xof3 = self.TurboSHAKE.new(data=b'90')
out1 = xof1.read(128)
out2 = xof2.read(128)
out3 = xof3.read(128)
self.assertEqual(out1, out2)
self.assertEqual(out1, out3)
def test_new_domain(self):
xof1 = self.TurboSHAKE.new(domain=0x1D)
xof2 = self.TurboSHAKE.new(domain=0x20)
self.assertNotEqual(xof1.read(128), xof2.read(128))
def test_update(self):
pieces = [bchr(10) * 200, bchr(20) * 300]
xof1 = self.TurboSHAKE.new()
xof1.update(pieces[0]).update(pieces[1])
digest1 = xof1.read(10)
xof2 = self.TurboSHAKE.new()
xof2.update(pieces[0] + pieces[1])
digest2 = xof2.read(10)
self.assertEqual(digest1, digest2)
def test_update_negative(self):
xof1 = self.TurboSHAKE.new()
self.assertRaises(TypeError, xof1.update, u"string")
def test_read(self):
xof1 = self.TurboSHAKE.new()
digest = xof1.read(90)
# read returns a byte string of the right length
self.assertTrue(isinstance(digest, bytes))
self.assertEqual(len(digest), 90)
def test_update_after_read(self):
xof1 = self.TurboSHAKE.new()
xof1.update(b"rrrr")
xof1.read(90)
self.assertRaises(TypeError, xof1.update, b"ttt")
def test_new(self):
xof1 = self.TurboSHAKE.new(domain=0x07)
xof1.update(b'90')
digest1 = xof1.read(100)
xof2 = xof1.new()
xof2.update(b'90')
digest2 = xof2.read(100)
self.assertEqual(digest1, digest2)
self.assertRaises(TypeError, xof1.new, domain=0x07)
class TurboSHAKE128Test(TurboSHAKETest):
TurboSHAKE = TurboSHAKE128
class TurboSHAKE256Test(TurboSHAKETest):
TurboSHAKE = TurboSHAKE256
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]
class TurboSHAKE128TV(unittest.TestCase):
def test_zero_1(self):
tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53
8C D9 45 A3 97 DD EC 54 1F 1C E4 1A F2 C1 B7 4C"""
btv = txt2bin(tv)
res = TurboSHAKE128.new().read(32)
self.assertEqual(res, btv)
def test_zero_2(self):
tv = """1E 41 5F 1C 59 83 AF F2 16 92 17 27 7D 17 BB 53
8C D9 45 A3 97 DD EC 54 1F 1C E4 1A F2 C1 B7 4C
3E 8C CA E2 A4 DA E5 6C 84 A0 4C 23 85 C0 3C 15
E8 19 3B DF 58 73 73 63 32 16 91 C0 54 62 C8 DF"""
btv = txt2bin(tv)
res = TurboSHAKE128.new().read(64)
self.assertEqual(res, btv)
def test_zero_3(self):
tv = """A3 B9 B0 38 59 00 CE 76 1F 22 AE D5 48 E7 54 DA
10 A5 24 2D 62 E8 C6 58 E3 F3 A9 23 A7 55 56 07"""
btv = txt2bin(tv)
res = TurboSHAKE128.new().read(10032)[-32:]
self.assertEqual(res, btv)
def test_ptn_1(self):
tv = """55 CE DD 6F 60 AF 7B B2 9A 40 42 AE 83 2E F3 F5
8D B7 29 9F 89 3E BB 92 47 24 7D 85 69 58 DA A9"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=ptn(1)).read(32)
self.assertEqual(res, btv)
def test_ptn_17(self):
tv = """9C 97 D0 36 A3 BA C8 19 DB 70 ED E0 CA 55 4E C6
E4 C2 A1 A4 FF BF D9 EC 26 9C A6 A1 11 16 12 33"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=ptn(17)).read(32)
self.assertEqual(res, btv)
def test_ptn_17_2(self):
tv = """96 C7 7C 27 9E 01 26 F7 FC 07 C9 B0 7F 5C DA E1
E0 BE 60 BD BE 10 62 00 40 E7 5D 72 23 A6 24 D2"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=ptn(17**2)).read(32)
self.assertEqual(res, btv)
def test_ptn_17_3(self):
tv = """D4 97 6E B5 6B CF 11 85 20 58 2B 70 9F 73 E1 D6
85 3E 00 1F DA F8 0E 1B 13 E0 D0 59 9D 5F B3 72"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=ptn(17**3)).read(32)
self.assertEqual(res, btv)
def test_ptn_17_4(self):
tv = """DA 67 C7 03 9E 98 BF 53 0C F7 A3 78 30 C6 66 4E
14 CB AB 7F 54 0F 58 40 3B 1B 82 95 13 18 EE 5C"""
btv = txt2bin(tv)
data = ptn(17**4)
# All at once
res = TurboSHAKE128.new(data=data).read(32)
self.assertEqual(res, btv)
# Byte by byte
xof = TurboSHAKE128.new()
for x in data:
xof.update(bchr(x))
res = xof.read(32)
self.assertEqual(res, btv)
# Chunks of various prime sizes
for chunk_size in (13, 17, 19, 23, 31):
xof = TurboSHAKE128.new()
for x in chunked(data, chunk_size):
xof.update(x)
res = xof.read(32)
self.assertEqual(res, btv)
def test_ptn_17_5(self):
tv = """B9 7A 90 6F BF 83 EF 7C 81 25 17 AB F3 B2 D0 AE
A0 C4 F6 03 18 CE 11 CF 10 39 25 12 7F 59 EE CD"""
btv = txt2bin(tv)
data = ptn(17**5)
# All at once
res = TurboSHAKE128.new(data=data).read(32)
self.assertEqual(res, btv)
# Chunks
xof = TurboSHAKE128.new()
for chunk in chunked(data, 8192):
xof.update(chunk)
res = xof.read(32)
self.assertEqual(res, btv)
def test_ptn_17_6(self):
tv = """35 CD 49 4A DE DE D2 F2 52 39 AF 09 A7 B8 EF 0C
4D 1C A4 FE 2D 1A C3 70 FA 63 21 6F E7 B4 C2 B1"""
btv = txt2bin(tv)
data = ptn(17**6)
res = TurboSHAKE128.new(data=data).read(32)
self.assertEqual(res, btv)
def test_ffffff_d01(self):
tv = """BF 32 3F 94 04 94 E8 8E E1 C5 40 FE 66 0B E8 A0
C9 3F 43 D1 5E C0 06 99 84 62 FA 99 4E ED 5D AB"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=b"\xff\xff\xff", domain=0x01).read(32)
self.assertEqual(res, btv)
def test_ff_d06(self):
tv = """8E C9 C6 64 65 ED 0D 4A 6C 35 D1 35 06 71 8D 68
7A 25 CB 05 C7 4C CA 1E 42 50 1A BD 83 87 4A 67"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=b'\xFF', domain=0x06).read(32)
self.assertEqual(res, btv)
def test_ffffff_d07(self):
tv = """B6 58 57 60 01 CA D9 B1 E5 F3 99 A9 F7 77 23 BB
A0 54 58 04 2D 68 20 6F 72 52 68 2D BA 36 63 ED"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=b'\xFF' * 3, domain=0x07).read(32)
self.assertEqual(res, btv)
def test_ffffffffffff_d0b(self):
tv = """8D EE AA 1A EC 47 CC EE 56 9F 65 9C 21 DF A8 E1
12 DB 3C EE 37 B1 81 78 B2 AC D8 05 B7 99 CC 37"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=b'\xFF' * 7, domain=0x0B).read(32)
self.assertEqual(res, btv)
def test_ff_d30(self):
tv = """55 31 22 E2 13 5E 36 3C 32 92 BE D2 C6 42 1F A2
32 BA B0 3D AA 07 C7 D6 63 66 03 28 65 06 32 5B"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=b'\xFF', domain=0x30).read(32)
self.assertEqual(res, btv)
def test_ffffff_d7f(self):
tv = """16 27 4C C6 56 D4 4C EF D4 22 39 5D 0F 90 53 BD
A6 D2 8E 12 2A BA 15 C7 65 E5 AD 0E 6E AF 26 F9"""
btv = txt2bin(tv)
res = TurboSHAKE128.new(data=b'\xFF' * 3, domain=0x7F).read(32)
self.assertEqual(res, btv)
class TurboSHAKE256TV(unittest.TestCase):
def test_zero_1(self):
tv = """36 7A 32 9D AF EA 87 1C 78 02 EC 67 F9 05 AE 13
C5 76 95 DC 2C 66 63 C6 10 35 F5 9A 18 F8 E7 DB
11 ED C0 E1 2E 91 EA 60 EB 6B 32 DF 06 DD 7F 00
2F BA FA BB 6E 13 EC 1C C2 0D 99 55 47 60 0D B0"""
btv = txt2bin(tv)
res = TurboSHAKE256.new().read(64)
self.assertEqual(res, btv)
def test_zero_2(self):
tv = """AB EF A1 16 30 C6 61 26 92 49 74 26 85 EC 08 2F
20 72 65 DC CF 2F 43 53 4E 9C 61 BA 0C 9D 1D 75"""
btv = txt2bin(tv)
res = TurboSHAKE256.new().read(10032)[-32:]
self.assertEqual(res, btv)
def test_ptn_1(self):
tv = """3E 17 12 F9 28 F8 EA F1 05 46 32 B2 AA 0A 24 6E
D8 B0 C3 78 72 8F 60 BC 97 04 10 15 5C 28 82 0E
90 CC 90 D8 A3 00 6A A2 37 2C 5C 5E A1 76 B0 68
2B F2 2B AE 74 67 AC 94 F7 4D 43 D3 9B 04 82 E2"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=ptn(1)).read(64)
self.assertEqual(res, btv)
def test_ptn_17(self):
tv = """B3 BA B0 30 0E 6A 19 1F BE 61 37 93 98 35 92 35
78 79 4E A5 48 43 F5 01 10 90 FA 2F 37 80 A9 E5
CB 22 C5 9D 78 B4 0A 0F BF F9 E6 72 C0 FB E0 97
0B D2 C8 45 09 1C 60 44 D6 87 05 4D A5 D8 E9 C7"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=ptn(17)).read(64)
self.assertEqual(res, btv)
def test_ptn_17_2(self):
tv = """66 B8 10 DB 8E 90 78 04 24 C0 84 73 72 FD C9 57
10 88 2F DE 31 C6 DF 75 BE B9 D4 CD 93 05 CF CA
E3 5E 7B 83 E8 B7 E6 EB 4B 78 60 58 80 11 63 16
FE 2C 07 8A 09 B9 4A D7 B8 21 3C 0A 73 8B 65 C0"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=ptn(17**2)).read(64)
self.assertEqual(res, btv)
def test_ptn_17_3(self):
tv = """C7 4E BC 91 9A 5B 3B 0D D1 22 81 85 BA 02 D2 9E
F4 42 D6 9D 3D 42 76 A9 3E FE 0B F9 A1 6A 7D C0
CD 4E AB AD AB 8C D7 A5 ED D9 66 95 F5 D3 60 AB
E0 9E 2C 65 11 A3 EC 39 7D A3 B7 6B 9E 16 74 FB"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=ptn(17**3)).read(64)
self.assertEqual(res, btv)
def test_ptn_17_4(self):
tv = """02 CC 3A 88 97 E6 F4 F6 CC B6 FD 46 63 1B 1F 52
07 B6 6C 6D E9 C7 B5 5B 2D 1A 23 13 4A 17 0A FD
AC 23 4E AB A9 A7 7C FF 88 C1 F0 20 B7 37 24 61
8C 56 87 B3 62 C4 30 B2 48 CD 38 64 7F 84 8A 1D"""
btv = txt2bin(tv)
data = ptn(17**4)
# All at once
res = TurboSHAKE256.new(data=data).read(64)
self.assertEqual(res, btv)
# Byte by byte
xof = TurboSHAKE256.new()
for x in data:
xof.update(bchr(x))
res = xof.read(64)
self.assertEqual(res, btv)
# Chunks of various prime sizes
for chunk_size in (13, 17, 19, 23, 31):
xof = TurboSHAKE256.new()
for x in chunked(data, chunk_size):
xof.update(x)
res = xof.read(64)
self.assertEqual(res, btv)
def test_ptn_17_5(self):
tv = """AD D5 3B 06 54 3E 58 4B 58 23 F6 26 99 6A EE 50
FE 45 ED 15 F2 02 43 A7 16 54 85 AC B4 AA 76 B4
FF DA 75 CE DF 6D 8C DC 95 C3 32 BD 56 F4 B9 86
B5 8B B1 7D 17 78 BF C1 B1 A9 75 45 CD F4 EC 9F"""
btv = txt2bin(tv)
data = ptn(17**5)
# All at once
res = TurboSHAKE256.new(data=data).read(64)
self.assertEqual(res, btv)
# Chunks
xof = TurboSHAKE256.new()
for chunk in chunked(data, 8192):
xof.update(chunk)
res = xof.read(64)
self.assertEqual(res, btv)
def test_ptn_17_6(self):
tv = """9E 11 BC 59 C2 4E 73 99 3C 14 84 EC 66 35 8E F7
1D B7 4A EF D8 4E 12 3F 78 00 BA 9C 48 53 E0 2C
FE 70 1D 9E 6B B7 65 A3 04 F0 DC 34 A4 EE 3B A8
2C 41 0F 0D A7 0E 86 BF BD 90 EA 87 7C 2D 61 04"""
btv = txt2bin(tv)
data = ptn(17**6)
res = TurboSHAKE256.new(data=data).read(64)
self.assertEqual(res, btv)
def test_ffffff_d01(self):
tv = """D2 1C 6F BB F5 87 FA 22 82 F2 9A EA 62 01 75 FB
02 57 41 3A F7 8A 0B 1B 2A 87 41 9C E0 31 D9 33
AE 7A 4D 38 33 27 A8 A1 76 41 A3 4F 8A 1D 10 03
AD 7D A6 B7 2D BA 84 BB 62 FE F2 8F 62 F1 24 24"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=b"\xff\xff\xff", domain=0x01).read(64)
self.assertEqual(res, btv)
def test_ff_d06(self):
tv = """73 8D 7B 4E 37 D1 8B 7F 22 AD 1B 53 13 E3 57 E3
DD 7D 07 05 6A 26 A3 03 C4 33 FA 35 33 45 52 80
F4 F5 A7 D4 F7 00 EF B4 37 FE 6D 28 14 05 E0 7B
E3 2A 0A 97 2E 22 E6 3A DC 1B 09 0D AE FE 00 4B"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=b'\xFF', domain=0x06).read(64)
self.assertEqual(res, btv)
def test_ffffff_d07(self):
tv = """18 B3 B5 B7 06 1C 2E 67 C1 75 3A 00 E6 AD 7E D7
BA 1C 90 6C F9 3E FB 70 92 EA F2 7F BE EB B7 55
AE 6E 29 24 93 C1 10 E4 8D 26 00 28 49 2B 8E 09
B5 50 06 12 B8 F2 57 89 85 DE D5 35 7D 00 EC 67"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=b'\xFF' * 3, domain=0x07).read(64)
self.assertEqual(res, btv)
def test_ffffffffffff_d0b(self):
tv = """BB 36 76 49 51 EC 97 E9 D8 5F 7E E9 A6 7A 77 18
FC 00 5C F4 25 56 BE 79 CE 12 C0 BD E5 0E 57 36
D6 63 2B 0D 0D FB 20 2D 1B BB 8F FE 3D D7 4C B0
08 34 FA 75 6C B0 34 71 BA B1 3A 1E 2C 16 B3 C0"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=b'\xFF' * 7, domain=0x0B).read(64)
self.assertEqual(res, btv)
def test_ff_d30(self):
tv = """F3 FE 12 87 3D 34 BC BB 2E 60 87 79 D6 B7 0E 7F
86 BE C7 E9 0B F1 13 CB D4 FD D0 C4 E2 F4 62 5E
14 8D D7 EE 1A 52 77 6C F7 7F 24 05 14 D9 CC FC
3B 5D DA B8 EE 25 5E 39 EE 38 90 72 96 2C 11 1A"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=b'\xFF', domain=0x30).read(64)
self.assertEqual(res, btv)
def test_ffffff_d7f(self):
tv = """AB E5 69 C1 F7 7E C3 40 F0 27 05 E7 D3 7C 9A B7
E1 55 51 6E 4A 6A 15 00 21 D7 0B 6F AC 0B B4 0C
06 9F 9A 98 28 A0 D5 75 CD 99 F9 BA E4 35 AB 1A
CF 7E D9 11 0B A9 7C E0 38 8D 07 4B AC 76 87 76"""
btv = txt2bin(tv)
res = TurboSHAKE256.new(data=b'\xFF' * 3, domain=0x7F).read(64)
self.assertEqual(res, btv)
def get_tests(config={}):
tests = []
tests += list_test_cases(TurboSHAKE128Test)
tests += list_test_cases(TurboSHAKE256Test)
tests += list_test_cases(TurboSHAKE128TV)
tests += list_test_cases(TurboSHAKE256TV)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -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')

View File

@ -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')