1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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)
|