Write freely.
The server can’t read it.
Obscura encrypts every note in your browser before it leaves your device. The server stores ciphertext only: no keys, no plaintext, no way in, even with full database access.
Open source and self-hostable, so the privacy is verifiable.
Q3 plan: the privacy bet
Competitors can’t match our model without giving up server-side access. Lead with that.
9f3a2c8e0d1b4a7f5e2c9d6b3a0f7e4c1d8b5a2f9e6c3d0b7a4f1e8c5d2b9a6f3e0c7d4b1a8f5e2c9d6b3a0f7e4c1d8b5a2f9e6c3d0b7a4f1e8c5d2b9a6f3e0c7d4b1a8f5e2c9d6b3a0f7e4c1d8b5a2f9e6c3d0b7a4f
Without your password, this is just bytes.
- EncryptionAES-256-GCM
- Key derivationPBKDF2 · SHA-256
- Iterations600,000
- Keys heldClient-side only
- SourceFully open
The threat model
“End-to-end encrypted” means very little if the server holds your keys.
Most note apps encrypt in transit and at rest, then keep a key on the server to power search, sync, or recovery. That means a breach, a subpoena, or an insider can turn your notes into plaintext. Obscura is built so the key is never on the server at all.
- Notes encrypted in transit (TLS)Obscura
- Notes encrypted at rest on the serverObscura
- Server never holds the decryption keyObscura
- Stays secret if the full database leaksObscura
- Stays secret under a subpoena or admin accessObscura
- You can read the code that does all thisObscura
The difference is structural, not promotional: because your master key is derived from your password and never leaves the browser, the server physically cannot decrypt your notes.
The chain
From thought to ciphertext, four steps.
Your password never leaves your device. Here is the exact path a note takes, the same path you can read in the source.
- 01
You type a password
It never leaves your browser. PBKDF2 derives a key from it using 600,000 iterations of SHA-256.
password → PBKDF2 → key - 02
It unlocks your master key
Your master key is stored encrypted on the server. The PBKDF2 key decrypts it, in memory, as a non-extractable CryptoKey.
wrapped key → decrypt → master key - 03
Each note is encrypted
AES-256-GCM with a fresh 12-byte IV per note, run entirely in the browser via the Web Crypto API.
note + key + IV → AES-GCM - 04
Only ciphertext syncs
The server stores opaque encrypted blobs. Even with full database access, your notes stay unreadable without your password.
ciphertext → server → just bytes
async function encryptNote(
content: string,
masterKey: CryptoKey
) {
// 12-byte initialization vector, fresh and random per note
const iv = crypto.getRandomValues(
new Uint8Array(12)
);
const encoded = new TextEncoder().encode(content);
// AES-GCM, entirely in the browser
const ciphertext = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
masterKey,
encoded
);
return { ciphertext, iv }; // only this leaves the device
}Open source
Privacy you can read, not just a promise.
The encryption layer, the client, and the server are all open source. Verify the cryptography yourself. This is the actual function that encrypts every note.
- AES-256-GCM encryption in the browser
- PBKDF2 key derivation, 600,000 iterations
- Fresh random IV per note
- Master key held as a non-extractable CryptoKey
- Zero server-side access to content
Self-host
Run it yourself, in minutes.
Because encryption never depends on the server, hosting it yourself doesn’t weaken anything. Same primitives, your infrastructure, your data.
$ git clone github.com/thepushkaraj/obscura
$ cd obscura
$ cp .env.example .env.local
# Add your Supabase credentials to .env.local
$ npm install && npm run dev
Running on http://localhost:3000
Your ideas deserve a private home
Start writing where no one else can read.
No tracking. No server-side keys. Free, open source, and encrypted by default.