ff.aifightfake.ai

Example

Prove the edit, not just claim it

Left: original clip. Right: same clip with one person covered by a moving black rectangle, a privacy-style redaction. The point of the proof is that only that edit happened, not a person added or removed, a sign rewritten, or the background altered.

Original

Original (demo)

Source clip

Edited

Tracked redaction

Edit proved
0:00 / 0:00

One control plays and scrubs both clips together.

Scrub to about 2.0s–4.5s to see the box follow that person on the edited clip.

This example demonstrates the edit-proof step, not the full pipeline. There is no hardware-rooted capture signature here (no secure-element signing in a real camera). The left clip is an original recording; the right carries a proof that only the redaction was applied. For capture signing, cameras, and the rest of the path, see How it works and Hardware.

Run it yourself

Clone the repository, run prove-edit on the same demo clip, then verify the proof file.

Prove edit

cargo run -p fightfake-cli --release --features eva-backend -- prove-edit \
  --input testdata/videos/input/demos1.mp4 \
  --gadget redact \
  --redact-track out/demos1-track/redact-track.json \
  --redact-frame-start 48 --redact-frame-end 108 \
  --redact-fill 0 \
  --touched-window --blocks-per-step 720 \
  --out-dir out/demos1-track

Verify proof

./target/release/fightfake verify-proof --proof out/demos1-track/proof.bin

What the proof attests to

The zero-knowledge proof does not say “trust us, we blurred someone.” It says, mathematically:

The published edited video is the result of applying only the declared redact gadget (a moving black rectangle over a declared frame range) to the original clip. The original pixels are fingerprinted as hash h1; the edited pixels as hash h2. The proof says the edit turns that h1 into that h2, and that no other pixel was changed.

The table below summarizes this specific example edit: redaction is active only on a limited frame window, and everything outside those frames remains unchanged.

Claims table
ClaimMeaning
Gadget = redact (tracked)Only macroblocks inside the per-frame rectangle are replaced with solid black (Y=0, i.e. luminance set to zero).
Frame window 48–107Redaction is active only in that range (~2.0s–4.5s at 23.98 fps).
30 keyframes + interpolationThe box moves smoothly between keyframes; outside the window the edit is identity.
h1 → h2 linkageh1 is the fingerprint of the original pixels; h2 of the edited ones. The C2PA assertion ties the proof to both; the verifier checks they match the manifest.
Proof systemThe proof system confirms the declared edit rules were followed on the original clip to produce this edited clip, without revealing private intermediate data.

What this demo does not include: Hardware-rooted capture signing (secure element on a camera). The left clip is a normal recording; the proof covers the edit step only. See how it works for the full capture → edit → verify path.

How we keep proving practical: touched time window

A 4K clip (3840×2160, 168 frames) has ~5.44 million 16×16 macroblocks. Our redaction only changes 60 frames (48–107). Proving every macroblock in the whole clip just to attest a ~2.5s edit is wasteful.

With --touched-window (redact only), the prover splits the video into three segments. Published h1 / h2 (fingerprints of the original and edited clips) combine all three segment hashes. The expensive SNARK runs only on MID, roughly a ~2.8× reduction vs full-clip proving for this window.

Touched-window table
SegmentFramesMacroblocks (approx.)How it’s attested
PRE0–47~1.54MPlain SHA-256 (bytes unchanged → hash proves identity)
MID (touched)48–107~1.94MFull Nova IVC + Groth16 with per-macroblock RedactRectCfg (moving box)
POST108–167~1.94MPlain SHA-256
What is actually proved

The proof checks decoded pixels (not just file bytes): applying only the declared redaction in frames 48–107 turns h1 into h2 with no other pixel changes.

Proving and verifying

Proving (one-time, editor machine)

Generating the edit proof for this 4K clip takes on the order of ~1–1.5 hours when scoped to the touched frame window (--touched-window). The prover checks only the macroblocks where the redaction can differ; untouched frames are hash-anchored instead.

Speeding this up is a focus for the coming months; progress will be reported on the blog.

~87–91 min ZK proving (~88–92 min total) for a smaller fixed-box window on Apple M1 with eva-backend

Other phases (typical): ffmpeg decode ~1s, edit + hashing ~35s, re-encode ~10s, C2PA ~0.2s.

Verifying (anyone, milliseconds to seconds)

Readers (or fightfake.ai’s verifier / a browser extension) check the C2PA manifest and run a cryptographic verifier on proof.bin in about 1–2 seconds, with no trust in the publisher’s server required.

  • fightfake verifyC2PA signatures, h1 linkage, proof SHA-256 in manifest · Sub-second
  • fightfake verify-proofFull cryptographic check on proof.bin · ~1–2 s (CLI)
  • Assertion linkage (WASM)h1 match + proof hash only · Milliseconds

Verification is intentionally fast: proving is heavy once; checking is cheap enough for a browser extension.