Skip to content

vcondriuc/Secret-Notes

Repository files navigation

Secret Notes — MVP

Zero‑knowledge note sharing. Encryption happens in the browser (AES‑GCM); the server stores ciphertext only. The URL looks like https://host/n/{id}#k=base64url(key) — the key stays in the URL fragment.

Quick Start

  1. Install dependencies
npm i
  1. Run in dev mode
npm run dev

Open http://localhost:3000

  1. Production build
npm run build
npm start

Architecture

  • Client

    • Generates a random 256‑bit noteKey (WebCrypto).
    • Optional user password → PBKDF2(SHA‑256, 310k, 16‑byte salt) → passKey.
    • Final CEK = SHA‑256(noteKey || passKey), or just noteKey if no password.
    • Encrypts the note with AES‑GCM (12‑byte IV). Sends to server: ciphertext, nonce, optional salt, and metadata.
    • Shareable link: /n/{id}#k=base64url(noteKey). Password must be shared separately.
  • Server

    • Stores notes table (SQLite via better‑sqlite3).
    • Endpoints:
      • POST /api/notes — create a note.
      • GET /api/notes/:id/meta — read metadata (does not consume a view).
      • POST /api/notes/:id/consume — get ciphertext and decrement views/burn.
    • Cleans up expired notes every 10 minutes.
    • Security headers: CSP, HSTS, Referrer‑Policy: no-referrer.
    • Rate limiting: 60 requests/min per IP for /api/*.

Parameters

  • Expiration: default 24 hours, up to 30 days.
  • Burn after read: delete on the first consume.
  • View limit: if reached, note is deleted on consume.
  • Extra password: client‑side only; server stores salt only.

Security Notes

  • The server never sees the key or the password.
  • URL fragment (#k=...) is not sent to the server; Referrer‑Policy prevents leaks.
  • AES‑GCM with 96‑bit IV; key length is 256‑bit.
  • PBKDF2 is used temporarily for the MVP. Argon2id is recommended long term.

Migrating PBKDF2 → Argon2id (post‑MVP)

  1. Add Argon2id in the browser (e.g., argon2-browser or @noble/argon2 when stable).
  2. In deriveCombinedKey:
    • passKey = Argon2id(password, salt, { t=3, m=64MB, p=1, hashLen=32 })
    • combined = HKDF‑SHA256(ikm = noteKey || passKey, salt = '' , info = 'secret-notes', len = 32)
  3. Mind CSP: you may need wasm-unsafe-eval and/or a worker.

MVP Limitations

  • “Burn after reading” happens at consume, not after successful decryption (the server cannot know decryption outcome).
  • If the password/key is wrong, a view is still consumed. The user is shown an error.

Contributing

Feel free to submit a pull request or open an issue if you have any suggestions or improvements.

Buy Me A Coffee

About

Zero‑knowledge, end‑to‑end encrypted notes. AES‑GCM in your browser; server stores ciphertext only. One‑time links and optional password.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors