[READ-ONLY] Mirror of https://github.com/thoda-dev/shhh. Self-hostable zero-knowledge pastebin for secrets that expire on their own
docker end-to-end-encryption nuxt nuxtjs pastebin secrets selft-hosted zero-knowledge
shhh apps docs content 1.getting-started 1.introduction.md
3.3 kB
Markdown


title: Introduction description: What shhh is, what it deliberately is not, and how the encryption works. navigation: icon: i-lucide-info #

Most "send me the password" moments end in a chat message that stays there forever. shhh is for the other path: paste a secret, get a link, and have it disappear after a set number of reads or a deadline — without trusting the server with the contents.

How the encryption works #

Everything happens in the browser, before anything is sent.

  1. The browser generates a random 256-bit key.
  2. It encrypts your text or file with AES-256-GCM using that key.
  3. It sends only the ciphertext and an initialisation vector to the server.
  4. The link you get back carries the key in its fragment — the part after #.
https://shhh.example.com/p/8f3c…#key=Ux7…
                        └─ sent to the server ─┘ └─ never sent ─┘

Browsers do not transmit the fragment in HTTP requests. The server receives the paste id, looks up the ciphertext, and hands it back. It has no way to decrypt it — and neither would anyone who obtained a dump of the database.

::note Filenames are encrypted too, with a separate initialisation vector. MIME types are stored in clear so the browser knows how to hand the file back to you. ::

Optional password protection #

You can add a password on top. It derives a second key with Argon2id (OWASP interactive parameters), salted with the fragment key itself. Both the password and the link are needed to decrypt — the server never sees the password and only records that one is required.

::note A wrong password costs nothing. Your browser proves it derived the right key by sending a SHA-256 of it, which the server checks in the same statement that spends the read — so a mistyped password is refused before the counter moves. The server still never sees the password itself. ::

The two tiers #

Anonymous Signed in
Encryption Zero-knowledge Zero-knowledge
Content Text only Text and file uploads
Password protection Yes Yes
Default max retention 7 days 30 days
Track your pastes No Yes, from a dashboard
Share by email Client-side mailto: Server-side, at creation

Anonymous stays deliberately minimal: no account, no follow-up, no management link. Counters and history are features of the signed-in tier.

What shhh is not #

  • Not a team secret manager. Multi-tenancy and organisation-shared vaults were evaluated and dropped. shhh is a pastebin with counters, not a Vault or Infisical replacement.
  • Not a file host. Uploads are capped (2 MB by default), stored in PostgreSQL, and expire like everything else.
  • Not protection against a malicious operator. A modified server could serve altered JavaScript. Self-hosting the instance you trust is the answer.

Next #

::card-group :::card #

icon: i-lucide-container to: /self-hosting/installation #

#title Install it

#description Docker Compose, environment variables, first run. :::

:::card #

icon: i-lucide-shield to: /self-hosting/security #

#title Security model

#description What the server can see, and the one deliberate exception. ::: ::