|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""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()) |
|
|
|
|
|
self.assertEqual(self.expected, out1) |
|
if sys.version_info[0] == 2: |
|
self.assertEqual(self.expected, out2) |
|
self.assertEqual(self.expected, out3) |
|
else: |
|
self.assertEqual(self.expected.decode(), out2) |
|
self.assertEqual(self.expected.decode(), out3) |
|
self.assertEqual(self.expected, out4) |
|
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
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()) |
|
|
|
|
|
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: |
|
|
|
|
|
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()) |
|
|
|
|
|
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) |
|
|
|
|
|
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()) |
|
|
|
|
|
h.verify(self.result) |
|
h.hexverify(result_hex) |
|
|
|
|
|
wrong_mac = strxor_c(self.result, 255) |
|
self.assertRaises(ValueError, h.verify, wrong_mac) |
|
self.assertRaises(ValueError, h.hexverify, "4556") |
|
|
|
|
|
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()) |
|
|
|
|
|
try: |
|
h = self.module.new(self.key, self.data, **self.params) |
|
h2 = h.copy() |
|
h3 = h.copy() |
|
|
|
|
|
h2.update(b"bla") |
|
self.assertEqual(h3.digest(), self.result) |
|
|
|
|
|
h.update(b"bla") |
|
self.assertEqual(h.digest(), h2.digest()) |
|
except NotImplementedError: |
|
pass |
|
|
|
|
|
self.assertTrue(isinstance(h.digest(), type(b""))) |
|
self.assertTrue(isinstance(h.hexdigest(), type(""))) |
|
|
|
|
|
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 |
|
|
|
|
|
|