← Back
Home › Systems › Security and identity

content-provenance

Binds signed, tamper-evident statements about who made a photo, video or file and how it was edited to the file itself, so any viewer can verify the history against a list of trusted signers.

C2PA

Open the content-provenance pagecontent-provenance Merkle treedata-structures: Hash tree for verifying and diffing large datasets with logarithmic proofsPerceptual hashingsearch-sort: Compact fingerprints (64 to 256 bits) of an image that stay close under resizing and recompression, compared by Hamming distance; pHash, dHash and Meta's PDQ.›Cbor cosesecurity: CBOR binary encoding and COSE signing/encryption structures (WebAuthn, C2PA, attestation)Certificate revocationsecurity: CRLs, OCSP, OCSP stapling, short-lived certificates and CRLite-style filters for revoked certificatesCryptographic hashes (SHA-2,BLAKE3)security: Collision-resistant fingerprints of data; SHA-256 for interoperability, BLAKE3 for speed, HMAC/HKDF for keyed uses.›ECDSA signaturessecurity: The elliptic-curve signature standardised in FIPS 186-5 (P-256) and used by secp256k1 ledgers; 64-byte signatures, but a repeated or biased nonce leaks the private key.›Hardware backed keystoresecurity: Non-exportable keys in Secure Enclave, StrongBox, TPM: generation, use policies, biometric gatingInvisible watermarkingsecurity: Embedding robust imperceptible marks in images/audio/video or token sampling for later detectionRemote attestationsecurity: Hardware-signed evidence (TPM quotes, SGX/TDX quotes, SEV-SNP reports, key attestation) proving device, key or enclave state to a verifierTrusted timestampingsecurity: RFC 3161 time-stamp tokens: a TSA signs a hash with time, proving data existed thenX509 certificatessecurity: Certificate chains, path validation, SANs, revocation and short-lived issuanceBloom filterdata-structures: Bit array answering "definitely not present" or "probably present" in about 10 bits per key for 1 % false positives; inserts are cheap, deletes impossible.›HTTP caching semanticsnetworking: The rules (RFC 9111) that decide whether a stored response is still fresh, and how a cheap conditional request revalidates it when it is not.›Convolutional networksml-training: Layers that slide a small shared kernel over a grid, giving translation equivariance and few parameters; still the most compute-efficient choice for many vision tasks.›Discrete cosine transformnumerics: Fast integer DCT/DST block transforms used by image and video codecsPRNGs (PCG, xoshiro)numerics: Small, fast, statistically strong non-cryptographic generators: PCG32 and xoshiro256**, with seeding, parallel streams and unbiased ranges.›Forward error correctionsignal-processing: Add redundancy (LDPC, Reed-Solomon, XOR parity) so receivers repair loss without retransmitCsprngsecurity: OS-backed cryptographically secure random numbers (getrandom), and when a fast PRNG is not enoughMeasured bootsecurity: Each boot stage hashes the next into TPM PCRs (extend) and logs events for later attestationTrusted execution environmentssecurity: Enclaves/confidential VMs with remote attestation for computing on sealed dataSecure boot chainsecurity: Each boot stage verifies the signature of the next before running it, anchored in an immutable ROM key hash, with version counters against downgrade and a TPM log of what ran.›

How it is built

Architecture overview

Content provenance signing attaches a verifiable history to a piece of media. A capture device or editing tool, the claim generator, collects statements about the asset (who or what made it, what edits happened, which sources were combined), hashes the content, signs the whole bundle with a key whose certificate chains to a trusted authority, and embeds the result in the file. Anyone later can check that the signature is intact, that the content still matches the hashes, that the certificate was valid at signing time, and whether the signer is on a list they trust. The standard for this is C2PA, and its consumer-facing name is Content Credentials.

The one idea to hold on to is that a manifest proves who signed which statements about exactly these bytes, not that the statements are true. Trust therefore moves to the signer's identity, to how well its key is protected, and to the validator's list of trusted authorities. When a manifest is removed from a file, a weaker second binding (a fingerprint or invisible watermark) can find it again in a repository, but it cannot prove the pixels are unchanged.

