Skip to content

Encryption

Your notes are encrypted in your browser before they are sent. Cloudflare stores ciphertext and wrapped keys, and cannot read either.

  • A random 256-bit data key (DEK) encrypts every note.
  • Your passphrase is stretched with Argon2id into a key that wraps the data key.
  • Your recovery code is turned into a second key that wraps the same data key.

Either secret can unwrap the data key. That is why the recovery code can rescue your notes, and why changing the passphrase doesn’t re-encrypt anything.

Encrypted (inside the ciphertext) Plaintext (so notes can be sorted)
Title pinned
Body archived
Labels trashed_at
Color position and timestamps
  • Your passphrase, the data key and note content never leave the browser unencrypted.
  • In a session the data key is a non-extractable CryptoKey kept in memory only. Locking discards it.
  • The offline copy on your device holds the same ciphertext and wrapped keys as the server. Signing out deletes it.
  • Each note’s ciphertext is bound to its id, so the server can’t swap content between notes.
  • The client rejects Argon2 parameters below a safe floor, so a malicious server can’t downgrade the key derivation.
  • The Worker verifies the Cloudflare Access JWT itself (signature, issuer, audience) instead of trusting headers.
  • A strict Content Security Policy ships with the app. The Markdown renderer escapes raw HTML and drops executable URLs.
Step Algorithm
Passphrase → key-encryption key Argon2id (64 MiB, t=3, p=1)
Recovery code → recovery key HKDF-SHA256
Wrapping the data key AES-256-GCM
Each note AES-256-GCM with a random 96-bit IV and AAD note:<id>