# Password Vault An offline-first password manager that runs entirely in your browser. No server, no cloud, no tracking — your vault lives on your machine. ## Features - **AES-256-GCM encryption** — All credentials encrypted with a key derived from your master password via PBKDF2 (100,000 iterations). The key exists only in memory. - **Zero network calls** — Works from `file://` or `localhost`. No APIs, no analytics, no telemetry. - **Group management** — Organize entries into color-coded groups. Create, rename, delete. - **Full-text search** — Instant search across title, username, URL, and notes. - **Password generator** — Configurable length (4–64), character types, custom exclusions, strength indicator. - **Copy to clipboard** — One-click copy with 15-second auto-clear. - **JSON import/export** — Export your entire vault as encrypted JSON. Import with merge or replace mode. - **Auto-lock** — Vault locks automatically on tab switch, visibility change, or configurable inactivity timer. - **Dark theme** — Responsive layout that works on desktop and mobile. ## Quick Start ```bash npm install npm run dev # http://localhost:5173 ``` ## Production Build ```bash npm run build # → dist/ (static files) npm run preview # test the production build locally ``` The `dist/` folder contains fully static HTML/CSS/JS that works from: - `file://` protocol (open `dist/index.html` directly) - Any static web server (nginx, Apache, GitHub Pages, etc.) ## Architecture ``` src/ ├── App.svelte # Root — toggles LockScreen ↔ MainLayout ├── main.js # Entry point ├── components/ │ ├── LockScreen.svelte # Vault creation & password unlock │ ├── MainLayout.svelte # Dashboard shell (sidebar + content) │ ├── Sidebar.svelte # Group list, search, group CRUD │ ├── EntryList.svelte # Searchable/filterable entry table │ ├── EntryDetail.svelte # View single entry, copy, delete │ ├── EntryForm.svelte # Create/edit entry with validation │ ├── PasswordGenerator.svelte # Standalone generator panel │ └── ImportExport.svelte # JSON import/export modals ├── lib/ │ ├── crypto/crypto.js # PBKDF2 key derivation, AES-GCM, generator │ ├── models/schema.js # Data factories, validation, ID generation │ ├── storage/db.js # IndexedDB wrapper (idb library) │ └── stores/ │ ├── app.svelte.js # Reactive app state (lock/unlock) │ ├── search.svelte.js # Shared search + filter state │ └── security.svelte.js # Auto-lock timer, visibility detection └── styles/ └── main.css # Dark theme, CSS variables, responsive ``` ### Encryption Flow ``` Master Password ──PBKDF2──→ 256-bit Key ──AES-GCM──→ Encrypted Credential (100k iters) │ └── Salt stored in IndexedDB (not encrypted) ``` - The encryption key is **never persisted** — it lives only in JavaScript memory. - A test payload (random string) is encrypted on vault creation and stored alongside the salt. On unlock, the entered password is used to derive a key and decrypt the test payload — if decryption succeeds, the password is correct. - On tab close or auto-lock, the key is cleared from memory. ### Storage Schema (IndexedDB) | Store | Fields | |---|---| | `entries` | `id`, `title`, `username`, `password` (encrypted), `url`, `notes` (encrypted), `groupId`, `createdAt`, `updatedAt` | | `groups` | `id`, `name`, `color`, `createdAt` | | `meta` | `salt`, `testEncrypted`, `testPlaintext` | ## Security Considerations | Threat | Mitigation | |---|---| | Key persistence | Key stored only in `$state`, cleared on lock/close | | Weak passwords | Strength indicator on generator; no minimum enforced (user's choice) | | Clipboard leakage | Auto-clear after 15 seconds | | Tab left open | Auto-lock on visibility change (tab switch) | | Database tampering | All sensitive data encrypted at rest with AES-256-GCM | | Brute force | PBKDF2 with 100,000 iterations slows offline attacks | ### Known limitations - **No browser fingerprinting or anti-keylogger** — This is a local tool, not a hardened security appliance. - **IndexedDB can be inspected** — Encrypted data is safe, but metadata (titles, usernames, URLs) may be visible if not encrypted. Currently only `password` and `notes` are encrypted; titles/usernames/URLs are stored in plaintext for searchability. - **No automatic backups** — Use the JSON export feature to back up your vault regularly. ## Development ```bash npm run dev # Start dev server with HMR npm run build # Production build (zero warnings target) npm run preview # Preview production build ``` ### Stack - **Svelte 5** — Runes-based reactivity (`$state`, `$derived`, `$effect`) - **Vite 8** — Build tool and dev server - **idb** — Promise-based IndexedDB wrapper - **Web Crypto API** — Native browser cryptography (no external crypto libraries) - **Vanilla CSS** — Dark theme with CSS custom properties, no preprocessors ## License MIT