# Storage encryption (IndexedDB) – Dec 2025 **Scope** - Encrypt private article content and invoices stored in IndexedDB using Web Crypto (AES-GCM). - Deterministic per-article secret derived from a persisted master key. - No fallbacks; fails if IndexedDB or Web Crypto is unavailable. **Key management** - Master key generated once in browser (`article_storage_master_key`, random 32 bytes, base64) and kept in localStorage. - Per-article secret: `:` (used only client-side). **Implementation** - `lib/storage/cryptoHelpers.ts`: AES-GCM helpers (base64 encode/decode, encrypt/decrypt). - `lib/storage/indexedDB.ts`: store/get now require a secret; payloads encrypted; unchanged API surface via `storageService`. - `lib/articleStorage.ts`: derives per-article secret, encrypts content+invoice on write, decrypts on read, same expiration (30 days). **Behavior** - If IndexedDB or crypto is unavailable, operations throw (no silent fallback). - Existing data written before encryption won’t decrypt; new writes are encrypted. **Next steps (optional)** - Rotate master key with migration plan. - Add per-user secrets or hardware-bound keys if required.