Chapter 10 · Code Snippet 10.1
The Digital Notary
C2PA reality-handshake validator
A reference implementation of the 'reality handshake' described in Chapter 10. Loads the Content Authenticity Initiative trust anchors, then verifies a file's C2PA manifest for identity and tamper status, returning VERIFIED, WARNING, TAMPERED, or UNVERIFIED.
c2pa_validator.py86 lines · Python
# File: c2pa_validator.py# Dependency: c2pa-python (official Coalition for Content Provenance# and Authenticity bindings, contentauth/c2pa-python on GitHub)# Install: pip install c2pa-python import hashlibimport jsonimport urllib.requestimport c2pa # Public trust list maintained by the Content Authenticity Initiative.# Anchors include Adobe, Microsoft, the BBC, Leica, Sony, Nikon, etc.TRUST_ANCHORS_URL = "https://contentcredentials.org/trust/anchors.pem" class RealityValidator: """ The Digital Notary: a logic gate for verifying Content Credentials. Simulates the 'reality handshake' performed by a browser, social platform, or newsroom verification pipeline. """ def __init__(self): # Load the 'Iron Alliance' trust anchors and bind them to a # c2pa.Settings object that the Reader will consult during validation. with urllib.request.urlopen(TRUST_ANCHORS_URL) as response: anchors_pem = response.read().decode("utf-8") self.settings = c2pa.Settings.from_dict({ "verify": {"verify_cert_anchors": True}, "trust": {"trust_anchors": anchors_pem}, }) def validate_asset(self, file_path: str) -> dict: """ Input: Path to an image or video file. Output: Verification status (VERIFIED, WARNING, TAMPERED, UNVERIFIED). """ # Step 1: Extract the 'Digital Nutrition Label' (Manifest). try: with c2pa.Context(self.settings) as context: with c2pa.Reader(file_path, context=context) as reader: manifest_json = json.loads(reader.detailed_json()) except Exception: return {"status": "UNVERIFIED", "reason": "No credentials found (Gray Zone)"} active_label = manifest_json.get("active_manifest") manifests = manifest_json.get("manifests", {}) manifest = manifests.get(active_label, {}) # Step 2: Verify the identity (who signed this?). # The Reader has already checked the signing certificate against the # trust anchors loaded above. A trust failure surfaces here as a # 'validation_status' entry with a code starting with 'signingCredential'. for status in manifest.get("validation_status", []): if status.get("code", "").startswith("signingCredential"): return {"status": "WARNING", "reason": "Identity unknown or self-signed"} # Step 3: Verify the integrity (has it been tampered with?). # The c2pa library validates hard-binding hashes during Reader # construction. Any mismatch is reported as 'assertion.dataHash.mismatch'. for status in manifest.get("validation_status", []): if status.get("code") == "assertion.dataHash.mismatch": return {"status": "TAMPERED", "reason": "Hash mismatch (deepfake injection)"} # Step 4: The handshake is complete. return { "status": "VERIFIED", "issuer": manifest.get("signature_info", {}).get("issuer"), "claim_generator": manifest.get("claim_generator"), "ingredients": manifest.get("ingredients", []), # the chain of edits } @staticmethod def _calculate_sha256(file_path: str) -> str: """Standard cryptographic hash of the binary file (illustrative; the c2pa Reader performs hard-binding validation internally).""" sha = hashlib.sha256() with open(file_path, "rb") as f: for block in iter(lambda: f.read(4096), b""): sha.update(block) return sha.hexdigest()