74 lines
3.2 KiB
Python
74 lines
3.2 KiB
Python
from pathlib import Path
|
|
import copy
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import zipfile
|
|
|
|
root = Path(__file__).resolve().parent.parent
|
|
original = root / 'harness/experiments/peer-union-windows-20260923'
|
|
scratch = root / '.local/peer-union-verifier-controls-20260923'
|
|
scratch.mkdir(exist_ok=True)
|
|
spec = importlib.util.spec_from_file_location('peer_verify', original / 'verify.py')
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
manifest = json.loads((original / 'manifest.json').read_bytes())
|
|
with zipfile.ZipFile(original / 'evidence.zip') as z:
|
|
data = {name: z.read(name) for name in z.namelist()}
|
|
|
|
|
|
def sha(raw):
|
|
return hashlib.sha256(raw).hexdigest()
|
|
|
|
|
|
def refresh(payloads, claim, name, raw):
|
|
payloads[name] = raw
|
|
claim['payloads'][name] = {'bytes': len(raw), 'sha256': sha(raw)}
|
|
|
|
|
|
reports = []
|
|
for case in ('payload-corruption', 'outcome-count', 'missing-selected-outcome', 'git-input-binding'):
|
|
payloads, claim = dict(data), copy.deepcopy(manifest)
|
|
folder = scratch / case
|
|
folder.mkdir(exist_ok=True)
|
|
if case == 'payload-corruption':
|
|
payloads['gates/combined-strict-3.log'] += b'corruption'
|
|
elif case == 'outcome-count':
|
|
next(g for g in claim['gates'] if g['name'] == 'combined-core-scenario-1')['outcomes'] = [26, 0, 0]
|
|
elif case == 'missing-selected-outcome':
|
|
name = 'gates/combined-core-scenario-1.log'
|
|
lines = payloads[name].splitlines(keepends=True)
|
|
removed = next(i for i, line in enumerate(lines) if line.startswith(b'test ') and b' ... ok' in line)
|
|
del lines[removed]
|
|
changed = b''.join(lines)
|
|
refresh(payloads, claim, name, changed)
|
|
receipt_name = 'gates/combined-core-scenario-1.result.json'
|
|
receipt = json.loads(payloads[receipt_name])
|
|
receipt['log_sha256'] = sha(changed)
|
|
refresh(payloads, claim, receipt_name, json.dumps(receipt).encode())
|
|
else:
|
|
input_name = 'gates/combined-strict-3.inputs.json'
|
|
inputs = json.loads(payloads[input_name])
|
|
inputs['inputs'][0]['sha256'] = '0' * 64
|
|
changed = json.dumps(inputs).encode()
|
|
refresh(payloads, claim, input_name, changed)
|
|
receipt_name = 'gates/combined-strict-3.result.json'
|
|
receipt = json.loads(payloads[receipt_name])
|
|
receipt['inputs_sha256'] = sha(changed)
|
|
refresh(payloads, claim, receipt_name, json.dumps(receipt).encode())
|
|
with zipfile.ZipFile(folder / 'evidence.zip', 'w', compression=zipfile.ZIP_DEFLATED) as z:
|
|
for name, raw in payloads.items():
|
|
z.writestr(name, raw)
|
|
archive = (folder / 'evidence.zip').read_bytes()
|
|
claim['archive_bytes'], claim['archive_sha256'] = len(archive), sha(archive)
|
|
(folder / 'manifest.json').write_text(json.dumps(claim), encoding='utf-8')
|
|
try:
|
|
module.verify(folder, root)
|
|
except AssertionError:
|
|
reports.append({'case': case, 'result': 'REJECTED_AS_EXPECTED'})
|
|
else:
|
|
raise AssertionError('Corrupted evidence accepted: ' + case)
|
|
report = {'source_archive_sha256': manifest['archive_sha256'], 'verifier_sha256': sha((original / 'verify.py').read_bytes()), 'controls': reports}
|
|
(scratch / 'result.json').write_text(json.dumps(report, indent=2), encoding='utf-8')
|
|
print(json.dumps(report, indent=2))
|