summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2017-11-14 19:45:43 +0100
committerMichał Górny <mgorny@gentoo.org>2017-11-14 19:45:43 +0100
commit1b2aa500ac7f32f8931097a9a4c222d842b7f856 (patch)
tree0d3be74d940a91d21d1436645e4050ca10c63949
parentbbcea9e8f99f6c0546d5c2d011df52fd7de262fd (diff)
downloadgemato-1b2aa500ac7f32f8931097a9a4c222d842b7f856.tar.gz
Add a utility to compare multiple hash implementations
-rwxr-xr-xutils/fuzzy-hash-tester.py80
1 files changed, 80 insertions, 0 deletions
diff --git a/utils/fuzzy-hash-tester.py b/utils/fuzzy-hash-tester.py
new file mode 100755
index 0000000..2d0c426
--- /dev/null
+++ b/utils/fuzzy-hash-tester.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# dumb utility to randomly test different hash implementations
+# for compliance
+
+import base64
+import functools
+import hashlib
+import random
+import subprocess
+import sys
+
+import pyblake2
+
+
+class ExternalToolHash(object):
+ def __init__(self, argv):
+ self.subp = subprocess.Popen(argv,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+
+ def update(self, data):
+ self.subp.stdin.write(data)
+
+ def hexdigest(self):
+ stdo, stde = self.subp.communicate()
+ return stdo.decode('ASCII').split()[0]
+
+
+ALGORITHMS = {
+ 'md5': [hashlib.md5,
+ functools.partial(ExternalToolHash, 'md5sum')],
+ 'sha1': [hashlib.sha1,
+ functools.partial(ExternalToolHash, 'sha1sum')],
+ 'sha224': [hashlib.sha224,
+ functools.partial(ExternalToolHash, 'sha224sum')],
+ 'sha256': [hashlib.sha256,
+ functools.partial(ExternalToolHash, 'sha256sum')],
+ 'sha384': [hashlib.sha384,
+ functools.partial(ExternalToolHash, 'sha384sum')],
+ 'sha512': [hashlib.sha512,
+ functools.partial(ExternalToolHash, 'sha512sum')],
+ 'blake2b': [hashlib.blake2b, pyblake2.blake2b,
+ functools.partial(ExternalToolHash, 'b2sum')],
+}
+
+
+def main(algo_name, min_size, max_size=None):
+ impls = ALGORITHMS[algo_name]
+ if max_size is None:
+ max_size = min_size
+ min_size = int(min_size)
+ max_size = int(max_size)
+
+ with open('/dev/urandom', 'rb') as urandom:
+ i = 0
+ while True:
+ size = random.randint(min_size, max_size)
+ data = urandom.read(size)
+ digests = {}
+ for a in impls:
+ h = a()
+ h.update(data)
+ digests[a] = h.hexdigest()
+
+ if len(set(digests.values())) != 1:
+ print('Inconsistent hash values found!')
+ print('Hash values:')
+ for a, v in digests.items():
+ print(' {}: {}'.format(a, v))
+ print('Data block as base64:')
+ print(base64.encodebytes(data).decode())
+ sys.exit(1)
+
+ i += 1
+ if i % 1000 == 0:
+ print('{} blocks tested.'.format(i))
+
+
+if __name__ == '__main__':
+ main(*sys.argv[1:])