Case StudiesProductsBlogOpen SourceBook a call

CryptPad's URL Trick Is Genius

CryptPad stores the shared encryption key in the URL fragment, the part after the `#`. That one choice solves a whole class of secure-sharing problems.

While revisiting CryptPad's architecture recently, something finally clicked.

CryptPad stores the shared encryption key in the URL fragment, the part after the #. That one choice solves a whole class of secure-sharing problems.

It turned out to be the missing piece I needed to safely create invite links with shared keys.

Why the # matters

Anything after # in a URL is never sent to the server. The browser keeps it entirely client-side.

That means the server can host and sync encrypted data without ever seeing the key used to decrypt it. The trust boundary is clean and enforced by the platform itself, not by policy or convention.

In CryptPad's case, the server only knows about a document ID. The browser extracts the key locally and does the decryption on its own.

Secure sharing without gymnastics

Before fully internalizing this pattern, invite links always felt risky. If a key is passed through a request or stored server-side, you're constantly guarding against leaks.

The fragment approach flips that model.

You can share a link like:

https://example.com/doc/abc123#<shared-secret>

The server handles availability. The client handles secrecy. Possession of the link is possession of the key, nothing more and nothing less.

Where it still needs care

The fragment stays out of request logs, but it does not stay out of everything. It lands in browser history, it rides along in Referer headers on older browsers unless you set a referrer policy, and any script on the page can read location.hash. A link pasted into a chat app is a key pasted into a chat app.

The guarantee is specific: your server never sees the key. Everything between the sender and the recipient's browser is still your problem.

The piece I was missing

I've spent a lot of time working on encrypted and local-first systems. I had solid key management, device trust, and encryption primitives in place.

What I didn't have was a simple, human-shareable invite mechanism that didn't weaken the system.

CryptPad's approach made it obvious: an invite link can just be a pointer plus a secret, as long as the secret never leaves the client.

No server trust. No invite state. No extra protocol.

Elegant in the best way

What I love about this design is how unremarkable it is.

It uses standard URLs, well-understood browser behavior, and clear boundaries. No new crypto, no clever hacks, just a small decision with big consequences.

It's the kind of idea that feels obvious in hindsight and transformative once you really see it.

Credit where it's due

CryptPad doesn't just promise privacy. Their architecture enforces it.

That tiny # is doing an enormous amount of work, and it deserves recognition. It unblocked a major design problem for me, and if you're building encrypted, shareable tools, it might unblock one for you too.

This remind you of a problem you've been dealing with?

I'd be happy to discuss it with you and see if it's something we could turn into a solution.

Book a call

Newsletter

Subscribe to my newsletter to be the first to hear about what I do next