# Sign · verify · who-verified

**Six copy-paste recipes put a publicly verifiable, revocable identity under a C2PA signer: bind it to the claim-signer cert serial it already carries, prove it keyless, DANE-anchor it so any verifier trusts it with no Trust-List slot, see who verified your content, revoke one burned signer at DNS-TTL, and sign an AI agent's output under an identity you can trust. Each one runs today against shipped primitives.**

They share one primitive: a routable IPv6 `/128` that a signer *derives* from a key it already holds, DNSSEC-signed and [DANE-pinned](/docs/dane) so anyone can verify it and nobody can forge it. Everything below is built from shipped parts: the device `/128`, keyless [verify](/docs/verify), the reverse-observability `op:lookups`, per-signer [egress governance](/docs/egress-governance), the [transparency log](/docs/transparency), and one-call [revoke](/docs/control-plane). Whisper does **not** create the C2PA manifest, sign the claim, or embed a watermark. Your Content Credentials tool keeps doing that. Whisper anchors the *signer* that manifest already references. Where a step is a pattern you assemble, or a connector still on the roadmap, it says so in plain words.

> **What's shipped, stated honestly.** The signer `/128` derivation from the signer's public key + its cert serial, keyless [verify](/docs/verify) / RDAP, the reverse-observability `op:lookups`, per-signer [egress governance](/docs/egress-governance) (policy · firewall · budget · revoke), and the Merkle [transparency log](/docs/transparency) are all **live**. Three caveats these recipes are written around: **(1)** there is no first-class `--c2pa-serial` CLI flag yet, so a signer is provisioned via the control-plane API (which *is* live) with the cert serial passed as the generic `device_id`; **(2)** a DNSSEC/DANE anchor is *not (yet)* a formally recognized C2PA *conformance* trust anchor: today conformance centers on the curated C2PA Trust List, so we surface the anchor via a CAWG identity assertion and as a proposal to the standard, a *complementary* identity ecosystem, never a fork; **(3)** a turnkey C2PA signer plugin and a hosted CAWG `did:web` issuer are roadmap. Whisper anchors the **signer identity at the DNS/DANE boundary**. It is not the manifest, not the claim signature, not the watermark, and it does not decide whether content is *true*. Each recipe names exactly where it stops.

## The shared primitive: a signer identity anchored in open DNS, not a gate-kept list

