#!/usr/bin/env python3 """ Generate ProofBundle conformance test vectors from a known-good bundle. Usage: python3 make_proofbundle_testvectors.py \\ /root/work/vaultmesh/proofbundle-sample.json \\ /root/work/vaultmesh/testvectors/proofbundle This script takes a valid ProofBundle and creates: - proofbundle-valid.json (copy of original with normalized bundle_id) - proofbundle-tampered-body.json (timestamp modified without updating root_hash) - proofbundle-tampered-root.json (wrong root_hash in a receipt) - proofbundle-broken-chain.json (previous_hash mismatch) """ import copy import json import sys from pathlib import Path def load_bundle(path: Path) -> dict: with path.open("r", encoding="utf-8") as f: return json.load(f) def save_bundle(bundle: dict, path: Path) -> None: path.write_text( json.dumps(bundle, indent=2, sort_keys=True, ensure_ascii=False), encoding="utf-8", ) print(f"[+] wrote {path}") def make_valid(bundle: dict) -> dict: """Create a normalized copy as the valid reference.""" out = copy.deepcopy(bundle) out["bundle_id"] = "pb-test-valid" return out def make_tampered_body(bundle: dict) -> dict: """Tamper a receipt's timestamp without updating root_hash.""" out = copy.deepcopy(bundle) out["bundle_id"] = "pb-test-tampered-body" receipts = out.get("chain", {}).get("receipts", []) if len(receipts) >= 2: # Modify the second receipt's timestamp (the root_hash will be wrong) receipts[1]["timestamp"] = "2099-01-01T00:00:00.000Z" return out def make_tampered_root(bundle: dict) -> dict: """Replace a receipt's root_hash with a clearly wrong value.""" out = copy.deepcopy(bundle) out["bundle_id"] = "pb-test-tampered-root" receipts = out.get("chain", {}).get("receipts", []) if receipts: # Tamper the last receipt's root_hash receipts[-1]["root_hash"] = "blake3:deadbeefdeadbeefdeadbeefdeadbeef" return out def make_broken_chain(bundle: dict) -> dict: """Break the chain linkage via previous_hash mismatch.""" out = copy.deepcopy(bundle) out["bundle_id"] = "pb-test-broken-chain" receipts = out.get("chain", {}).get("receipts", []) if len(receipts) >= 2: # Break linkage at receipt[1] receipts[1]["previous_hash"] = "blake3:badcafebadcafebadcafebadcafebad0" return out def main(): if len(sys.argv) != 3: print( "Usage: make_proofbundle_testvectors.py INPUT_BUNDLE OUTPUT_DIR", file=sys.stderr, ) sys.exit(1) src = Path(sys.argv[1]) dest_dir = Path(sys.argv[2]) dest_dir.mkdir(parents=True, exist_ok=True) base = load_bundle(src) save_bundle(make_valid(base), dest_dir / "proofbundle-valid.json") save_bundle(make_tampered_body(base), dest_dir / "proofbundle-tampered-body.json") save_bundle(make_tampered_root(base), dest_dir / "proofbundle-tampered-root.json") save_bundle(make_broken_chain(base), dest_dir / "proofbundle-broken-chain.json") print(f"\n[OK] Generated 4 test vectors in {dest_dir}") if __name__ == "__main__": main()