AES-GCM and PBKDF2: How Your Net Worth Gets Encrypted in Your Browser
title: "AES-GCM and PBKDF2: How Your Net Worth Gets Encrypted in Your Browser" description: "A plain-English walkthrough of the crypto a local-first tracker uses: PBKDF2 key derivation, AES-256-GCM, and why the vendor can never read your vault." date: "2026-11-08" tags: ["privacy", "encryption", "local-first"]
When an app promises "military-grade encryption," the honest question to ask is: encrypted with whose key? If the vendor holds the key — or can compute it — then the encryption protects against outsiders, not against the vendor, and not against whoever breaches the vendor's database.
This article walks through the cryptographic design used by LocalVault, piece by piece, in plain English. It is the same design used by password-manager-grade tools, and every part of it runs inside your browser via the Web Crypto API.
The one-sentence version
Your master password is stretched into a 256-bit key, that key encrypts your entire vault with AES-256-GCM, and neither the key nor the plaintext ever leaves your device.
Now the longer version.
Step 1: Your master password becomes a key
A password is not a key. Human passwords have far too little entropy — even a good 12-character passphrase contains maybe 60 bits of unpredictability, while AES-256 wants a full 256-bit key.
PBKDF2 (Password-Based Key Derivation Function 2) bridges that gap by design: it hashes the password over and over, 600,000 iterations in LocalVault's case, salted with a random 16-byte salt stored alongside the ciphertext. Each login attempt on an attacker's hardware must pay the same 600,000-iteration cost, which turns cheap bulk password guessing into an expensive grind.
Two details matter more than the iteration count:
- The salt is random per vault. Two people with the same master password produce completely different keys, so attackers cannot precompute a rainbow table across users.
- The salt is not secret — and does not need to be. Its job is to defeat precomputation, not to hide the key.
The output is a CryptoKey marked non-extractable in the browser: the page can use it for encryption, but JavaScript — including any injected script — cannot read the raw key bytes.
Step 2: The vault is sealed with AES-256-GCM
AES-GCM (Galois/Counter Mode) is an authenticated encryption mode, and that second word is the important one. It provides two guarantees in a single pass:
- Confidentiality — nobody without the key can read the contents.
- Integrity — nobody can modify the ciphertext undetected. Flip one bit of tampered data and GCM's authentication tag fails to verify, and the decryption call simply throws.
That integrity property is why GCM is the default recommendation over older modes like CBC, which encrypts but does not authenticate.
Mechanically, each save works like this:
- A fresh random 12-byte initialization vector (IV) is generated per encryption. Reusing an IV with the same key is the one fatal mistake in GCM — a fresh random IV per operation avoids it.
- The IV is stored in the clear next to the ciphertext. Like the salt, it is not a secret.
- Your vault — assets, liabilities, subscriptions, everything — is serialized, encrypted, and written to IndexedDB as an opaque blob.
Step 3: What the server sees (spoiler: nothing)
The architecture has exactly one network dependency: the Google sign-in that gates access to the app. That flow verifies who you are — it never carries what you own. After sign-in, every read and write of your financial data happens between the page and your browser's local database.
You do not have to trust this article. Open your browser's dev tools, watch the network tab, and update an asset: zero requests containing your data. Local-first is a verifiable claim, not a promise.
What this design deliberately cannot do
Honest crypto means stating the limits:
- No password reset. The key exists only in your head, derived on your device. Lose the master password, lose the vault. Any system that can recover your data can also read it — pick one.
- No server-side search or insights. The server never sees plaintext, so it cannot compute anything over it. All analytics run locally, in your browser.
- A weak master password weakens everything. PBKDF2 slows guessing down; it does not stop it. A random four-word passphrase is a good floor.
Why it matters for a net worth tracker
There is a categorical difference between "we encrypt our databases" and "we cannot read your data." The first is table stakes for any competent server. The second is an architectural property — and only client-side key derivation gives it to you.
If you want the full argument for keeping your balance sheet off servers entirely, start with why your net worth data should never touch a server. If you would rather see the local-first approach in action, try the sandbox — the encryption described above is exactly what runs behind it.
Related reading
- Why Your Net Worth Data Should Never Touch a ServerNov 10, 2026
Bank-linked trackers ask you to hand over read access to your entire financial life. A local-first net worth tracker keeps that data in your browser instead.
- How to Track Net Worth Without Linking Your Bank (No Plaid Required)Nov 5, 2026
Bank-linked trackers trade your financial credentials for convenience. Here is how a no-Plaid net worth tracker works, and what you give up.