aboutsummaryrefslogtreecommitdiffstats
path: root/research/experiments/044-specs/check.py
diff options
context:
space:
mode:
Diffstat (limited to 'research/experiments/044-specs/check.py')
-rwxr-xr-xresearch/experiments/044-specs/check.py46
1 files changed, 46 insertions, 0 deletions
diff --git a/research/experiments/044-specs/check.py b/research/experiments/044-specs/check.py
new file mode 100755
index 0000000..bc43090
--- /dev/null
+++ b/research/experiments/044-specs/check.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+"""Research 140 / design 027 stage 1: SHA-256 written in aup (aup's examples/sha256.aup).
+
+Builds it with aup (AUP, default the sibling checkout), runs FIPS 180-2's
+examples and messages of every length 0-129 and some longer ones on Pure's
+three paths (batches, rounds, all compiled) and the default, each digest
+against hashlib; then counts lines (code lines: neither blank nor a comment;
+brace lines: a closing brace alone) of sha256.aup and of sha256.py's
+algorithm (above its main). One JSON line."""
+import hashlib, json, os, random, subprocess, sys, tempfile
+
+here = os.path.dirname(os.path.abspath(__file__))
+pure = os.path.normpath(os.path.join(here, '../../..'))
+aup = os.environ.get('AUP', os.path.join(pure, '..', 'aup'))
+
+def lines(path, stop=None):
+ code = braces = 0
+ for line in open(path):
+ if stop and line.startswith(stop): break
+ text = line.strip()
+ if not text or text.startswith('#'): continue
+ code += 1
+ braces += text == '}'
+ return code, braces
+
+random.seed(140)
+messages = [b'', b'abc', b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
+ b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu']
+messages += [bytes(random.randrange(256) for _ in range(n)) for n in list(range(130)) + [255, 256, 511, 512, 1000, 4096, 10000, 32000]]
+with tempfile.TemporaryDirectory() as tmp:
+ module = os.path.join(tmp, 'sha256.pmod')
+ subprocess.run([os.path.join(aup, 'build', 'aup'), 'build', os.path.join(aup, 'examples', 'sha256.aup'), '-o', module], check=True)
+ given = ''.join(f"message hash {m.hex() or '-'}\n" for m in messages).encode()
+ paths = {}
+ for name, env in (('batches', {'PURE_JIT': '0'}), ('rounds', {'PURE_JIT': '0', 'PURE_BATCH': '0'}),
+ ('all', {'PURE_JIT': 'all'}), ('default', {})):
+ out = subprocess.run([os.path.join(pure, 'build', 'pure-run'), module], input=given, capture_output=True,
+ env=dict(os.environ, **env), check=True).stdout.decode().splitlines()
+ paths[name] = sum(json.loads(o)['states']['digest'] == hashlib.sha256(m).hexdigest() and json.loads(o)['fault'] == 'none'
+ for m, o in zip(messages, out)) if len(out) == len(messages) else 0
+aup_code, aup_braces = lines(os.path.join(aup, 'examples', 'sha256.aup'))
+python_code, _ = lines(os.path.join(here, 'sha256.py'), stop='if __name__')
+ok = all(n == len(messages) for n in paths.values())
+print(json.dumps({'messages': len(messages), 'right': paths, 'aup_lines': aup_code, 'aup_brace_lines': aup_braces,
+ 'python_lines': python_code}))
+sys.exit(0 if ok else 1)