content credentials · c2pa · private by construction
Who made this file, and has it changed since?
If a file carries Content Credentials, you'll see what made it — including whether that was AI — who signed it, and whether a single byte has moved since.
The image and video are c2pa-rs test fixtures signed with test certificates, so you can watch the trust check fail honestly while the signatures and hashes pass. The PDF is a real ChatGPT-generated document, and it verifies.
Drop a file here
or click to choose — up to 10 at once
- JPEG
- PNG
- WebP
- GIF
- HEIC
- MP4
- MOV
- MP3
- +6 more
Your file stays on your device
result
Inspection result.
Claims (as recorded — unverified)
Signer chain (as presented in the manifest)
Vouched for by (who signed as a named actor)
A C2PA claim says which tool wrote the manifest. A CAWG identity assertion says which person or organisation signed over the content with their own credential. It does not say who created the file.
Validation log
Every C2PA §15 status the validator recorded, in order.
Raw manifest
The JUMBF box tree exactly as embedded — every assertion, including the ones the summary above doesn't model.
what it checks
The whole C2PA validation algorithm, in your browser.
Most viewers show you what a manifest says. This one checks whether the manifest is telling the truth.
COSE signature
Verifies the COSE_Sign1 over the claim — ES256/384/512, PS256/384/512, and EdDSA.
Certificate chain
Chains the signer to the official C2PA trust list and enforces the certificate profile — EKU, key usage, no weak algorithms.
Hash bindings
Recomputes the hard-binding content hash — c2pa.hash.data for most carriers, c2pa.hash.bmff.v2/.v3 for HEIC and MP4 — and every assertion's hashed_uri, so edits after signing show up.
RFC 3161 timestamp
Full CMS verification of the timestamp token, the TSA chain, and that it covers this signature.
Ingredients
Recursively validates nested manifests from earlier edits, with cycle detection.
Private by construction
The validator is WebAssembly running in your tab. No upload, no server, no analytics on your files — and the shareable link carries the result, never the file. Signing keys live in your browser's WebCrypto store, non-extractable.
sign
Sign a file with your own key.
Embed Content Credentials right here. The private key is created or imported into your browser's WebCrypto store as non-extractable and never leaves it; the page only ever asks it for signatures. Be clear about what that buys: a test identity made on this page proves a file has not changed since you signed it — not who you are — and every verifier, this one included, will say the signer is untrusted. Import a certificate chain from a CA on the C2PA trust list to be trusted.
Identity
No signing identity yet. Create a self-signed test identity in one click, or import your own key and certificate chain.
Import my own key and certificate
The key is imported into WebCrypto as non-extractable and the pasted text is discarded. The key must match the first certificate — this is checked with a test signature. ECDSA P-256/384/521, RSA (2048+) and Ed25519 where the browser supports it.
Sign
Adds a second signature — a CAWG identity assertion — made with the same credential, saying that its holder vouches for this content in that role. It does not claim they created the file. A verifier reports it as genuine but unproven unless they have put your certificate authority on a trust list of their own.
Advanced
A browser can only reach a timestamp authority that allows cross-origin requests over https — most public ones do not. If it fails, nothing is written.
Signed
questions
What people ask.
Can this tell me if an image is AI-generated?
If the file carries Content Credentials that say so, yes — this reports it prominently, along with the model that made it where the manifest names one. But the absence of a credential is not evidence that something is real. Most files on the internet carry no manifest at all, and metadata can be stripped by any tool that re-saves the image. A credential is proof of provenance when it is present; silence proves nothing either way.
What is C2PA?
C2PA (Coalition for Content Provenance and Authenticity) is the open standard behind "Content Credentials". A camera, editor or generative model signs a manifest into the file describing what made it and what was done to it. Because the manifest is cryptographically signed and bound to the file's bytes, both the claim and any subsequent tampering are detectable.
Why does it say the signature is valid but the signer is untrusted?
Those are two separate questions. The signature check asks whether the bytes were signed by whoever holds the key. The trust check asks whether that key belongs to anyone recognised — it chains the signer's certificate to the official C2PA trust list. A file signed with a test or self-issued certificate passes the first and fails the second, which is the correct and honest outcome rather than a bug.
Someone “vouched for” a file — does that mean they made it?
No, and the standard is explicit about it: a CAWG identity assertion “should not be construed to convey either attribution or ownership”. What it does say is narrower and more useful — a named actor signed over this manifest's content with their own credential, in whatever role they declared. Where the credential comes from an identity aggregator, the names and accounts you see are that aggregator's word: it attests that the actor showed it those signals and showed it this asset, nothing more.
This page reports an actor as unproven unless you have given it a trust list of your own. That is the normal outcome, not a warning: nobody publishes a list of authorities that vouch for people, so a genuine signature by a real person still reads as unproven here.
What does a failed hash binding mean?
The manifest records a hash of the file's own bytes at signing time. If that hash no longer matches, the content has changed since it was signed — a crop, a re-compression, or a deliberate edit. The credential still tells you truthfully who signed the original; it simply no longer describes the file you have.
Why does a file say “signed, but not bound to this file”?
Because the credential is real and nothing checked it against these bytes. It happens when the manifest describes something the file carries rather than the file itself — an image or a font inside a PDF, which is where the C2PA spec says such a manifest belongs — and when a fragmented video is inspected without its fragments. It is neither a pass nor a failure: the signature and the signer are exactly as reported, and the question “are these the signed bytes?” simply has no answer here. A green tick would claim more than the validator did.
Are my files uploaded anywhere?
No. The validator is compiled from Go to WebAssembly and runs inside this page, so your file is read by your own browser and never sent over the network. There is no server to upload to. The shareable link encodes the result in the URL, never the file.
Can I sign my own files here?
Yes. The page creates a key in your browser's WebCrypto store as non-extractable, or imports one you already have, and the validator's Go code — compiled to WebAssembly — builds the manifest and asks the key for each signature. The key never leaves the browser; only the signed file does, as a download. A test identity made here is self-signed, so verifiers will report the signature as valid and the signer as untrusted — that is the honest outcome, not a fault. To be trusted, import a certificate chain issued by a CA on the C2PA trust list. Timestamping needs a timestamp authority that allows cross-origin requests, which most public ones do not.
Which file types can it read?
JPEG, PNG, WebP, GIF, TIFF, DNG, HEIC, HEIF, AVIF, SVG, MP4, MOV, M4A, AVI, WAV, MP3 and PDF. If a format is not listed, the page will say so rather than silently reporting "no credentials".
for developers
Powered by a pure-Go C2PA implementation.
This page is a thin WebAssembly wrapper around richardwooding/c2pa — a small, no-cgo Go library with a fast unverified reader and a full validator. The same code that runs here runs server-side in file-search-on and the c2pa-mcp MCP server.
go get github.com/richardwooding/c2pa
// the entire integration r := c2pa.Validate(ctx, c2pa.JPEG, file) if r.Valid { fmt.Println("verified, signed at", r.SignedAt) }