The honest crypto design: what we can't see, and why we say so
The honest crypto design: what we can't see, and why we say so
There's a claim you see constantly in link-shortener and pastebin marketing: "zero-knowledge and we check every link for safety." It sounds good. It is also impossible, and this article is about why we refuse to say it.
The tension is real
The logic is short:
- Zero-knowledge of a datum means the service cannot read it.
- Destination verification requires the service to read the
- Therefore any design claiming full zero-knowledge and server-side
destination — follow its redirect chain, inspect its content, score its host.
verification of the same URL is lying.
We resolve this the only honest way: split the data, not the slogan. There are two data classes with different rules, and we state both plainly.
What we encrypt (and the verifier never touches)
Link ownership and account data — who created which link, sessions, the mapping between a destination and a user — is encrypted at rest. And the important part: the verification pipeline never touches it. The verifier receives only the destination blob plus a job nonce, and returns a verdict plus a chain report. No user id, no account handle, no email flows through verification.
Why this matters: a breach of verification logs cannot map destinations back to users, because the mapping was never there. Identity and destination are separated by architecture, not by policy.
What we must see (and don't pretend otherwise)
Destination URLs: the service must see them. Verification and the redirect itself require plaintext inside the Worker isolate. We do not claim zero-knowledge here. We claim minimum-knowledge:
- AES-256-GCM at rest, per-link random 96-bit nonce, key held as a
- Decrypted only inside the Worker isolate at the moment of use
- The owner sees their own links' destinations; nobody else does. The
Worker secret.
(creation, verification, redirect); never written to logs, never exported in bulk.
list API never returns destinations except to the owning account on the detail route.
And we explicitly do not claim end-to-end encryption of destinations between creator and visitor. That's impossible with server-side verification, and anyone who tells you otherwise is selling you the impossible claim from the first paragraph.
What we don't store — the actual trust case
The strongest privacy statement isn't about encryption. It's about what never exists in the first place:
- No redirect access logs with visitor IPs. None. Rate limiting uses
- No user agents, no referrers, no per-visitor anything. Click counts
- Sessions store token hashes, never raw tokens. Magic-link tokens
ephemeral sliding-window counters that expire in minutes.
are aggregate counters only. We cannot tell you who clicked your link, because we never recorded it.
are single-use with a 15-minute expiry; we couldn't replay one if we wanted to.
You can't leak what you never collected, and you can't be subpoenaed for it either.
The threat model, stated plainly
This design protects against:
- D1 theft — backups, SQL dumps, stolen credentials at the database
- Log leakage. There is no plaintext destination in any log, because we
- Insider curiosity. No dashboard shows plaintext destinations except the
- Traffic analysis by outsiders. Verification is identity-separated, so
layer. Destinations are encrypted; sessions are hashes.
never write one.
owner's own links.
watching the verifier teaches you nothing about who created what.
It does NOT protect against:
- A compromised Cloudflare account. Whoever controls the Cloudflare
account can read Worker secrets, including the master encryption key. This is the honest boundary of every Cloudflare-hosted system that encrypts at the application layer, and we say it outright on our security page because a threat model with no "does not protect against" section is a brochure, not a threat model.
The path to stronger
For the enterprise tier, the plan is per-customer key-encrypting keys: customer-held KEKs via envelope encryption, so a Cloudflare-account compromise of our account no longer decrypts your destinations. The schema already reserves the key-version column, so this needs no redesign — it's a key-management upgrade, not an architecture change.
Why honesty is the differentiator
CISOs don't buy "zero-knowledge" marketing. They buy a precise statement of what the vendor can and cannot see, with the code and the data-flow documentation to back it. The vendors who handwave the ZK-vs-verification tension are hoping you won't notice the contradiction. We noticed it first, and we built the architecture around it in the open.
Read the security page for the data-flow diagram, the retention table, and the full threat model — or open any link's trust report at linktary.com/v/<code> and see the verification side for yourself.