#!/usr/bin/env python3 """Independent verifier for the CAIN-42 frontier evidence bundle. stdlib + `cryptography` only; imports NOTHING from CAIN; own RFC 6962 implementation. python3 verify_frontier_bundle.py # fetch from all three public sites and cross-check them python3 verify_frontier_bundle.py --dir ./frontier # verify a local copy python3 verify_frontier_bundle.py --pin-key BASE64 # pin the transparency signer key YOURSELF (recommended; otherwise the key comes from the bundle) What it checks (each result is reported separately; nothing is summarised as 'secure'): 1. every site serves byte-identical manifest.json, and every file's sha256 matches the manifest, on every site 2. the published source files hash to the values in the source manifest (so what you read is what was measured) 3. the transparency checkpoint's Ed25519 signature, and the RFC 6962 inclusion proof of the decision-log head in the checkpoint's root 4. AgentBench results are recomputed from the per-scenario rows (counts and rates must match the summary) 5. the release-gate decision is recomputed from its own evidence fields (unmeasured evidence must block; the decision must match) What it does NOT check: that the tests/benchmarks are the right ones, that the code is free of bugs, or that any of this was reviewed by an independent party. Exit 0 = every check passed; 1 = at least one failed. 'limitations' in the output are always printed.""" import argparse, base64, hashlib, json, sys, urllib.request from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey SITES = ["cainstudio.online", "mcpgate.online", "clawx.click"]; PATH = "/evidence/frontier/" def sha(b): return hashlib.sha256(b).hexdigest() def enc(o): if isinstance(o, float) and o == int(o): o = int(o) if isinstance(o, dict): return "{" + ",".join(json.dumps(k, ensure_ascii=False) + ":" + enc(o[k]) for k in sorted(o, key=lambda s: [ord(c) for c in s])) + "}" if isinstance(o, list): return "[" + ",".join(enc(x) for x in o) + "]" return json.dumps(o, ensure_ascii=False) def vsig(pub, obj, sig): try: Ed25519PublicKey.from_public_bytes(base64.b64decode(pub)).verify(base64.b64decode(sig), enc(obj).encode()); return True except Exception: return False def H0(d): return hashlib.sha256(b"\x00" + d).digest() def H1(l, r): return hashlib.sha256(b"\x01" + l + r).digest() def incl(leaf, m, n, path, root): if not 0 <= m < n: return False fn, sn, r = m, n - 1, H0(leaf) for p in path: if sn == 0: return False if fn & 1 or fn == sn: r = H1(p, r) if not fn & 1: while not fn & 1 and fn != 0: fn >>= 1; sn >>= 1 else: r = H1(r, p) fn >>= 1; sn >>= 1 return sn == 0 and r == root def fetch(base, name): try: with urllib.request.urlopen(urllib.request.Request(base + name, headers={"User-Agent": "cain-frontier-verify/1"}), timeout=20) as r: return r.read() except Exception: return None def gate_decision(ev): """Same rule the gate uses, re-implemented: any unmeasured (None) or false requirement blocks.""" checks = {"critical tests ran and none failed": ev.get("critical_tests_run") not in (None, 0) and ev.get("critical_tests_failed") == 0, "security properties verified": ev.get("security_properties_verified") is True, "artifacts signed": ev.get("artifacts_signed") is True, "independent verification succeeded": ev.get("independent_verification") is True, "rollback succeeded": ev.get("rollback_tested") is True, "recovery succeeded": ev.get("recovery_tested") is True, "three-site state reconciles": ev.get("three_site_reconciled") is True, "public claims map to evidence": ev.get("public_claims_mapped") is True, "known limitations disclosed": ev.get("known_limitations_disclosed") is True} if ev.get("tree_clean") is False: checks["working tree clean"] = False bl = [k for k, v in checks.items() if not v]; return ("GO" if not bl else "NO_GO"), bl def main(): ap = argparse.ArgumentParser(); ap.add_argument("--dir"); ap.add_argument("--sites", default=",".join(SITES)); ap.add_argument("--pin-key"); a = ap.parse_args() out = {"checks": {}, "limitations": ["self-generated evidence: produced and served by the operator's own host; no third-party review", "all three sites run on one host, so identical bytes across sites is a consistency check, not independence", "the transparency signer key comes from the bundle unless you pass --pin-key"]} C = out["checks"]; getters = {} if a.dir: import os getters["local"] = lambda n: (open(os.path.join(a.dir, n), "rb").read() if os.path.exists(os.path.join(a.dir, n)) else None) else: for s in a.sites.split(","): getters[s] = (lambda s: lambda n: fetch("https://" + s + PATH, n))(s) mans = {s: g("manifest.json") for s, g in getters.items()} C["manifest_reachable_on_all_sites"] = all(v is not None for v in mans.values()) if not C["manifest_reachable_on_all_sites"]: out["overall"] = "FAILED"; print(json.dumps(out, indent=1)); return 1 hashes = {s: sha(v) for s, v in mans.items()}; C["manifest_identical_across_sites"] = len(set(hashes.values())) == 1; out["manifest_sha256"] = hashes man = json.loads(next(iter(mans.values()))); files = man["files"]; bad = [] for s, g in getters.items(): for name, meta in files.items(): b = g(name) if b is None or sha(b) != meta["sha256"]: bad.append(f"{s}:{name}") C["every_file_hash_matches_on_every_site"] = not bad; out["hash_mismatches"] = bad[:20] g0 = next(iter(getters.values())) man = json.loads(g0("source/manifest.json") or b"{}") if "source/manifest.json" in files else {} leaked = [n for n in files if n.startswith("source/") and n != "source/manifest.json"] C["source_not_published_only_hash_commitments"] = man.get("source_published") is False and not leaked and bool(man.get("files")); out["source_commitments"] = len(man.get("files", {})) try: cp = json.loads(g0("checkpoint.json")); inc = json.loads(g0("inclusion-proof.json")); pins = json.loads(g0("PINNED_SIGNER_KEYS.json") or b"{}") pub = a.pin_key or pins.get("cain42/daily"); body = {k: cp[k] for k in ("origin", "size", "root", "epoch", "at")} C["checkpoint_signature_valid"] = bool(vsig(cp["public_key"], body, cp["signature"]) and cp["public_key"] == pub); out["signer_key_source"] = "--pin-key (yours)" if a.pin_key else "bundle PINNED_SIGNER_KEYS.json (not independent)" leaf = base64.b64decode(inc["leaf"]); C["inclusion_proof_valid"] = incl(leaf, inc["index"], inc["size"], [base64.b64decode(p) for p in inc["path"]], base64.b64decode(cp["root"])) and inc["size"] == cp["size"] out["anchored_entry"] = json.loads(leaf) except Exception as e: C["checkpoint_signature_valid"] = C["inclusion_proof_valid"] = False; out["transparency_error"] = type(e).__name__ try: ab = json.loads(g0("CAIN42_AGENTBENCH_RESULTS.json")); rows = ab["results"]; s = ab["summary"] C["agentbench_recomputes"] = (len(rows) == s["scenarios"] and sum(r["pass"] for r in rows) == s["passed"] and round(sum(r["security_correct"] for r in rows) / len(rows), 3) == s["security_correct_rate"] and round(sum(r["task_success"] for r in rows) / len(rows), 3) == s["task_success_rate"]) out["agentbench"] = {k: s[k] for k in ("scenarios", "passed", "security_correct_rate", "task_success_rate")} except Exception as e: C["agentbench_recomputes"] = False; out["agentbench_error"] = type(e).__name__ try: gt = json.loads(g0("CAIN42_FRONTIER_RELEASE_GATE.json")); dec, bl = gate_decision(gt["evidence"]); C["release_gate_recomputes"] = dec == gt["decision"] and sorted(bl) == sorted(gt["blockers"]) out["release_gate"] = {"decision": gt["decision"], "blockers": gt["blockers"]} except Exception as e: C["release_gate_recomputes"] = False; out["gate_error"] = type(e).__name__ out["overall"] = "ALL_CHECKS_PASSED_WITH_LIMITATIONS" if all(C.values()) else "FAILED"; print(json.dumps(out, indent=1)); return 0 if all(C.values()) else 1 if __name__ == "__main__": sys.exit(main())