Security Whitepaper

How Dim Notes Protects Your Data

This document explains the technical mechanisms behind Dim Notes' encryption and security model. It is written for users who want to verify our claims rather than take them on faith. Last updated: April 2026.

1. Architecture Overview

Dim Notes uses a client-server architecture where encryption and decryption happen exclusively in your browser or app — never on our servers. The server stores only ciphertext it cannot read.

The data flow for a note looks like this:

Your device (browser / desktop app)
├─ Note body typed → AES-256-GCM encrypt (CEK, random IV)
├─ Note title typed → AES-256-GCM encrypt (CEK, random IV)
│ [only ciphertext leaves the device]
└─ POST /api/notes ─────────────────────────────────────────▶ Supabase DB
stores: encrypted_body
encrypted_title
body_iv, title_iv
word_count (number only)
timestamps, metadata
Your device (reading notes)
├─ GET /api/notes ◀─── server returns ciphertext ──────────── Supabase DB
└─ AES-256-GCM decrypt (CEK) → plaintext rendered in editor

The Content Encryption Key (CEK) lives only on your device while your session is unlocked. It is never sent to our servers in raw form. The server stores a copy of your CEK that has itself been encrypted with a key derived from your PIN — so even that stored copy is opaque to us.

2. Encryption Implementation

All encryption runs in the browser using the built-in window.crypto.subtle (Web Crypto API). We do not use any third-party crypto library. The algorithm is AES-256-GCM.

  • Algorithm: AES-256-GCM (256-bit key, authenticated encryption with additional data). GCM provides both confidentiality and integrity — a tampered ciphertext will fail to decrypt rather than produce garbage output.
  • IV (Initialization Vector): 96-bit (12 bytes), generated fresh from crypto.getRandomValues() for every encrypt call. IVs are never reused.
  • What is encrypted: Note title, note body, and file attachments. These fields leave your device only as ciphertext.
  • What is not encrypted: Folder names, tag names, note status labels (e.g. "draft"), color labels, word count (stored as a number), timestamps, and whether a note is pinned or archived. See Section 6 for the full breakdown.

File attachments are encrypted with the same AES-256-GCM scheme as notes, using the same per-account CEK, before being uploaded to cloud storage. The server stores the ciphertext bytes and an IV; it cannot read the file content.

3. Key Derivation & Storage

Dim Notes uses a two-key system: a Content Encryption Key (CEK) that encrypts your data, and a Key Encryption Key (KEK) that protects the CEK.

CEK — Content Encryption Key

A 256-bit random AES key generated once when you first set up encryption. This key encrypts all your notes and attachments. It is stored on our server only in wrapped (encrypted) form. We never see the raw CEK.

KEK — Key Encryption Key

Derived from your PIN on your device using PBKDF2-SHA-256 with 100,000 iterations and a 256-bit random salt. The KEK wraps the CEK before sending it to the server. The KEK itself never leaves your device and is never stored anywhere.

When you enter your PIN to unlock, your device derives the KEK locally, uses it to unwrap the CEK from the server, and holds the CEK in memory for the duration of your unlock session. When the session expires or you lock manually, the CEK is discarded from memory.

The PBKDF2 salt is unique per account and stored on our server alongside the wrapped CEK. The salt is not a secret — its purpose is to make pre-computation attacks (rainbow tables) infeasible, which it achieves regardless of whether the attacker has the salt.

4. Authentication Layers

Dim Notes has two separate authentication layers that operate independently.

Layer 1 — Account Login (Clerk)

Standard account authentication. Supports email + password, Google OAuth, Apple OAuth, and Microsoft OAuth. This layer controls who can access your account. Clerk manages session tokens via httpOnly cookies. Dim Notes never handles your OAuth provider credentials.

Layer 2 — Note Unlock (Encryption Gate)

A second gate that controls access to note content. Being logged in is not enough — you must also pass the unlock step before your notes are decrypted. This layer is independent of Layer 1; even if your account session is valid, a locked Dim Notes session hides all note content.

Unlock methods (you choose one at signup):

  • TOTP: Time-based one-time password via Google Authenticator or any compatible app. First unlock per session only.
  • Email OTP: 6-digit code sent to your registered email. First unlock per session only.
  • Biometrics + PIN: Device biometrics (fingerprint / Face ID) as primary; PIN as fallback. All unlocks.
  • PIN: 4–6 digit PIN set by you. Required alongside TOTP/Email OTP to derive the encryption key. Always available as a fallback.

Auto-lock: Your session automatically locks after a configurable period of inactivity (5 minutes, 15 minutes, 30 minutes, 1 hour, or Never). The default is 15 minutes. After the initial unlock, re-locking always requires your PIN or biometrics — not a new TOTP or email code — to avoid constant interruptions.

The unlock session is tracked as an HS256 JWT stored in an httpOnly, SameSite=Strict cookie. The cookie is inaccessible to JavaScript running on the page, which prevents XSS from stealing the unlock session.

Your PIN is the root secret for key derivation. TOTP and email OTP verify your identity but your PIN is also required alongside them during the first unlock, because the KEK is derived from the PIN. Without the PIN, the CEK cannot be unwrapped even with a valid TOTP code.

5. Recovery Codes

