cinderpaste

How cinderpaste Works

cinderpaste uses browser-side encryption so the server never sees your plaintext. Here's the whole journey of a paste, from the moment you type it to the moment someone reads it — in four steps.

  1. 1. Type your text

    You write or paste your secret into the editor. Nothing has been sent anywhere yet — it's all still in your browser tab.

  2. 2. Choose expiration

    Pick how long the paste should live and whether it should burn after reading. Optionally set a passphrase for a second factor.

  3. 3. Share the link

    Your browser encrypts the text and uploads only the ciphertext. You get back a link with the decryption key stored in the URL fragment after the # symbol.

  4. 4. Recipient decrypts

    When someone opens the link, their browser reads the key from the fragment and decrypts the paste locally. The server never touches the key.

Under the hood

Encryption uses AES-256-GCM through the Web Crypto API — a fast, authenticated cipher that's built into every modern browser, so there's no third-party crypto library to trust.

For password pastes, the key is derived with PBKDF2-SHA256 over 600,000 iterations and a random 16-byte salt, which makes brute-forcing a weak passphrase expensive.

The magic is the URL fragment. Everything after the # in a link is never sent to the server by the browser. That's where cinderpaste keeps the decryption key, so the key travels with the link but never reaches us.

Illustrative example

// Illustrative — runs entirely in the recipient's browser
const key = keyFromUrlFragment(location.hash);   // never sent to the server
const { ciphertext, iv } = await fetch(pasteUrl).then(r => r.json());

const plaintext = await crypto.subtle.decrypt(
  { name: "AES-GCM", iv },
  key,
  ciphertext,
);

A simplified sketch of what your browser does — not the exact implementation.