Server-side vs end-to-end encryption for secret links
What server-side and end-to-end encryption each protect against, how ShareShield's server-side envelope encryption works, and what to use if you need E2E.
On this page
ShareShield encrypts secrets on its servers, not in your browser. We hold the keys, so an attacker who gained control of our servers, or someone at ShareShield with production access, could read a secret that hasn’t been opened yet. End-to-end tools, where your browser encrypts the secret and the key travels only inside the link, remove that risk. They don’t remove the others.
For most handovers, the risks that actually cause leaks (a forwarded email, a link pasted into the wrong chat, malware on a laptop) are the same under both models. This page sets out what each model protects against, exactly how ShareShield’s encryption works, why we chose it, and what we’d recommend if your threat model rules us out.
The two models
Server-side encryption. Your browser sends the secret to the server over TLS. The server encrypts it before storing it and decrypts it when the link is opened. The provider holds the keys.
End-to-end encryption (often sold as “zero-knowledge”). Your browser generates a key, encrypts the secret and uploads only the ciphertext. The key goes in the link’s fragment, the part after #, which browsers don’t send to the server. The recipient’s browser decrypts it. The provider never holds the key, but it does serve the JavaScript that does the encrypting, fresh, every time someone visits.
What each one protects against
| Threat | Server-side (ShareShield) | End-to-end |
|---|---|---|
| Recipient's mailbox compromised before the link is opened | Not protected. Whoever has the link can open it. A passcode sent by another channel helps. | Not protected, for the same reason: the link carries the key. |
| Link intercepted in a chat log, proxy log or screen share | Not protected if the interceptor opens it first. The real recipient then sees that it has already been viewed. | Same, with one edge: the key in the fragment doesn't appear in proxy or server logs. |
| Provider's database or backups stolen | Protected while the key-encryption keys, held outside the database, stay safe. Exposed if they are stolen too. | Protected. The thief gets ciphertext without keys. |
| Attacker running code on the provider's servers | Exposed. They can read secrets as they are created and opened. | Partly protected. Stored ciphertext is safe, but the attacker can change the JavaScript served to the next sender or recipient and capture their keys. |
| Malicious insider at the provider | Exposed in principle to anyone with access to both the database and the keys. | Mostly protected. An insider would have to ship modified code, which is harder to do quietly. |
| Legal demand served on the provider | Secrets not yet opened, burned or expired could be disclosed. Metadata, such as when a secret was opened, exists. | Only ciphertext and metadata can be handed over, unless the provider is compelled to change its code. |
| Malware or a malicious browser extension on either device | Not protected. | Not protected. The secret is on screen in plaintext either way. |
End-to-end encryption wins clearly in two rows: a stolen database, and the people who run the service. Everywhere else, the outcome depends on things neither model controls: how long the link lives, whether the recipient opens it promptly, and the state of the devices at each end.
How ShareShield’s encryption works
This is what the code does, not a summary of intent.
- A key per secret. Every secret gets a fresh random 256-bit data key. The secret, text or file, is encrypted with AES-256-GCM under that key, with a random 96-bit nonce and a 128-bit authentication tag.
- Envelope encryption. The data key is itself encrypted (wrapped) with AES-256-GCM under a key-encryption key from a keyring that is not stored in the database. The database holds the ciphertext, the wrapped data key and the id of the key-encryption key that wrapped it. The unwrapped data key is zeroed in memory as soon as it has been used.
- Binding. The secret’s record id and the key id are bound into both layers as additional authenticated data. Ciphertext or a wrapped key copied onto another record fails to decrypt, rather than opening as someone else’s secret.
- Rotation. A new key-encryption key is added to the keyring and made active. New secrets use it; older ones keep decrypting under the key that wrapped them. Nothing is re-encrypted in bulk, and because the longest expiry on any plan is 90 days, a retired key stops protecting live data within 90 days.
- Deletion. Opening a secret takes exactly one view in a single atomic step, and the last permitted view deletes the stored ciphertext in the same database transaction (a file held in blob storage is deleted straight after it commits). Burning a link deletes it too, whether the owner burns it, the recipient uses their burn link, or five wrong passcodes destroy it. An expired secret stops opening at its expiry time, and its ciphertext, including any file in blob storage, is deleted by a scheduled sweep. The secret’s record (label, status and timestamps) stays in the owner’s history. The content does not.
Two further facts belong here. The secret exists in plaintext in our application’s memory while it is being encrypted and again when it is revealed. And our database, like any managed database, is backed up, so the ciphertext of a deleted secret can survive in a backup until that backup ages out, still wrapped under its key-encryption key.
Why we chose server-side
The honest version is that a few features need the server to handle the plaintext, and several more are much simpler and harder to get wrong if it does.
- Emailing recipients. ShareShield can email a link to up to ten people and tell you when it’s opened. A server that sends the link knows the link. In an end-to-end design the key would have to be in that email, so the server would see it anyway.
- Secret requests. You send someone a form and what they type arrives in your account. End-to-end, your browser would need a private key that it keeps for as long as the request is open, and a lost or cleared browser would lose the secret.
- A plain API. A deployment script can send a secret over HTTPS and get a link back, with no client-side cryptography library to integrate or get wrong.
- Server-enforced passcodes. Passcodes are checked by the server, which destroys the secret after five wrong attempts. In most end-to-end designs the passcode becomes part of the key, so anyone who obtains the ciphertext can try passcodes offline at their own pace. The flip side: our passcode is an access check, not part of the encryption, so it adds nothing if our keys are stolen.
Some things work equally well under either model. View limits, expiry, organisation policies and the audit log deal in metadata, not content. They’re not a reason to choose server-side encryption, and we won’t present them as one.
If your threat model needs end-to-end encryption
If you need protection from the provider itself, including us, use a tool that encrypts in the browser:
- Bitwarden Send or 1Password’s item sharing, if your team already uses either. Both encrypt on the device and put the key in the link.
- Yopass or PrivateBin, open-source tools that encrypt in the browser. Run them on your own infrastructure and the provider drops out of the threat model altogether, because the provider is you.
- age or GPG for files exchanged between people who are comfortable managing keys.
Whichever you choose, the habits that matter are the same as with ShareShield: send the link and any passcode by different channels, keep the expiry short, and treat a link that says it has already been opened as a leaked credential that needs changing.
If what worries you is the inbox, the chat history or the laptop, end-to-end encryption won’t change your exposure. A one-view link with a short expiry, a passcode delivered separately and prompt rotation will. Our guide to one-time links and password managers covers where links fit alongside a vault.
Send the next one as a link that expires.
ShareShield turns a password, key or file into a link that opens once and is then deleted. You can send a text secret without an account.