When you enable encryption, Dim Notes generates 10 single-use recovery codes in the format XXXX-XXXX-XXXX. These are the only way to recover your encrypted notes if you lose access to your PIN and your primary unlock method.

  • Each code independently encrypts a backup copy of your CEK using PBKDF2-derived keys with unique salts. The 10 backups are stored on our server.
  • Using a code decrypts its CEK backup and immediately marks the code as consumed. It cannot be reused.
  • We store a scrypt hash of each code for verification. We cannot reverse the hash to recover the original code.
  • Recovery codes are presented to you once at setup. If you lose them without saving copies, they are gone.
  • You can regenerate your recovery codes at any time. Regeneration creates a new set of 10 codes and invalidates all previous ones.
  • We cannot reset your PIN, restore your recovery codes, or recover your encryption key. This is intentional — it means a server breach cannot compromise your data.
If you lose your PIN and all 10 recovery codes, your encrypted notes are permanently unrecoverable. Not by you, not by us. Save your recovery codes somewhere safe — a password manager, printed paper, or offline storage. This is the trade-off of true end-to-end encryption.

6. Zero-Knowledge Architecture

"Zero-knowledge" means we designed the system so that our servers cannot read your note content, even if compelled to by law enforcement, even if our database is breached.

We cannot read

  • Note titles
  • Note body content
  • File attachment contents
  • Folder names
  • Tag names
  • Your raw PIN or recovery codes
  • Your encryption key (CEK)

We can see

  • Your account email (via Clerk)
  • Note count and storage usage
  • Word count (a number, not content)
  • Timestamps (created/updated)
  • Status labels (e.g. "draft")
  • Color labels
  • Whether notes are pinned or archived

Folder and tag names are encrypted using the same AES-256-GCM scheme as note content. They are decrypted client-side after you unlock your notes. While locked, folder and tag names are not visible — even on your own device.

When law enforcement presents a valid court order, the only data we can produce is what is in the "We can see" column above. Note content is inaccessible to us and cannot be handed over regardless of legal process.

7. What We Don't Do

  • No AI processing of your notes. Your note content never touches a language model or any AI service.
  • No analytics on note content. Usage analytics (PostHog) track app-level events like "note created" — never what is inside a note.
  • No advertising, no ad networks, no tracking pixels.
  • No selling data. We are a subscription product. Our revenue comes from you, not from your data.
  • No third-party access to note content. Our infrastructure vendors (Supabase, Vercel, Cloudflare) receive only the encrypted ciphertext stored on their hardware — the same blobs we cannot read.

8. Known Limitations

We believe honesty about limitations is more useful than pretending they don't exist.

  • Metadata is visible. Note count, storage usage, word count, timestamps, status labels, color labels, and whether notes are pinned or archived are stored in plaintext. This reveals usage patterns even without access to content.
  • Not open source (currently). Dim Notes is built and maintained by a solo developer. The codebase is not yet public. The encryption implementation in lib/crypto.ts uses standard Web Crypto API calls that can be independently verified by inspecting the JavaScript bundle in your browser's DevTools. We plan to open-source the repository after launch stabilizes.
  • PIN strength matters. The security of your encryption depends on the strength of your PIN. A 4-digit PIN has 10,000 possible values. PBKDF2 with 100,000 iterations makes brute-force slow, but a longer PIN or using a random one is stronger. We recommend at least 6 digits.
  • Biometrics are device-local. Biometric unlock does not change the underlying cryptography — it is a convenience gate that, on success, uses a stored PIN to derive the KEK. The PIN still underpins the encryption.

9. Threat Model

A threat model is a statement of what a security system does and does not protect against. Being specific about this is more useful than vague assurances.

Protected against

  • Server breach / database dump: Attackers who steal our database get ciphertext they cannot decrypt without your PIN.
  • Insider access: Dim Notes staff, contractors, or infrastructure providers cannot read note content. The server never holds the raw CEK.
  • Legal requests for note content: A court order served on Dim Notes or our infrastructure providers cannot produce plaintext note content — we do not have it.
  • Network interception: All client-server communication uses TLS. Even without E2E encryption, this would protect data in transit. With E2E, intercepted requests contain only ciphertext.
  • Cross-site scripting stealing note content: Note content is decrypted only when the unlock session is active. Even if an XSS attack runs on the page, it cannot access the unlock JWT (httpOnly cookie) and the CEK is held in memory only.

Not protected against

  • Compromised device: If an attacker has physical or remote access to your unlocked device, they can read your notes — the same way they could read anything else on your screen. Device security is outside the scope of Dim Notes.
  • Keyloggers: A keylogger on your device captures your PIN before it reaches the crypto layer. Dim Notes cannot detect or prevent this.
  • User error: Sharing your PIN, losing all recovery codes, or being socially engineered into providing credentials. We cannot protect against voluntary disclosure.
  • Malicious browser extensions: A malicious extension with broad page access could read DOM content or intercept decrypted text. Use a trusted browser environment.
  • Account takeover (Clerk): If an attacker gains access to your Layer 1 account (email + password), they can initiate an unlock attempt. They still need your PIN, but account security is the first line of defense.

Questions about our security model? security@dimnotes.com

This document is updated when the security implementation changes. Effective April 2026.

We use analytics to improve Dim Notes. Your notes are never included.