Parts:

  • Signer identity — certificates for the signing key and the chain a validator must trust — x509-certificates (no page yet), ECDSA signatures
  • Encoding and container — how claims and signatures are serialised and wrapped in the file — cbor-cose (no page yet)
  • Hard binding — hashes tying the manifest to the exact content bytes, with tree hashing for large video — Cryptographic hashes (SHA-2, BLAKE3), merkle-tree (no page yet)
  • Soft binding — content-derived identifiers that survive re-encoding and let a lost manifest be found — Perceptual hashing; invisible-watermarking (no page yet), built on Convolutional networks, discrete-cosine-transform (no page yet) and forward-error-correction (no page yet)
  • Time and revocation — proof of when the signature was made and that the key was still good — trusted-timestamping (no page yet); certificate-revocation (no page yet), built on Bloom filter and HTTP caching semantics
  • Protected signing environment — where the private key lives and how a validator knows the device is genuine — hardware-backed-keystore (no page yet); Secure boot and remote attestation, built on measured-boot (no page yet), trusted-execution-environments (no page yet) and csprng (no page yet)
 CLAIM GENERATOR (camera, editor, cloud service)                  VALIDATOR (viewer, platform)
 content bytes ─► hard binding: hash (SHA-2) / box hash / Merkle    parse JUMBF ─► claim (CBOR)
 assertions: actions, ingredients, metadata, thumbnail, source       │
        │              │                                            ├─ signature: COSE_Sign1 + x5chain ─► trust list?
        ▼              ▼                                            ├─ time-stamp (RFC 3161) ─► TSA trust list
      claim (CBOR) ─► COSE_Sign1 signature (key in secure element)   ├─ revocation: stapled OCSP / query
        │            + x5chain (signer + intermediates)             ├─ assertions + ingredients (recursive)
        │            + time-stamp token + OCSP response             └─ content hash ─► Valid / Trusted
        ▼
 manifest in JUMBF box ─► embedded in file ──────────────► (optional) soft binding: fingerprint / watermark ─► manifest repository

How the parts fit together

Signer identity

Every claim signature is a COSE_Sign1 structure that carries the signer's credential in its protected header: an x5chain holding the signer's certificate and all intermediate CAs, but not the root (source: C2PA specification 2.1, section 14.5, building on RFC 9360). The validator holds the trust anchors and builds the path itself, treating the supplied chain as untrusted input. x509-certificates (no page yet) are the right credential because they bring issuance, validity periods, key usage constraints and a revocation story that a CA ecosystem already operates. The alternative, a bare public key published by the vendor, has no way to expire, rotate or revoke a single device.

Allowed signature algorithms in the 2.1 specification are ECDSA with SHA-256, SHA-384 or SHA-512 on the P-256, P-384 and P-521 curves, RSASSA-PSS, and Ed25519 (source: C2PA specification 2.1, section 13.2). ECDSA signatures are the common choice because secure elements and phone keystores support them natively. The contract with the next part: the signature covers the claim bytes, and nothing else may carry authority.

Encoding and container

cbor-cose (no page yet) gives a compact, canonical binary form: the claim is CBOR and must follow the core deterministic encoding rules, so the bytes that were signed are the bytes that are verified; the signature uses the COSE_Sign1 structure with the algorithm in the protected header and an empty external-data field (source: C2PA specification 2.1, sections 10 and 13.2). The manifest is wrapped in a JUMBF box (ISO 19566-5), chosen because it can hold several manifests, address elements by URI, carry JSON, CBOR and image data side by side, and already fits JPEG and ISO base media file formats (source: C2PA specification 2.1, section 11.1). A validator ignores boxes it does not recognise.

A manifest is a set of assertions, one claim that lists them by hashed URI, and the claim signature. Manifests in a manifest store can reference each other as ingredients, so a composite image can carry the credentials of its source images, and the last manifest is the active one whose bindings are checked.

Hard binding

The hard binding is a hash that matches only these bytes. A standard manifest must contain exactly one: a data hash over byte ranges, a box hash for JPEG and PNG-like box formats, a BMFF hash for MP4, or a collection hash for sets of files (source: C2PA specification 2.1, section 9.2). The hash algorithms permitted for new content are SHA-256, SHA-384 and SHA-512; SHA-3 is not allowed because COSE had not yet defined signature algorithms using it (source: C2PA specification 2.1, section 13.1). See Cryptographic hashes.

