Releases: TheHolyOneZ/ZWatermark
Release list
ZWatermark v0.1.0
ZWatermark
Every screenshot, invisibly signed with your cryptographic identity.
A local-first desktop app that embeds a signed, steganographic watermark into every image you mark — so if the file leaks, is reposted, or is impersonated, anyone can prove where it came from and when.
Ed25519 · BLAKE3 · DWT spread-spectrum · Pixel-LSB signature · RFC 3161 · OpenTimestamps · Tauri 2 · Rust · React 19
Why
Visible watermarks get cropped off in three seconds. EXIF metadata gets stripped by any re-save. Netflix-tier forensic watermarking exists — but only for enterprise studios.
ZWatermark closes that gap for individuals and small teams:
- Journalists & sources — trace which reporter's laptop a leaked screenshot came from without watermarks visible to the source.
- Digital artists & creators — prove your art is yours before someone reposts it under their name.
- Pentesters & security consultants — provable origin for engagement screenshots.
- Insider-threat / IR teams — automatic marking, offline verification, CSV incident reports.
- Anyone who ships screenshots to strangers — a cryptographic receipt that this really came from you.
Free. Offline by default. Open source. GPL-3.0-or-later.
What it actually does
Every mark writes two independent layers into your image and (optionally) attaches a sidecar of external time proofs:
Under the hood
|
Signing |
Ed25519 — 32-byte pubkey, 64-byte signature, deterministic nonces (RFC 8032). Same primitive used by OpenSSH, Signal, Tor v3, WireGuard, GitHub SSH. |
|
Hashing |
BLAKE3 — 6–10× faster than SHA-256, Merkle-tree design, used for the image digest and the payload envelope. |
|
Robust layer |
DWT spread-spectrum embed in HL2 & LH2 subbands. Carries a 128-bit fingerprint (identity + device + timestamp + counter). Based on Cox/Kilian/Leighton/Shamoon 1997. |
|
Fragile layer |
1 bit per color channel per pixel LSB. Carries the full pubkey, exact signing time, optional screen serial, and the Ed25519 signature covering the entire image plus payload. |
|
Timestamps |
RFC 3161 TSA tokens (FreeTSA, DigiCert by default) + OpenTimestamps calendars (Alice, Bob, Finney). Only the SHA-256 hash is sent — no pixels, no identity. |
|
Sidecar |
image.png.zwm — bincode-serialized SidecarV1 containing digest, pubkey, creation epoch, RFC 3161 DER tokens and OTS receipt bytes. Verified offline (plus a Bitcoin-header lookup for OTS). |
How it works, in plain English
Skip this section if you already speak crypto. Read on if you want to understand what's happening under the hood without a computer science degree.
Your identity is a pair of secret math numbers
When you create an identity in ZWatermark, the app generates a matched pair of very large numbers — a private key (that stays on your machine, forever) and a public key (that anyone is allowed to see). The math connecting them has one useful property: you can use the private key to produce a signature over any file, and anyone with the public key can check that signature came from you — but they cannot use the public key to figure out the private key or forge new signatures.
We use a signing scheme called Ed25519. It's the same one behind SSH logins, Signal messages, Tor onion services, WireGuard tunnels, and every commit signed on GitHub. It's fast, small (32-byte public key, 64-byte signature), and considered secure against everything short of a working quantum computer.
Your private key never leaves your device. Not to us, not to a cloud, not to a server. If you back it up, you back it up yourself.
Marking an image is really two watermarks in one
When you press Mark, ZWatermark writes two independent watermarks into your image at the same time:
-
The Robust watermark hides tiny changes across the frequency structure of the image — think of it like fingerprint powder dusted through the whole picture rather than written on top of it. It's invisible to the eye. It survives being screenshotted again, JPEG-recompressed, resized, even photographed off a monitor with a phone. What it carries is a short fingerprint of your identity, your device, and roughly when you signed it.
-
The Fragile watermark writes a cryptographic signature into the least noticeable bit of every pixel. This one is a digital seal: it stays valid only if nobody has touched the file. Change a single pixel and the seal breaks. That's the point — it's how a verifier can say with certainty that "this file, byte for byte, is the one you signed."
You choose which layer (or both) with the Strength picker. Both is the recommended default: it proves origin and flags tampering.
Verifying doesn't require any accounts or downloads
Anyone with the app (or the CLI, or eventually the browser verifier) can open a marked image and get an answer instantly, offline. The verifier reads out your public key from inside the image, checks the signature, and shows the result — a green banner if the signature holds, a warning if it doesn't. If they already have your identity in their local keyring, they see your name. If they don't, they see just the key's fingerprint.
That's the honest limit of any watermarking system: it can prove a file came from a specific key, but linking that key to your name still depends on you publishing your fingerprint somewhere trustworthy (your website, GitHub profile, Nostr, or eventually the built-in registry).
The .zwm sidecar answers "when?" 🟠 Beta
A signature proves who signed a file. It does not prove when. Without proof of time, a thief could strip your mark, re-mark the same image with their own key, and claim they were first.
That's what the optional .zwm sidecar is for. When timestamping is turned on, ZWatermark asks two independent Time Stamp Authorities (small servers whose only job is signing "yes, we saw this hash at this exact moment") to stamp the SHA-256 hash of your marked image. Their responses are archived in the sidecar file next to your image.
Then it goes further: it also submits the same hash to OpenTimestamps, which folds thousands of submitted hashes into a Merkle tree and publishes the tree's root into a Bitcoin block. About a day later, your image's existence is provably anchored to a moment in Bitcoin's history — a timeline no one can rewrite without redoing years of mining, which no one can afford.
Only the hash is sent. No pixels, no metadata, no identity information is transmitted.
⚠️ Beta status. The timestamping pipeline (write, sidecar archive, RFC 3161 + OpenTimestamps verify against live TSAs and Bitcoin block headers) works end-to-end and is covered by integration tests. But it hasn't been battle-tested against every real-world TSA quirk, network outage, or OpenTimestamps upgrade edge case yet. Treat a verified timestamp as strong evidence — not court-grade proof — for now. Bug reports welcome.
The whole point: nothing leaves your machine unless you say so
ZWatermark runs entirely on your computer. It doesn't phone home, doesn't gather analytics, doesn't need an account, doesn't upload your images. The only outbound network traffic happens when you click something that needs it: pressing Publish identity (planned), or leaving timestamps turned on (in which case only the file's hash goes to the TSAs you...