How OncePad keeps a secret

Encryption, threat model, and what the server can and cannot see

The short version

When you press Encrypt & create link, your browser encrypts the secret and uploads only the ciphertext. The server stores that opaque blob in memory under a random id. The recipient opens the link, types the passphrase, and their browser decrypts it — the server hands the ciphertext over exactly once and deletes it in the same atomic step. OncePad is end-to-end encrypted, one-time, and ephemeral by construction, not by policy.

Encryption happens in your browser

Secrets are encrypted with AES-256-GCM using the browser's built-in Web Crypto API. The key is derived from a passphrase with PBKDF2-HMAC-SHA256 at 600,000 iterations and a fresh random salt per secret; a fresh key protects every secret. The passphrase is generated, not typed: 7 words drawn uniformly from the EFF wordlist (about 72 bits of entropy), which puts offline brute force against a stolen blob out of reach. The wire format is frozen and versioned, and the crypto library is exercised against fixed test vectors on every build.

Two channels: a key-less link and a spoken passphrase

Many one-time-secret tools put the decryption key in the URL, so whoever sees the link can read the secret. OncePad's link carries no key — it is only an address — so it can be pasted into email, Slack, or a ticket. The passphrase travels on a separate channel: a text, a call, said out loud. An attacker who captures one channel has nothing; the design assumes at least one of the two stays private. The web client never issues key-in-URL links and refuses to open one.

What the server stores — and what it never sees

Stored, in RAM only: a random id, the opaque ciphertext blob (up to 64 KB), a SHA-256 hash of the one-time management token, and an expiry. Never present on the server: your plaintext, the key, or the passphrase. The server is crypto-agnostic — it relays one blob it cannot parse. There is no database and nothing is written to this server's disk; a restart destroys every live secret. Client IP addresses are used transiently for rate limiting and abuse control and are never linked to a secret; request logging is compiled out of production builds because the request path contains the secret id.

Files

A file is encrypted the same way a message is — in your browser, under the same generated passphrase — and its name and type are encrypted with it, so neither we nor our storage provider ever learn what you sent or what it was called. The encrypted file goes straight from your browser to the storage bucket; it never passes through this server, which only ever learns how large it is and when it arrived.

Files are stored as encrypted blobs in Cloudflare R2 under random names unrelated to your link. Cloudflare acts as our processor: it holds ciphertext it cannot read, and sees the connecting IP address, the size, and the timing — never the contents, the key, the passphrase, or the filename. Because a third party is involved at all, file sharing is a separate, optional part of this service.

One redemption, then deletion. The link opens exactly once: one visitor wins it, and everyone after them finds it gone. That visitor gets a short-lived download address that works only for a few minutes — they already hold the file, so this changes nothing for them, but it is a slightly weaker promise than the message path's single atomic read, and we would rather say so than round it up. The encrypted file is then actively deleted, usually within minutes; a storage lifetime rule removes anything that active deletion could not reach.

One read, then gone

Reveal is an atomic remove-and-return in the store, so a secret can be read exactly once even under concurrent requests. Unopened secrets expire after 24 hours. Opening the link shows a non-destructive page that asks for the passphrase — link previewers, prefetchers, and security scanners cannot burn a secret; only the recipient pressing Decrypt & Reveal does. If you sent something by mistake, Erase it now revokes it before anyone opens it.

Threat model

Protects against: a curious or compromised server (it holds only ciphertext under a strong passphrase); a breach of the channel that carried the link (no key in it); a breach of the channel that carried the passphrase (no ciphertext in it); replay (the blob is gone after one read); and a stolen ciphertext (offline guessing at ~72 bits and 600k PBKDF2 iterations is impractical).

Does not protect against: someone who obtains both the link and the passphrase before the recipient; malware or a keylogger on either endpoint; a recipient who copies the secret somewhere insecure; or an origin that has been compromised to serve different JavaScript. The last risk is reduced — not eliminated — by Subresource Integrity on every script and a strict Content Security Policy.

Browser hardening

Every page ships a strict CSP (default-src 'none'; script-src 'self') with no inline executable scripts and no remote JavaScript; all three scripts — the crypto library, the page driver, and the theme bootstrap — are self-hosted and SRI-pinned, so a tampered file is refused by the browser. Referrer-Policy: no-referrer keeps capability URLs out of outbound request headers. Fonts and icons are self-hosted; there are no cookies, ad pixels, or third-party analytics. Public visits carrying utm_source=chatgpt.com increment one anonymous aggregate counter in server memory; no URL, IP, referrer, user agent, or timestamp is retained. Only your light/dark preference is kept in your browser.

Small by design

OncePad is a single small service with no database, no accounts, no background jobs, and no build step — the JavaScript the browser runs is the exact file served, pinned by hash. Less machinery means less to break and less to attack, and every secret is gone from memory the moment it is read or expires.

Published evidence and audit status

The versioned encryption format and conformance test vectors are the same artifacts shipped with and exercised against the browser crypto bundle. The threat model above states both protections and limitations. OncePad has not yet completed an independent third-party security audit; when one is completed, the report and remediation status will be published here rather than implied in marketing copy.

Reporting a vulnerability

Please report security issues privately to security@oncepad.com; read the public vulnerability disclosure and safe-harbor policy or security.txt (RFC 9116). Abuse or takedown notices go to support@oncepad.com as described in the terms.

Share a secret