merkle-tree (no page yet) enters for video. A BMFF hash can include Merkle tree rows over fixed or variable blocks of the media data, so a player can validate fragments of a fragmented MP4 as they arrive instead of waiting for the entire file, and the leaf nodes may align to random-access points in the video (source: C2PA specification 2.1, sections 15.12 and A.4). The contract: a hard binding fails on any change to the covered bytes, including legitimate re-encoding, so it distinguishes "this exact file" from "something derived from it".

Soft binding

When social platforms strip metadata or re-encode, the hard-bound manifest is lost or no longer matches. A soft binding is an identifier computed from the content rather than its bytes: a fingerprint (perceptual hashing) or an invisible watermark (invisible-watermarking, no page yet) embedded in the pixels (source: C2PA specification 2.1, sections 2.3.13 and 9.3). Watermark payloads are short and must survive compression and cropping, so they are typically protected with an error-correcting code (forward-error-correction, no page yet) and embedded either in a transform domain such as the discrete cosine transform (discrete-cosine-transform, no page yet) or by a trained encoder and decoder network; Adobe's TrustMark uses neural models (source: TrustMark README), the convolutional-network family. A manifest may hold zero or more soft bindings, and they must come from the C2PA-registered algorithm list. Their job is lookup: the fingerprint or watermark is the key into a manifest repository to find the original credentials. A soft binding must never be used as a hard binding, because it is not statistically unique and cannot prove the content is unmodified.

Time and revocation

trusted-timestamping (no page yet) lets a signature remain verifiable after the signing certificate expires. The generator sends the signature hash to a time-stamping authority and stores the RFC 3161 token in the COSE headers. At validation the attested time, not the current time, is used to check the signer certificate's validity, and the TSA has its own trust list, separate from the signer list (source: C2PA specification 2.1, sections 14.4.2 and 15.8). If a device is offline when it signs, a separate Time-Stamp Manifest can add the token later.

certificate-revocation (no page yet) handles a stolen or misissued key. The generator may staple an OCSP response into the signature headers; a stapled response counts only when a valid time-stamp gives an attested time, and it must show the certificate was not revoked at that time. Without a stapled response the validator may query the OCSP responder (source: C2PA specification 2.1, section 15.9; RFC 6960). Stapling matters for scale and privacy, since viewers do not have to contact the CA when they open an image. Where a client must check offline, a compact revocation set such as a Bloom filter answers "possibly revoked" locally, and HTTP caching semantics decide how long a fetched response may be reused.

Protected signing environment

The private key is the entire security of the system. hardware-backed-keystore (no page yet) keeps it in a secure element or TEE so malware on the device cannot export it. The standard also lets an assertion state where its contents came from, with source types for a claim generator or data provider in a rich execution environment (an ordinary OS), in a trusted execution environment, from a remote provider, or entered by a human (source: C2PA specification 2.1, assertion metadata data source types). Secure boot and remote attestation is how a CA or validator becomes confident that a device key really lives in that hardware and the software running on it is the vendor's: the device proves a measured boot chain (measured-boot, no page yet) and a trusted execution environment (trusted-execution-environments, no page yet) over a fresh random challenge (csprng, no page yet). Issuing signing certificates on a vendor's word, the alternative, leaves any rooted device able to sign. Per the specification, certificates for hardware and software signers trusted to sign claims are rooted in the C2PA Trust List, and validators may add their own anchors (source: C2PA specification 2.1, section 14.4).

Data and control flow

Capture and sign on a camera or phone.

  1. The capture pipeline produces the image and assertions: capture action, device information, optional location, a thumbnail.
  2. The generator computes the hard binding over the image bytes with the manifest's own location excluded (or reserved at a fixed size).
  3. It builds the claim: hashed references to each assertion, the binding, and the generator information, encoded as deterministic CBOR.
  4. The secure element signs the claim with ECDSA inside a COSE_Sign1 structure; the headers carry the x5chain, and a time-stamp token from a TSA, plus a stapled OCSP response, when online.
  5. The manifest is wrapped in JUMBF and embedded in the file; optionally a watermark or fingerprint is registered with a repository.

Edit and re-sign.

  1. The editor reads the active manifest of the input and validates it.
  2. It writes a new manifest that lists the input as an ingredient, records actions (crop, composite, generative step), and binds the new bytes.
  3. If only metadata changes and the content does not, an update manifest documents the change without a new content binding; removed assertions are redacted with a record of what was removed (source: C2PA specification 2.1, sections 6.8 and 11.2.3).
  4. It signs with its own certificate: the new manifest vouches for the edit, the ingredient manifest for the original.

