#!/usr/bin/env python3 """Compile isolated test-root verifier using exact production crypto source. Only newly generated disposable key bytes are used. No release seed, signing ceremony, runtime production override, publication or candidate qualification. Run as a durable CPU2/8G/no-swap job; heavy lock is acquired inside the job. """ import argparse import fcntl import hashlib import json import os from pathlib import Path import secrets import shutil import subprocess import tomllib def sha(path): with path.open('rb') as f: return hashlib.file_digest(f,'sha256').hexdigest() p=argparse.ArgumentParser(description=__doc__) p.add_argument('--source',type=Path,required=True) p.add_argument('--output',type=Path,required=True) a=p.parse_args() with open('/tmp/opencode/release-heavy.lock','a') as lock: fcntl.flock(lock,fcntl.LOCK_EX) assert shutil.disk_usage(a.output.parent).free>24*1024**3 a.output.mkdir(mode=0o700,exist_ok=False) crate=a.output/'crate' trust=crate/'src/trust' trust.mkdir(parents=True) sources={} for name in ('signed_doc.rs','canonical.rs','did.rs'): path=a.source/'core/archipelago/src/trust'/name raw=path.read_bytes() (trust/name).write_bytes(raw) sources[str(path.relative_to(a.source))]=hashlib.sha256(raw).hexdigest() main=a.source/'scripts/tests/os_ota_crypto_fixture.rs' shutil.copyfile(main,crate/'src/main.rs') seed=secrets.token_bytes(32) key=a.output/'fixture.seed' fd=os.open(key,os.O_CREAT|os.O_EXCL|os.O_WRONLY,0o600) with os.fdopen(fd,'wb') as f: f.write(seed) # PKCS#8 wrapper of our freshly generated raw Ed25519 seed. OpenSSL only # derives its public key; it never reads an operator key or environment seed. public=subprocess.check_output(['openssl','pkey','-inform','DER','-pubout','-outform','DER'], input=bytes.fromhex('302e020100300506032b657004220420')+seed) assert public[:12]==bytes.fromhex('302a300506032b6570032100') and len(public)==44 pin=public[12:].hex() (trust/'anchor.rs').write_text('''// GENERATED DISPOSABLE TEST ANCHOR; NO RUNTIME OVERRIDE. pub fn release_root_pubkey() -> Option { let raw: [u8;32] = hex::decode("'''+pin+'''").unwrap().try_into().unwrap(); Some(ed25519_dalek::VerifyingKey::from_bytes(&raw).unwrap()) } ''') packages=tomllib.loads((a.source/'core/Cargo.lock').read_text())['package'] dependencies={} for name in ('anyhow','ed25519-dalek','serde_json','hex','bs58'): versions=[x['version'] for x in packages if x['name']==name and (name!='ed25519-dalek' or x['version'].startswith('2.'))] assert len(versions)==1,(name,versions) dependencies[name]='='+versions[0] (crate/'Cargo.toml').write_text('[package]\nname="archipelago-os-ota-crypto-fixture"\nversion="0.0.0"\nedition="2021"\n[workspace]\n[dependencies]\n'+ '\n'.join(name+'='+json.dumps(version) for name,version in dependencies.items())+'\n') env=dict(os.environ,CARGO_BUILD_JOBS='1',CARGO_INCREMENTAL='0',CARGO_TARGET_DIR=str(a.output/'target')) command=['/home/archipelago/.cargo/bin/cargo','build','--offline','--release','--manifest-path',str(crate/'Cargo.toml')] with (a.output/'build.log').open('x') as log: result=subprocess.run(command,env=env,stdout=log,stderr=subprocess.STDOUT) (a.output/'compile-result.json').write_text(json.dumps(dict(exit=result.returncode,command=command))+'\n') result.check_returncode() binary=a.output/'fixture-native' shutil.copyfile(a.output/'target/release/archipelago-os-ota-crypto-fixture',binary) proof=dict(schema=1,scope='ISOLATED_COMPILETIME_TEST_ROOT_NOT_CANDIDATE', production_approved=False,production_sources_unchanged=sources, production_anchor_sha256=sha(a.source/'core/archipelago/src/trust/anchor.rs'), fixture_anchor_sha256=sha(trust/'anchor.rs'),fixture_main_sha256=sha(crate/'src/main.rs'), fixture_public_key=pin,binary_sha256=sha(binary),cargo_lock_sha256=sha(crate/'Cargo.lock'), trust_difference='compile-time generated test anchor; production canonical/DID/verify_strict code unchanged; no environment override', dependencies=dependencies) (a.output/'fixture-proof.json').write_text(json.dumps(proof,indent=2)+'\n') assert all(sha(a.source/name)==expected for name,expected in sources.items()) print(json.dumps(proof,indent=2),flush=True)