password_manager/README.md

98 lines
4.6 KiB
Markdown

# 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 (600,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** — One-click random password generation in the entry form (🎲 button). Uses Web Crypto API for cryptographically secure randomness.
- **Copy to clipboard** — One-click copy with 15-second auto-clear.
- **JSON import/export** — Export your vault as encrypted JSON with selective group filtering. Import with merge or replace mode.
- **Auto-lock** — Vault locks automatically on tab switch, visibility change, or 5-minute 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/index.html (single self-contained file)
npm run preview # test the production build locally
```
The build produces a **single `dist/index.html`** file with all JavaScript, CSS, and assets (including favicon) inlined as data URIs. No external files, no network requests — it works from:
- `file://` protocol (open `dist/index.html` directly)
- Any static web server (nginx, Apache, GitHub Pages, etc.)
- USB stick, email attachment, or any offline medium
The single-file output is handled by [`vite-plugin-singlefile`](https://www.npmjs.com/package/vite-plugin-singlefile) for JS/CSS inlining, plus a post-build script that inlines the favicon SVG and removes leftover asset files.
### Encryption Flow
```
Master Password ──PBKDF2──→ 256-bit Key ──AES-GCM──→ Encrypted Credential
(600k 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`, `encryptedPassword` (encrypted), `url`, `notes`, `groupId`, `tags`, `createdAt`, `updatedAt` |
| `groups` | `id`, `name`, `color`, `createdAt` |
| `meta` | `salt`, `testEncrypted`, `testPlaintext`, `dbVersion` |
## Security Considerations
| Threat | Mitigation |
|---|---|
| Key persistence | Key stored only in `$state`, cleared on lock/close |
| Weak passwords | 16-character default with mixed character types |
| Clipboard leakage | Auto-clear after 15 seconds |
| Tab left open | Auto-lock on visibility change (tab switch) |
| Database tampering | Passwords encrypted at rest with AES-256-GCM |
| Brute force | PBKDF2 with 600,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** — Only `encryptedPassword` is encrypted at rest. Titles, usernames, URLs, and notes are stored in plaintext for searchability and are visible if the database is inspected.
- **Test plaintext stored in IndexedDB** — The `testPlaintext` value used for password verification is stored unencrypted in the `meta` store. An attacker with access to IndexedDB could use it to verify guessed passwords alongside the salt.
- **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`), props-based event passing
- **Vite 8** — Build tool and dev server
- **vite-plugin-singlefile** — Inlines all JS/CSS into a single HTML file
- **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