Under the hood

How CaptureSeal works

Last updated

CaptureSeal fingerprints every photo and video with SHA-256, signs those fingerprints together with the time and place using a key locked in the phone’s secure hardware (Secure Enclave on iPhone, StrongBox/TEE on Android), and cross-checks the clock against internet time. Anyone can recompute the fingerprints and check the signature, so any later edit shows.

Capture produces an original and a stamped copy; both are fingerprinted, signed into a record, and verified by anyone. Originaluntouched file Stamped copytime · place · QR manifest.jsonSHA-256 × 2, time, GPS manifest.sighardware-held key
What one capture produces. The signature covers the exact bytes of manifest.json, which holds both fingerprints.

What happens when you press the shutter

  1. Capture. The camera saves the untouched original, exactly as the sensor produced it, with GPS in its metadata.
  2. Stamp. A stamped copy is made with the date, time, address, coordinates and a QR code burned into the pixels.
  3. Fingerprint. Both files get a SHA-256 fingerprint: a 64-character code calculated from every byte. Change anything and it changes completely.
  4. Cross-check the clock. Shortly before capture, the phone’s clock is compared with internet time, and the difference is recorded.
  5. Sign. The fingerprints, time, location and device go into a record (manifest.json) signed with an ECDSA P-256 key held in the phone’s secure hardware (Secure Enclave on iPhone, StrongBox/TEE on Android).
  6. Verify. Anyone recomputes the fingerprints and checks the signature with the public key inside the record, in the app, in a browser, or with OpenSSL.

What’s in the record?

Each capture has a manifest.json and a manifest.sig. The record holds the capture ID, kind (photo or video), the capture time and time zone, how the time was established (network-verified with the measured clock offset, or device clock), the GPS fix with its accuracy and the looked-up address, the device model and OS version, the camera and resolution, the filename, size and SHA-256 of the original and the stamped copy, and the public key and its key ID.

The signature is an ECDSA P-256 signature over SHA-256 of those exact bytes, DER-encoded. The key ID is the first 8 bytes of SHA-256 of the public key, in hex, which is what the verify page shows in groups of four.

How do I verify a capture?

A link alone doesn’t prove the photo; the check does. A verify link shows what the capturing phone recorded. Only the file you were sent can show that your copy matches it, so the page stays neutral until you drop that file in. It turns green only for an identical file, and red for anything else.

Verify with OpenSSL

# 0. A Proof File is a standard zip inside: unpack it (or use the separate demo files)
unzip "CaptureSeal F1E33C32.seal" -d proof && cd proof
# 1. Rebuild the public key from the record (or use key.pem from the package)
KEY=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["signing"]["publicKey"])' manifest.json)
{ printf '3059301306072a8648ce3d020106082a8648ce3d030107034200' | xxd -r -p; printf '%s' "$KEY" | base64 -d; } \
  | openssl pkey -pubin -inform DER -out key.pem

# 2. Check the signature over the exact bytes of manifest.json
openssl dgst -sha256 -verify key.pem -signature manifest.sig manifest.json
#    → Verified OK

# 3. Check the key ID shown on the stamp's verify page
printf '%s' "$KEY" | base64 -d | openssl dgst -sha256 -r | cut -c1-16 | tr a-f A-F

# 4. Compare the media's fingerprint with "sha256" in manifest.json
#    (the stamped copy is under "sealed", the untouched original under "original")
shasum -a 256 *.jpg

Tested on macOS with LibreSSL/OpenSSL 3. On Linux, sha256sum works in place of shasum -a 256.

Sharing is always free: send the photo or a .seal proof file and anyone can verify it in CaptureSeal or at captureseal.link/verify. We only charge for hosting verify links.

What’s in a Proof File (.seal)?

A Proof File is one file anyone can verify. It opens in CaptureSeal on iPhone, with a preview right in Files, Mail and Messages; on any computer, drop it on captureseal.link/verify. Inside, it’s a standard, uncompressed zip archive, so it stays future-proof and inspectable with ordinary tools:

Rename it to .zip and any unzip tool opens it; the verifier accepts both. Try the demo Proof File.

How a verify link is tied to your device

A capture’s ID is printed in its QR code, so anyone who sees the photo can read it, and anyone can sign a record with a key of their own. To stop a stranger from publishing a fake record under your capture’s ID, the QR code also names your device’s key: it links to /v/<capture ID>#<original fingerprint>.<key ID>.

Why a copy sent over WhatsApp won’t match

Messaging and social apps recompress photos and videos to save data. The picture looks the same, but the bytes differ, so the fingerprint differs. That’s the seal working as intended: it can’t tell a harmless recompression from an edit. The QR code still leads to the record, so the recipient can see the original time and place and ask for the original file.

What it proves, and what it can’t

A passed check shows the file wasn’t edited after capture, the stamped time and place are the recorded ones, and the record came from the device whose key ID it shows. It can’t show the scene was real, who held the phone, or GPS truth on a modified device. The security page covers each limit.

Questions

Frequently asked questions

Why both a stamp and a signature?

The stamp is for people: it shows the time and place at a glance. But anyone can type a stamp with an editor. The signature is for checking: it ties the fingerprints, time and place to one device key, so an edit shows up.

What is a SHA-256 fingerprint?

A 64-character code calculated from every byte of a file. Two different files practically never share one, and changing a single pixel, or re-saving the file, gives a completely different code.

Where is the signing key?

In the phone’s secure hardware: the Secure Enclave on iPhone, or StrongBox or the Trusted Execution Environment (TEE) on Android. It can use the key but never reveals it. Not even CaptureSeal can read or copy it. Only the public key leaves the phone, inside each record.

How accurate is the time?

When the phone is online, CaptureSeal compares its clock with internet time shortly before capture and records the offset. Offline, the record says “Device clock”, so a reader knows the time wasn’t cross-checked.

What does a verify link publish?

Only the signed record: time, location and address, device model and OS, fingerprints and the public key. Never the photo or video. You can withdraw a link at any time.

Can someone publish a fake record under my photo’s ID?

They can publish a record signed with their own key, but your QR code and verify links name your device’s key, so the verify page shows only your record. Their record would be listed separately, with its different key ID, and only to someone opening a bare link without a key.

Coming soon to iPhone & Android

Be first to seal your photos

CaptureSeal is coming soon to iPhone and Android. Leave your email and we’ll tell you the day it launches.

I’ll use it on (optional)