#!/usr/bin/env python3 """CAIN-42 E25 clean-room verifier. Imports NOTHING from CAIN. With its own canonical serializer and Ed25519 checks it re-derives every signature, digest, delegation-attenuation step, receipt link and event-chain link in the bundle, and re-checks the measured records for internal consistency. It proves the bundle is intact and self-consistent; it does not run the fabric. python3 verify_e25.py [bundle-dir] """ 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 D_ENVELOPE = "CAIN42/E25-AGENCY-ENVELOPE/v1" D_DELEGATION = "CAIN42/E25-DELEGATION/v1" D_BINDING = "CAIN42/E25-MODEL-RUNTIME-BINDING/v1" D_DECISION = "CAIN42/E25-GOVERNANCE-DECISION/v1" D_RECEIPT = "CAIN42/E25-EXECUTION-RECEIPT/v1" D_CREDENTIAL = "CAIN42/E25-CREDENTIAL/v1" D_EVENT = "CAIN42/E25-GOVERNANCE-EVENT/v1" D_POLICY = "CAIN42/E25-POLICY-IR/v1" def canonical(o) -> bytes: return json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode() def h(o) -> str: return hashlib.sha256(canonical(o)).hexdigest() def digest(domain: str, body) -> str: return h({"domain": domain, "body": body}) def verify(pub: str, sig: str, domain: str, body) -> bool: try: ed25519.Ed25519PublicKey.from_public_bytes(base64.b64decode(pub)).verify( base64.b64decode(sig), digest(domain, body).encode()) return True except (InvalidSignature, ValueError, TypeError): return False def _within(resource: str, prefixes) -> bool: for p in prefixes: if p == "*" or resource == p or (p.endswith("/") and resource.startswith(p)) or resource.startswith(p + "/"): return True return False def _scope_subset(child, parent) -> bool: parent = list(parent) return all(c != "*" or "*" in parent for c in child) and all(_within(c.rstrip("/"), parent) or c in parent for c in child) class Checker: def __init__(self) -> None: self.checks = 0 self.passed = 0 self.problems: list = [] def check(self, name: str, ok: bool, detail: str = "") -> None: self.checks += 1 if ok: self.passed += 1 else: self.problems.append(f"{name}: {detail}"[:300]) def main() -> int: d = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(".") c = Checker() must = ["CAIN42_E25_EVIDENCE_BUNDLE.json", "AGENCY_RUN_MANIFEST.json", "INVARIANTS.json", "SECURITY_RESULTS.json", "CHAOS_RESULTS.json", "PERFORMANCE_RESULTS.json", "CONFORMANCE_RESULTS.json", "SCALE_RESULTS.json", "MUTATION_RESULTS.json", "SHA256SUMS", "SIGNATURE.json", "MANIFEST.json", "SCHEMAS.json", "KNOWN_LIMITATIONS.json", "UNKNOWN_BOUNDARIES.json", "TEST_RESULTS.json"] for n in must: c.check(f"file_present:{n}", (d / n).exists(), "missing") def load(n): try: return json.loads((d / n).read_text()) except Exception as e: # noqa: BLE001 return {"_error": str(e)} # --- hashes sums = {} for line in (d / "SHA256SUMS").read_text().splitlines() if (d / "SHA256SUMS").exists() else []: parts = line.split(" ", 1) if len(parts) == 2: sums[parts[1]] = parts[0] for n, dig in sums.items(): c.check(f"sha256sums:{n}", (d / n).exists() and hashlib.sha256((d / n).read_bytes()).hexdigest() == dig, "hash mismatch") manifest = load("MANIFEST.json") for n, dig in (manifest.get("files") or {}).items(): c.check(f"manifest:{n}", (d / n).exists() and hashlib.sha256((d / n).read_bytes()).hexdigest() == dig, "manifest hash mismatch") # --- master signature sig = load("SIGNATURE.json") c.check("master:hashes_digest", sig.get("master", {}).get("hashes_digest") == h(sums), "hashes_digest mismatch") c.check("master:signature", verify(sig.get("signer_public_key_b64", ""), sig.get("signature_b64", ""), "CAIN42/E25-MASTER/v1", sig.get("master", {})), "master signature invalid") c.check("master:files_match_sums", sig.get("files") == sums, "files map differs from SHA256SUMS") # --- published run run = load("AGENCY_RUN_MANIFEST.json") instances = run.get("instances", {}) fab_pub = run.get("fabric_pub", "") broker_pub = run.get("broker_pub", "") delegations = {dd["body"]["delegation_id"]: dd for dd in run.get("delegations", [])} env_ids = set() for inst_id, inst in instances.items(): c.check(f"instance:{inst_id}:binding_digest", inst.get("binding_digest") == digest(D_BINDING, inst.get("binding", {})), "binding digest mismatch") c.check(f"instance:{inst_id}:pub", isinstance(inst.get("pub"), str) and len(inst.get("pub", "")) > 20, "bad pub") c.check(f"instance:{inst_id}:trust_domain", bool(inst.get("trust_domain")), "no trust domain") for en, entry in enumerate(run.get("envelopes", [])): env = entry["envelope"].get("envelope", {}) env_ids.add(env.get("envelope_id")) c.check(f"envelope:{en}:id", env.get("envelope_id") == "env_" + digest(D_ENVELOPE, {k: v for k, v in env.items() if k != "envelope_id"})[:32], "envelope id mismatch") pub = instances.get(entry["instance"], {}).get("pub", "") c.check(f"envelope:{en}:signature", verify(pub, entry["envelope"].get("signature_b64", ""), D_ENVELOPE, env), "envelope signature invalid") c.check(f"envelope:{en}:canonical", isinstance(canonical(env), bytes), "not canonical") c.check(f"envelope:{en}:single_capability", len(env.get("requested_capabilities", [])) == 1, "capability count") for i, dec in enumerate(run.get("decisions", [])): body = dec["decision_body"] c.check(f"decision:{i}:digest", dec["decision_digest"] == digest(D_DECISION, body), "decision digest mismatch") c.check(f"decision:{i}:signature", verify(fab_pub, dec["signature_b64"], D_DECISION, body), "decision signature invalid") c.check(f"decision:{i}:envelope_known", dec["envelope_id"] in env_ids, "unknown envelope") c.check(f"decision:{i}:allow_has_authorization", (dec["decision"] != "ALLOW") or bool(dec["authorization_id"]), "ALLOW without authorization id") c.check(f"decision:{i}:allow_has_no_reasons", (dec["decision"] != "ALLOW") or dec["reasons"] == [], "ALLOW carries reasons") prev = "0" * 64 for i, rec in enumerate(run.get("receipts", [])): b = rec["body"] c.check(f"receipt:{i}:seq", b.get("seq") == i, "seq mismatch") c.check(f"receipt:{i}:prev", b.get("prev") == prev, "link broken") c.check(f"receipt:{i}:hash", rec["receipt_hash"] == digest(D_RECEIPT, b), "hash mismatch") c.check(f"receipt:{i}:signature", verify(fab_pub, rec["signature_b64"], D_RECEIPT, b), "signature invalid") c.check(f"receipt:{i}:recorded", rec.get("body", {}).get("status") in ("EXECUTED", "INCIDENT", "REFUSED"), "unknown status") prev = rec["receipt_hash"] for did, dd in delegations.items(): b = dd["body"] c.check(f"delegation:{did}:signature", verify(dd["delegator_pub"], dd["signature_b64"], D_DELEGATION, b), "delegation signature invalid") c.check(f"delegation:{did}:from_principal_in_root", bool(b.get("capabilities")) and bool(b.get("resources")), "empty scope") parent = delegations.get(b.get("parent", "")) if b.get("parent") else None if parent: pb = parent["body"] c.check(f"delegation:{did}:cap_subset", set(b["capabilities"]) <= set(pb["capabilities"]), "child capabilities exceed parent") c.check(f"delegation:{did}:resource_subset", _scope_subset(b["resources"], pb["resources"]), "child resources exceed parent") c.check(f"delegation:{did}:time_subset", b["expires_ms"] <= pb["expires_ms"], "child outlives parent") c.check(f"delegation:{did}:depth", b["depth"] == pb["depth"] + 1 and b["depth"] <= pb["max_depth"], "depth rule") for i, cred in enumerate(run.get("credentials", [])): c.check(f"credential:{i}:signature", verify(broker_pub, cred["signature_b64"], D_CREDENTIAL, cred["body"]), "credential signature invalid") try: hdr, claims, sl = cred["jwt"].split(".") ed25519.Ed25519PublicKey.from_public_bytes(base64.b64decode(broker_pub)).verify( base64.urlsafe_b64decode(sl + "=" * (-len(sl) % 4)), (hdr + "." + claims).encode()) c.check(f"credential:{i}:jwt", True) except Exception as e: # noqa: BLE001 c.check(f"credential:{i}:jwt", False, str(e)) c.check(f"credential:{i}:cnf", cred["body"].get("cnf_pub") == cred.get("cnf_pub"), "cnf mismatch") prev = "0" * 64 for i, ev in enumerate(run.get("events", [])): body = {k: ev[k] for k in ("seq", "kind", "data", "prev")} c.check(f"event:{i}:hash", ev["hash"] == digest(D_EVENT, body), "event hash mismatch") c.check(f"event:{i}:link", ev["prev"] == prev, "event link broken") prev = ev["hash"] # --- measured records inv = load("INVARIANTS.json") c.check("invariants:all_hold", inv.get("all_hold") is True, "not all hold") c.check("invariants:count", inv.get("checked", 0) >= 500, "fewer than 500") c.check("invariants:holding", inv.get("holding") == inv.get("checked"), "holding != checked") c.check("invariants:rows", len(inv.get("rows", [])) == inv.get("checked"), "row count mismatch") for i, r in enumerate(inv.get("rows", [])): c.check(f"invariant:{i}:ok", r["ok"] is True, f"{r.get('id')} failed") bench = load("SECURITY_RESULTS.json") c.check("attacks:total", bench.get("total", 0) >= 1000, "fewer than 1000") c.check("attacks:all_contained", bench.get("all_contained") is True, "not all contained") c.check("attacks:contained_count", bench.get("contained") == bench.get("total"), "contained != total") for name, a in (bench.get("attacks") or {}).items(): c.check(f"attack:{name}:contained", a["contained"] is True, "not contained") c.check(f"attack:{name}:digest", a["digest"] == h({"attack": name, "contained": a["contained"], "evidence": a["evidence"]}), "digest mismatch") ch = load("CHAOS_RESULTS.json") c.check("chaos:all_handled", ch.get("all_handled") is True, "not all handled") for i, inj in enumerate(ch.get("injections", [])): c.check(f"chaos:{i}:handled", inj["handled"] is True, f"{inj.get('fault')} unhandled") perf = load("PERFORMANCE_RESULTS.json").get("benchmark", {}).get("operations", {}) for op, v in perf.items(): c.check(f"perf:{op}:ordered", 0 <= v.get("p50_ms", -1) <= v.get("p95_ms", -1) <= v.get("p99_ms", -1), "percentiles not ordered") conf = load("CONFORMANCE_RESULTS.json") for name, lvl in (conf.get("adapters") or {}).items(): c.check(f"conformance:{name}", lvl == 5, f"level {lvl}") sim = load("SCALE_RESULTS.json") c.check("scale:authority_leakage", sim.get("results", {}).get("authority_leakage") == 0, "leakage") c.check("scale:agents", sim.get("population", {}).get("agents", 0) >= 100000, "too few agents") c.check("scale:kind", sim.get("result_kind") == "CONTROLLED_SINGLE_PROCESS_MODEL", "unlabelled model") mut = load("MUTATION_RESULTS.json") c.check("mutation:all_caught", mut.get("all_mutants_caught") is True, "mutant not caught") c.check("mutation:controls", mut.get("controls_ok") is True, "control mutated") bundle = load("CAIN42_E25_EVIDENCE_BUNDLE.json") c.check("bundle:schema", bundle.get("schema") == "cain42.e25.evidence-bundle.v1", "schema") c.check("bundle:invariants_match", bundle.get("invariants", {}).get("checked") == inv.get("checked"), "invariant count differs") c.check("bundle:attacks_match", bundle.get("attacks", {}).get("total") == bench.get("total"), "attack count differs") c.check("bundle:limitations", bool(load("KNOWN_LIMITATIONS.json").get("limitations")), "no limitations") c.check("bundle:unknowns", bool(load("UNKNOWN_BOUNDARIES.json").get("unknowns")), "no unknowns") c.check("standards:no_compliance_claim", all(v not in ("COMPLIANT", "CERTIFIED") for v in (load("STANDARDS.json").get("standards") or {}).values()), "a standard claims compliance") result = "INTACT" if not c.problems and c.checks >= 300 else "BROKEN" print(json.dumps({"schema": "cain42.e25.verify.v1", "verifier": "verify_e25.py", "imports_cain": False, "result": result, "checks": c.checks, "passed": c.passed, "problems": c.problems[:50]}, indent=1, sort_keys=True)) return 0 if result == "INTACT" else 1 if __name__ == "__main__": sys.exit(main())