Security

Encrypted pastes are encrypted in your browser before anything is sent. The server stores ciphertext and never receives your password.

This page describes exactly how that works, and — just as importantly — what it does not protect you from.

Parameters

CipherAES-256-GCM (authenticated encryption)
Key derivationPBKDF2 with SHA-256
Iterations310,000 (OWASP 2023 recommendation)
Key length256 bits
Salt16 bytes, randomly generated per paste
Initialisation vector12 bytes, randomly generated per paste
Stored formatbase64(salt ‖ iv ‖ ciphertext)
Randomnesscrypto.getRandomValues (Web Crypto API)

What happens when you encrypt

You enter a password. The browser generates a random 16-byte salt and runs PBKDF2-SHA256 over your password for 310,000 iterations to derive a 256-bit key. The iteration count is deliberate cost: it makes each guess in a brute-force attempt expensive.

A random 12-byte initialisation vector is generated, and the content is encrypted with AES-256-GCM. GCM is an authenticated mode, so decryption fails loudly if the ciphertext has been altered rather than returning corrupted output.

The salt, IV and ciphertext are concatenated, base64-encoded, and sent to the server. The password is not sent. The derived key is not sent. Neither is stored anywhere.

What the server stores

Every paste is one database row with four fields:

  • an id and an eight-character public id used in the URL
  • the content — Brotli-compressed for normal pastes, ciphertext for encrypted ones
  • a flag marking whether it is encrypted
  • a created-at timestamp

There is no IP address, no user agent, no account, no email and no author field. Not as a policy that could change — those columns do not exist.

What this does not protect against

A weak password. 310,000 PBKDF2 iterations raise the cost per guess; they do not save a password that appears in a wordlist. The strength of an encrypted paste is the strength of the password you chose.

Losing the password. There is no recovery, no reset and no back door. If it is lost, the content is unrecoverable — that is the design working, not failing.

Unencrypted pastes. A normal paste is compressed, not encrypted. Anyone with the link can read it, and so can the server. The URL is eight characters from a 36-character alphabet — about 2.8 trillion combinations, which is impractical to guess but is obscurity, not access control.

A compromised browser or page.Encryption happens in your browser, so it inherits your browser's security. Malware or a malicious extension that can read the page can read the content before it is encrypted.

Remembered passwords.Choosing to remember a password stores it in that browser's localStorage in readable form. It is convenient and it is a tradeoff; anyone with access to that browser profile can read it. There is a “forget” control for this reason.

Pastes are not deleted automatically. Expiry is on the roadmap but not built. Today a paste persists until removed.

Verifying this yourself

Do not take a security page at its word. The encryption is about a hundred lines in src/lib/crypto.ts, and the whole project is open source — read it, or watch the network tab while you create an encrypted paste and confirm the request body contains nothing but ciphertext.

Create an encrypted paste

Pick a strong password, share the link, and the content stays readable only to whoever has that password.