Every conformant Content Credential already carries an X.509 **claim signer**: the claim signature is a [COSE_Sign1](https://www.rfc-editor.org/rfc/rfc9360) whose certificate chain travels in-band in the `x5chain` header, with the EKU `c2pa-kp-claimSigning` (OID `1.3.6.1.4.1.62558.2.1`). That end-entity cert has a **serial**. Whisper takes only the signer's **public** SubjectPublicKeyInfo (SPKI) and, together with the cert serial as a domain separator, *deterministically derives* a `/128` under `2a04:2a01::/32` (`AS219419`). The private signing key never leaves the signer; the server only ever computes a public *address*.

C2PA decides whether to trust a signer by checking its cert against an *allowed* list or a set of *trust anchors*. Crucially, the spec makes those **pluggable configuration inputs to the validator**, not a single mandated PKI. That is the honest hook: a DNSSEC-signed DANE anchor is a legitimate *alternative* trust source, not a fork of C2PA. Today an off-list CA renders your Content Credential as *"unknown source"*, there is no free automated path (no "Let's Encrypt for provenance"), commercial claim-signing certs run ~$289/yr, and the recognized-CA set is governed by a small coalition. The derivation below keeps the signature format exactly as-is and adds the four properties the gate-kept list withholds:

- **Deterministic & idempotent**: the same signer key + cert serial always yields the same `/128`. Re-anchoring after a cert renewal for the same serial returns the same address; there is no registry to keep in sync.
- **Tenant-bound & unlinkable**: the derivation folds in your tenant, so the same key under two tenants yields two *unrelated* `/128`s. No one can link a signer across brands by address suffix, and there is no enumeration oracle.
- **Forge-proof**: the `/128` is [DANE-EE `3 1 1`](/docs/dane)-pinned to the signer's key and has DNSSEC-signed reverse DNS. An impostor with a different key derives a different address and can't present the pinned key.
- **Revocable worldwide**: one control-plane call tears the `/128`, its PTR, and its DANE pin down everywhere at DNS-TTL speed, a far shorter exposure window than C2PA's optional, cache-heavy OCSP/CRL.

```
C2PA claim-signer         ──public SPKI · domain-sep = cert serial──▶   /128                ──DNSSEC + DANE-EE 3 1 1──▶   a signer anyone verifies
COSE_Sign1 · x5chain                                                    2a04:2a01:c0d3::5e         (no Trust-List slot)         whisper verify --trustless
EE cert serial = device_id                                             routable · tenant-bound                                 op:revoke → gone at DNS-TTL
(private key stays with signer)
```

The C2PA claim-signer's key is already the root of trust; Whisper binds its *public* half + the cert serial to a routable, publicly verifiable `/128` and gives it the off-switch the Trust List's OCSP/CRL never delivered in real time. The cert serial alone yields nothing: you cannot go serial → `/128` without the key. Every check in the recipes below that doesn't provision is **keyless**: no account, just DNS and TLS any verifier already has.

## Recipe 1: Bind a C2PA signer to its cert serial

Give a signer the public identity it should have had, derived from the key it already signs with and named by the claim-signer cert serial already embedded in every manifest it produces. One call; the reply is the address, and a stock `dig` confirms the name and the DANE pin.

> **Boundary.** This **complements** your C2PA signing stack and the CAWG identity assertion. It does **not** create the manifest, produce the claim signature, or embed a watermark. It takes the *public* half of the same key your claim signer already uses and makes it addressable, publicly verifiable, and revocable. The `op:connect` WireGuard peer config it returns is *optional* for a pure signing key: a signing *service* can use it to source-bind its egress (Recipe 6), but a document signer only needs the anchored `/128` + DANE name.

Pass the claim-signer cert serial as the generic `device_id`. Re-running with the same signer key + serial returns the same `/128`: it is idempotent, so it is safe to run from a provisioning loop:

```bash
# Bind a C2PA claim-signer to the EE cert serial it already carries. device_id = the serial.
# Re-running with the same signer key + serial returns the SAME /128 (idempotent).
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.agents({op:'"'"'connect'"'"', args:{tier:'"'"'wireguard'"'"', identity_public_key:'"'"'<base64 SPKI of the signer key>'"'"', device_id:'"'"'03ac74661e9a4f0c'"'"'}}) YIELD op, ok, status, result, error RETURN op, ok, status, result, error"}' | jq .
# { "op":"connect", "ok":true, "status":200,
#   "result":{ "address":"2a04:2a01:c0d3::5e",
#              "name":"signer-03ac7466.c2pa.example-press.whisper.online",
#              "dane":"3 1 1", "dnssec":"signed",
#              "wireguard":"<peer config, optional for a pure signer>" } }
```

Confirm the `/128`, its name, and the DANE pin from the other side, keyless: the reverse DNS is forward-confirmed (PTR ⇄ AAAA), so nothing but `dig` is required:

```bash
dig +short -x 2a04:2a01:c0d3::5e
# signer-03ac7466.c2pa.example-press.whisper.online.

# …the forward AAAA resolves straight back: the round trip that makes it forge-proof:
dig +short AAAA signer-03ac7466.c2pa.example-press.whisper.online
# 2a04:2a01:c0d3::5e

# …and the DANE-EE pin over the signer cert's public key is right there in DNS:
dig +short TLSA _443._tcp.signer-03ac7466.c2pa.example-press.whisper.online
# 3 1 1 b653a4ef…fcb82d1d
```

The mint is not issued in the dark. Every `/128` minted and every one revoked lands in a public, append-only Merkle [transparency log](/docs/transparency), so you and an auditor can replay the full issuance history of a signer: the non-repudiable trail an EU AI Act Art.50(4) disclosure duty wants:

```bash
# The signer identity's ordered lifecycle (mint, any rotations, revoke), keyless:
curl -s https://whisper.online/ip/2a04:2a01:c0d3::5e/transparency
```

> A supplied serial is checked against a reused identity: the same signer key with a *different* `device_id` on your tenant is a `409`, and a non-string `device_id` is a clear `400`. That's liberal in what it accepts, strict and unambiguous in what it commits. **Honest status of the ledger:** it is tamper-evident, Ed25519-signed, and Bitcoin-anchored via OpenTimestamps today; independent third-party witnessing is the next step. It already speaks the C2SP `tlog-witness` protocol, so any external witness can co-sign. A first-class typed `--c2pa-serial` argument is on the roadmap; today the serial rides the generic `device_id`, which is shipped.

## Recipe 2: Prove a signer's identity, keyless

Once anchored, any verifier (a newsroom checking a wire photo, a platform verifying at ingestion, a fact-checker triaging a viral clip, a browser extension) proves the signer is real without an account, without a curated CA allow-list, and without trusting Whisper as an authority. This is the move that *resolves the signer* rather than merely reading the manifest. The proof re-derives against the IANA DNSSEC root.

> **Boundary.** This authenticates the signer's *network identity*: that the key behind a claim signature is anchored, publicly, to a resolvable name. It sits **alongside** the C2PA validation your tool already does (hash bindings, the COSE signature, the `x5chain`); it does not replace it. What it adds is a proof that is verifiable *off*-ecosystem: something the curated Trust List cannot give a verifier who isn't already configured with the right CA anchors.

The trustless check walks the full chain: DNSSEC to the IANA root, the DANE-EE pin (the same key that signs the claim), and the transparency-log entry. It prints exactly what it trusted:

```bash
# Prove any signer identity, trustless: re-derived against the IANA DNSSEC root,
# with no Whisper API trusted as an authority anywhere in the chain.
whisper verify --trustless 2a04:2a01:c0d3::5e
dnssec   pass   DNSSEC-root   AAAA, PTR and TLSA(3 1 1) all DNSSEC-validated to the IANA root
dane     pass   DNSSEC-root   served leaf SPKI-SHA256 == TLSA pin (== the C2PA signer cert key)
ledger   pass   DNSSEC-root   transparency-log entry present, signature verifies
CRYPTOGRAPHICALLY PROVEN, trust anchor: DNSSEC root (IANA) + DANE-EE, Whisper API NOT trusted
```

The same fact is reachable with tools already in every desk's toolbox: one keyless HTTPS call, or plain `dig`. A self-signed or off-list signer with no public anchor (what CAWG calls *well-formed but unrooted*) has no `/128` to resolve and says so plainly:

```bash
# Is this address a real, DANE-anchored signer identity? One keyless call, no install:
curl -s https://whisper.online/verify-identity/2a04:2a01:c0d3::5e
# {"is_whisper_agent":true,"dane_ok":true,"jws_ok":true,
#  "evidence":{"address":"2a04:2a01:c0d3::5e",
#    "ptr":"signer-03ac7466.c2pa.example-press.whisper.online.",
#    "forward_aaaa":"2a04:2a01:c0d3::5e"}}

# An off-list, self-signed signer with no public anchor: no registered /128, no DANE pin:
curl -s https://whisper.online/verify-identity/2a04:2a01::1
# {"is_whisper_agent":false,"detail":"no Whisper agent identity anchors this address"}
```

A lifted or stolen identity assertion buys an impostor nothing here: the identity is a network fact bound to a key, not a bearer credential that can be copied out of one asset and pasted onto another (C2PA's own security model flags exactly that identity-assertion-spoofing mode).

## Recipe 3: DANE-anchor your signer, no Trust-List slot

This is the wedge. Content signed by an off-list CA displays as *"unknown source"*; there is no free, automated path for an independent creator, a stringer, a small newsroom, or an agent to become a recognized signer, and the recognized-CA set is governed by a small coalition. Publish your claim-signer's key as a **DNSSEC-signed TLSA record on your own domain** and any verifier configured to consult it trusts the signer with *no list to join, no gatekeeper, and no annual CA toll*.

> **Honest scope: read this first.** C2PA trust anchors and allow-lists are *pluggable configuration inputs* to the validator, so a DANE-anchored signer is a legitimate *alternative* trust source. **But** a DNSSEC/DANE anchor is *not (yet)* a formally recognized C2PA *conformance* trust anchor. Today conformance centers on X.509 + the curated C2PA Trust List. Position this as a **complementary identity ecosystem**, surfaced through a CAWG identity assertion (`cawg.web_site` + a `did:web` issuer) and offered as a proposal to the standard, *never* as "already C2PA-approved." It directly answers C2PA's own experimental *Web Domain Trust Anchor* (a self-signed cert fetched from an HTTPS `/.well-known/c2pa.json`, which its authors flag as vulnerable to domain takeover) with the mechanism that proposal didn't use: **DNSSEC**.

```
a verifier reading a Content Credential asks: trust this signer?

  gate-kept path │ central C2PA Trust List (curated CAs · ~$289/yr) ──▶ off-list ──▶ ✗ "unknown source"
  Whisper path   │ the signer's own domain: DNSSEC-signed TLSA (3 1 1) == claim-signer key ──▶ ✓ trusted signer
                 │   domain-owner controlled · revocable at DNS-TTL · surfaced via a CAWG identity assertion
```

Anchor under a domain you actually own (BYOD) so a verifier reads *"signed by newsroom.example,"* not an opaque hosted label. Proving the domain is one shipped control-plane call (`op:domain`); thereafter your signer names live under your zone:

```bash
# Prove a domain you own and issue signer identities under it (op:domain, shipped).
curl -s https://graph.whisper.security/api/query -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.agents({op:'"'"'domain'"'"', args:{domain:'"'"'newsroom.example'"'"'}})"}'
# → returns the DS + delegation to publish once; then your signer's TLSA lives at
#   _443._tcp.c2pa.newsroom.example, DNSSEC-signed, under YOUR control.
```

What a DANE-aware validator does is exactly what you can do by hand: extract the claim-signer EE cert from the Content Credential, hash its public key, and compare it to the DNSSEC-signed TLSA pin on the signer's domain. If they match, the signer is trusted, with no list consulted and no CA phoned home:

```bash
# Export the claim-signer EE cert from the manifest (your C2PA tool does this), then:
openssl x509 -in claim-signer.pem -pubkey -noout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256           # the SPKI-SHA256 of the signer's key
# SHA2-256(...)= b653a4ef…fcb82d1d

# …and it equals the DNSSEC-signed TLSA 3 1 1 pin on the signer's own domain:
dig +short TLSA _443._tcp.c2pa.newsroom.example
# 3 1 1 b653a4ef…fcb82d1d          # match → trusted signer, no Trust-List slot
```

Two organizations that both trust the DNS root now verify each other's signers with no shared private list: the cross-org trust the curated model can't give without both parties joining it.

## Recipe 4: See who verified your content

Here is the quadrant no incumbent occupies. C2PA verification needs *no network call*: the signer cert travels in the manifest's `x5chain`, so a verifier builds the chain offline. That makes provenance **write-only** from the signer's side: once content is out, you have zero visibility into who checked it, where, or how often. The moment your signer identity is DNS/DANE-anchored, that changes: a verifier resolving and validating your anchor generates DNS/TLSA/RDAP lookups against Whisper's own authoritative servers, and `op:lookups` turns those into *"who verified my content"* analytics plus an impersonation early-warning.

> **Boundary.** `op:lookups` reports resolution and RDAP accesses against *your* signer identity's authoritative records: the PTR / AAAA / TLSA queries and `/ip` reads a DANE-aware verifier makes. It measures the *volume and source* of those lookups against your one anchor, never *which asset* a verifier was checking, so any per-asset correlation is yours to make against your own publish log, not something Whisper performs. It is a signal about who is checking *your anchor*; it does not see a verification performed purely from the in-manifest chain, and it is not a claim to observe traffic inside anyone else's network. It is the feedback loop C2PA and watermarking structurally lack, not a surveillance tap.

Ask who has been verifying a single signer identity (keyless, per-address) or the whole picture with your key:

```bash
# Who resolved / RDAP-queried this signer's DANE anchor? Keyless, per-address:
curl -s https://whisper.online/ip/2a04:2a01:c0d3::5e/lookups
# {"address":"2a04:2a01:c0d3::5e","window":"24h",
#  "lookups":[{"kind":"TLSA","count":184},{"kind":"PTR","count":57},
#             {"kind":"rdap","count":22}]}

# With your key (op:lookups): where your byline is being verified, and any spike:
curl -s https://graph.whisper.security/api/query -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.agents({op:'"'"'lookups'"'"', args:{agent:'"'"'2a04:2a01:c0d3::5e'"'"', window:'"'"'24h'"'"'}})"}' | jq .
#   184 TLSA resolutions: your byline verified from 6 regions in 24h
#   ⚠ spike: verify volume 3× your trailing baseline → cross-check your own publish log for identity lift
```

Feed a suspicious source straight into the attribution graph (below) and anonymous verification traffic becomes an attributed operator. That's the moment someone starts trading on your name.

## Recipe 5: Revoke one compromised signer at DNS-TTL

When a signing key is stolen or a signer is compromised, the C2PA answer is CRL/OCSP plus removal from the Trust List: committee-paced, cache-heavy, and (per the spec) revocation checking is *optional*, so a compromised signer can stay "trusted" long after. In 2025 a camera vendor had to **suspend its authenticity service and revoke its entire set of C2PA device certificates** after a security flaw (a fleet-wide reset). With a per-unit Whisper identity you revoke the *one* burned key worldwide at DNS-TTL, and every other signer keeps working:

> **Boundary.** This **complements** C2PA's own OCSP/CRL and Trust-List removal. It does not replace them, and it cannot retroactively un-sign what a stolen key already minted. A manifest carrying an [RFC 3161](https://www.rfc-editor.org/rfc/rfc3161) TSA countersignature and signed *before* the revocation stays syntactically valid. What DNS-TTL revocation changes is the *exposure window* (from "until OCSP, if ever" down to minutes), so it bounds the damage, it does not erase the past.

One verb, or one control-plane call. After it lands, every keyless check from Recipe 2 flips to `is_whisper_agent:false` for that address within the DNS TTL: no CRL to distribute, no Trust-List committee, no fleet-wide firmware reset:

```bash
# A signer key is burned. Revoke THIS unit's identity worldwide at DNS-TTL,
# not a fleet-wide cert reset. Every keyless check flips to false within the TTL.
whisper kill --revoke 2a04:2a01:c0d3::5e

# The same over the control plane (op:revoke): tears down /128 + PTR + DANE pin:
curl -s https://graph.whisper.security/api/query -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.agents({op:'"'"'revoke'"'"', args:{agent:'"'"'2a04:2a01:c0d3::5e'"'"'}})"}'
```

The revoke is itself written to the [transparency log](/docs/transparency), so the burn is auditable: an investigator can prove exactly when the signer stopped being valid, and any manifest signed after that timestamp fails to verify against a live identity worldwide. Revocation, counterfeit-signer detection, and containment are, deliberately, the *same* mechanism.

## Recipe 6: Sign an AI agent's output under a Whisper-anchored identity

Under EU AI Act Art.50(2), a generative-AI provider must mark synthetic output as machine-readable and detectable-as-AI; C2PA's IPTC `digitalSourceType` (`trainedAlgorithmicMedia`) and `c2pa.actions` (`c2pa.created`) carry exactly that assertion. The standardized part is *what* the manifest says; the open question is *who signed it*: signer trust for AI agents is explicitly unresolved, and no agent gets a Trust-List slot. An agent that already holds a Whisper `/128` and a [per-agent CA leaf](/docs/per-agent-ca) (deterministic, DANE-EE `3 1 1`) has precisely what it lacks: a publicly verifiable, revocable signer identity, with no list to join and no ~$289/yr CA fee.

> **Shipped vs. roadmap, plainly.** **Shipped:** the agent's `/128`, its [per-agent CA leaf](/docs/per-agent-ca) (DANE-EE, revocable), keyless verify, and `op:lookups`. **Roadmap:** a *turnkey* Whisper C2PA signer plugin and a hosted CAWG `did:web` issuer. Today you assemble the pattern: point your C2PA tool's external-signer hook at the per-agent leaf, and (optionally) run your own identity-claims aggregator as a `did:web` under your Whisper-anchored, DNSSEC-signed domain. And honestly on Art.50: a signature proves *who + integrity*, not that content is *AI*: the AI-generated declaration rides in the C2PA manifest's `digitalSourceType`; Whisper anchors the signer, it does not make you compliant. Recital 133 lists "cryptographic methods for proving provenance" as an *enumerated* technique and asks that verification be "accessible to the public," which an open DNS/DANE anchor advances.

Wire the agent's leaf as the claim signer and mark the output as AI-generated. The private leaf key stays on the agent; only the signature and the manifest go on the wire:

```bash
# The agent already holds a Whisper /128 + a per-agent CA leaf (DANE-EE 3 1 1):
# a publicly verifiable, revocable signer identity, no Trust-List slot required.
# Mark the output AI-generated in the manifest, and sign with the per-agent leaf:
#   c2pa.actions:      c2pa.created
#   digitalSourceType: trainedAlgorithmicMedia   (IPTC, declares it AI)
c2patool asset.png --manifest ai-manifest.json \
  --signer-path ./whisper-agent-leaf-signer.sh --reserve-size 20000 --output signed.png
# --signer-path = your external-signer hook → the agent's per-agent CA leaf;
# --reserve-size reserves bytes for its signature (c2patool requires it for an external signer).
# The result: a Content Credential whose signer is DNSSEC/DANE-verifiable and revocable.
```

Verifiers then resolve the agent-signer exactly like Recipe 2 (no account, no list) and, because it is a real network identity, the same [egress governance](/docs/egress-governance) that fences any agent fences this one: default-deny the signing service's egress to only your publish endpoint and the C2PA TSA, cap it, and keep the one-call kill-switch ready:

```bash
# Any verifier proves the agent-signer, keyless: no Trust-List slot involved:
whisper verify --trustless signer-agent.c2pa.example-press.whisper.online

# Govern the signing service's egress: default-deny, allow only what it must reach.
whisper policy set --agent 2a04:2a01:c0d3::a1 \
  --default deny --allow publish.example-press.com,tsa.c2pa-timestamp.example

# CAWG path: a Whisper DNSSEC-anchored domain is a first-class did:web issuer:
#   ICA VC issuer:  did:web:c2pa.example-press.whisper.online
#   cawg.web_site.uri points at the domain you proved in Recipe 3.
```

The result is the one thing agent stacks cannot otherwise get: an AI output whose signer is trusted *and* revocable, anchored in public DNS rather than a coalition's allow-list. See [Sign agent outputs](/docs/sign-outputs) for the full external-signer pattern and [did:web & VCs](/docs/did-web) for the CAWG issuer.

## Attribution: name whoever is trading on your signer (keyed)

The recipes above need no key. If you hold one, the same public API answers a deeper question: who is behind a source that is lifting your identity assertion, spoofing your brand, or scraping your verify endpoint. Passing an address to `whisper.identify` over `POST https://graph.whisper.security/api/query` fingerprints the operator across rotating clouds and residential proxies, because it tracks the infrastructure and the tooling, never the disposable last IP:

```bash
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.identify(\"34.90.x.x\")"}' | jq .
# operator fingerprinted across AWS / GCP / Azure; residential swarm collapsed by JA4
```

This is the graph API, not a CLI verb: the call above *is* the interface. The read-only verbs `identify`, `origins`, `walk`, `variants`, and `history` each return a reproducible, replayable JSON evidence chain a verification desk or an ICC-grade dossier can reproduce. More in [Graph & cognition](/docs/graph-api).

## Provenance is history, not truth: what signing can't do

Over-claiming is the credibility trap in this space, so here is the honest boundary of everything above:

- **Provenance ≠ veracity.** A valid signature proves *who signed* and that the bits weren't altered since, *not* that the content is true. A genuine signer can sign a staged photo or a deepfake-on-a-screen. What Whisper adds is **accountability**: the signer is publicly named and revocable, so a liar can be identified. It is not a truth oracle.
- **Signing doesn't stop a strip.** C2PA manifests are embedded metadata (JUMBF); a screenshot, a re-encode, or a platform upload can delete them: the standard concedes "a screenshot eliminates any trace of provenance." That is *watermarking / soft-binding's* job (SynthID, Digimarc), which Whisper complements, not replaces. `op:lookups` can help *detect* stripping via a drop in verification traffic; it cannot *prevent* it.
- **Not a deepfake detector.** The absence of a credential is not proof of fakery: most content is unsigned. Whisper raises the value of *signed-authentic* content; it does not flag *unsigned-synthetic*. Pair it with detection and watermarking.
- **It can't un-spoof the past.** DNS-TTL revocation shrinks a stolen key's exposure window dramatically versus optional/slow OCSP, but a spec-valid, TSA-timestamped manifest minted before the revoke stays valid: the mechanism bounds damage, it does not erase it.
- **Only where verifiers check.** Like all provenance, the value depends on downstream adoption: a channel that never validates gains nothing. And for privacy, anchor at the *org/domain* level with pseudonymity where a named human identity would endanger a journalist or a whistleblower; never force doxxing.

## Where each recipe stops and what's roadmap

Honest scoping, grouped by what each recipe touches. Whisper anchors the signer at the DNS/DANE boundary; the manifest, the pixels, and the veracity of the content stay exactly where they are.

| Recipe | Complements | Does *not* touch / replace |
|---|---|---|
| Bind a signer · DANE-anchor | C2PA Content Credentials, the CAWG identity assertion | creating the manifest or the claim signature: that stays with your C2PA tool |
| Prove keyless · Who-verified | `contentcredentials.org` verify, the in-manifest `x5chain` | embedding a watermark; the pixels; whether the content is *true* |
| Revoke a signer | C2PA OCSP / CRL + Trust-List removal | already-timestamped manifests signed before the revoke |
| Sign an agent's output | C2PA AI assertions (`digitalSourceType`), CAWG `did:web` | the "is this AI?" claim itself: that rides in the manifest, not the signature |

> **Roadmap, clearly labelled.** Streaming this evidence into a SIEM ships today for **Splunk**, **Microsoft Sentinel** and **OpenCTI** (signed JSON → CEF/ECS). A **STIX 2.1 over TAXII** feed for sharing signer-revocation and impersonation evidence across a provenance coalition is proposed, not yet available. The first-class typed `--c2pa-serial` argument is roadmap: provision signers via the control-plane API above, passing the cert serial as the generic `device_id`, which is live. A **turnkey C2PA signer plugin** and a **hosted CAWG `did:web` issuer** are roadmap; the external-signer + `did:web` pattern in Recipe 6 works today. And **DANE as a formal C2PA conformance trust anchor** is a proposal to the standard, surfaced via CAWG in the meantime, not "already approved." The transparency log is tamper-evident, Ed25519-signed and Bitcoin-anchored today; independent witnessing is the next step. Nothing on this list is required for the six recipes; they run on shipped primitives alone.

## Next

- [Signer & C2PA identity](/docs/industries/content/signer-identity): the full derivation the `/128` above comes from, signer key + cert serial to address
- [Provenance-gap cure](/docs/industries/content/provenance-gap-cure): these primitives applied to the exact trust-list / "unknown source" problem they were built for
- [DANE & TLSA](/docs/dane): the `3 1 1` pin every check here rests on, byte for byte
- [EU AI Act · C2PA · ISO 22144](/docs/industries/content/content-compliance): where these recipes map into Art.50 marking evidence
