#!/usr/bin/env python3 """Clean-room verifier for the CAIN-42 Evolution 13 decision-integrity proof bundle. IMPORTS NO CAIN-42 CODE. Standard library plus `cryptography` (Ed25519). It checks every file against MANIFEST.json, the D1-D24 invariant matrix, the 36-scenario bench (all contained), both signatures, the master module digests, the published schemas, the decision trace, and that no key material is present. It proves the bundle is intact and self-consistent. It does NOT prove the decision governance is sound or that a model's reasoning is correct. Usage: python3 verify_e13.py """ from __future__ import annotations import base64 import hashlib import json import sys from pathlib import Path from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives.asymmetric import ed25519 REQUIRED_SCHEMAS = ("GovernedDecision", "DecisionBasis", "CandidateAction", "CompiledPolicy", "DecisionTrace", "DecisionTransition") FORBIDDEN = ("private_key", "private key", "-----begin", "secret_key", "password") def canon(o) -> bytes: return json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode() def digest(domain: str, fields: dict) -> str: return hashlib.sha256(canon({"domain": domain, **fields})).hexdigest() def verify(pub_b64: str, sig_b64: str, domain: str, fields: dict) -> bool: try: ed25519.Ed25519PublicKey.from_public_bytes(base64.b64decode(pub_b64)).verify( base64.b64decode(sig_b64), digest(domain, fields).encode()) return True except (InvalidSignature, ValueError, TypeError): return False def main() -> int: if len(sys.argv) < 2: print("usage: python3 verify_e13.py ") return 2 d = Path(sys.argv[1]) problems: list = [] checks = 0 manifest = json.loads((d / "MANIFEST.json").read_text()) for name, want in manifest["files"].items(): checks += 1 if hashlib.sha256((d / name).read_bytes()).hexdigest() != want: problems.append(f"file {name}: sha256 mismatch") proof = json.loads((d / "CAIN42_EVOLUTION13_PROOF.json").read_text()) master = json.loads((d / "CAIN42_EVOLUTION13_MASTER_PROOF.json").read_text()) inv = proof.get("invariants") or {} ids = {x.get("id") for x in inv.get("checks", [])} checks += 1 if ids != {f"D{i}" for i in range(1, 25)}: problems.append(f"invariant ids {sorted(ids)} != D1..D24") for x in inv.get("checks", []): if not x.get("holds"): problems.append(f"invariant {x.get('id')} does not hold") checks += 1 if inv.get("all_hold") is not True or inv.get("failed"): problems.append("invariant matrix all_hold is not true") bench = proof.get("attack_bench") or {} checks += 1 if not (bench.get("all_contained") is True and bench.get("contained") == bench.get("total") and bench.get("total", 0) >= 36): problems.append("decision bench is not fully contained with at least 36 scenarios") body = {k: v for k, v in proof.items() if k not in ("signature_b64", "signer_public_key_b64")} checks += 1 if not verify(proof.get("signer_public_key_b64", ""), proof.get("signature_b64", ""), "CAIN42/E13-PROOF/v1", body): problems.append("proof signature does not verify") mbody = {k: v for k, v in master.items() if k not in ("signature_b64", "signer_public_key_b64")} checks += 1 if not verify(master.get("signer_public_key_b64", ""), master.get("signature_b64", ""), "CAIN42/E13-MASTER/v1", mbody): problems.append("master signature does not verify") checks += 1 if master.get("modules") != {k: v["sha256"] for k, v in (proof.get("modules") or {}).items()}: problems.append("master module digests do not match the proof") checks += 1 if set(proof.get("schemas") or {}) != set(REQUIRED_SCHEMAS): problems.append("published schemas are incomplete") checks += 1 trace = json.loads((d / "DECISION_TRACES.json").read_text()).get("trace") or {} if not trace.get("decision_digest") or not trace.get("transitions") is not None: problems.append("decision trace is incomplete") if "chain_of_thought" in json.dumps(trace).lower() or "chain-of-thought" in json.dumps(trace).lower(): problems.append("decision trace contains chain-of-thought") checks += 1 if any(f in (d / "DECISION_EXAMPLES.json").read_text().lower() for f in FORBIDDEN): problems.append("examples contain key material") print(json.dumps({"bundle": str(d), "checks": checks, "problems": problems, "result": "INTACT" if not problems else "FAILED"}, indent=2)) return 0 if not problems else 1 if __name__ == "__main__": raise SystemExit(main())