Validate in a viewer.

  1. Locate the manifest store; if the manifest is gone, try a soft binding lookup in a manifest repository.
  2. Check the claim signature against the signer's certificate and path to the trust list, then the time-stamp and revocation information.
  3. Check assertions, then each ingredient manifest recursively, then recompute the hard binding over the content.
  4. Report a state: well-formed, valid (signature, binding and validity period check out and the credential is not revoked), or trusted (valid and the signer chains to a trusted anchor) (source: C2PA specification 2.1, section 14.3).

Scaling

  1. Signing volume: one asymmetric signature per asset is cheap, but a service signing millions of generated images needs HSM capacity or batching. Lever: sign at the edge with short-lived credentials; keep the CA in a separate tier.
  2. Large and live video: hashing a multi-gigabyte file as one block delays validation. Lever: Merkle-tree BMFF hashing validated per fragment.
  3. Manifest size: nested ingredients grow with every edit. Lever: compressed manifests (Brotli), thumbnails only where needed, external manifests referenced by URI.
  4. Revocation traffic: viewers querying OCSP for every image overload responders and leak browsing habits. Lever: stapled responses and time-stamps.
  5. Soft-binding lookups: a repository indexed by fingerprint or watermark must answer near-match queries across billions of assets. Lever: approximate nearest-neighbour search over compact fingerprints; exact lookup for watermark payloads.
  6. Trust list distribution: anchors and revocation change over time. Lever: validators update trust lists regularly; allow user-configured lists.

Failure modes

FailureSymptomCauseFix
Stripped credentialsimage shows no provenanceplatform or editing tool removes metadata or re-encodessoft binding lookup in a repository; platforms preserve or re-attach manifests
Hard binding broken by benign edit"tampered" on a resized or recompressed copythe hash covers exact bytestreat as a new derived asset: re-sign with the original as ingredient
Untrusted signermanifest valid but not trustedsigner not on the validator's trust listsurface "valid, unknown signer" clearly; allow user trust anchors
Compromised signing keyforged credentials from a trusted signerkey exported from a software keystorekey in secure element, short-lived credentials, revocation with time-stamps
Expired certificateold assets start to fail validationvalidity checked against the current timetrusted time-stamps so validity is evaluated at signing time
Revocation unknownvalidators disagree or fail openno stapled response and the responder is unreachablestaple at signing; define the policy for "unknown"
False reassuranceusers read "has credentials" as "is true"assertions are statements by the signerUI states who signed and what is claimed, not authenticity of the scene
Watermark removal or forgerywrong or missing match from the repositorythe watermark was attacked or reused on other contenttreat soft matches as hints and verify with the hard binding
Redaction abusea damaging fact removed from the historyan editor redacts assertions in an ingredientthe claim lists what was redacted, by label; the actions assertion cannot be redacted
Privacy leaklocation or identity exposed in the manifestoptional assertions embed personal datamake sensitive assertions opt-in; redact before sharing

Real implementations

namewhat it isrepolicencenotes
c2pa-rsRust SDK to create, sign, embed and validate C2PA manifestscontentauth/c2pa-rsMIT OR Apache-2.0reference SDK of the Content Authenticity Initiative; C API for other languages
c2patoolcommand-line tool to display and add manifestscontentauth/c2patoolApache-2.0reads manifest reports and adds manifests to supported formats
c2pa-jsJavaScript libraries: c2pa-web for browsers, c2pa-node for Node.jscontentauth/c2pa-jsMITbrowser WebAssembly bindings of c2pa-rs; Node can also add signed manifests
c2pa-pythonPython binding for c2pa-rscontentauth/c2pa-pythonApache-2.0scripting and pipelines
TrustMarkinvisible watermarking for images, with an example of recording it in a C2PA manifestadobe/trustmarkMITsoft binding by watermark; Python, JS, Rust and C++ runners
C2PA Specificationthe standard itself, with trust model, validation rules and assertion definitionsc2pa.org—version 2.1 used here; the C2PA Trust List defines the default anchors

The alternative: detect instead of prove. Classifiers that guess whether media is synthetic yield probabilities that decay as generators improve, and say nothing about real media; signed provenance proves origin for participating tools, but says nothing about media from tools that do not sign. Systems use both.

Sources

Similar systems

Share the most building blocks with this one.