An open API service indexing awesome lists of open source software.

https://github.com/dris1153/zk-vault

Zero-knowledge personal credential vault — client-side Argon2id + AES-256-GCM encryption, the server stores only ciphertext. WebAuthn unlock, TOTP, PWA. Next.js + Supabase.
https://github.com/dris1153/zk-vault

2fa aes-256-gcm argon2 bip39 client-side-encryption credential-vault e2ee end-to-end-encryption nextjs passkey password-manager pwa self-hosted supabase tailwindcss totp typescript web-crypto-api webauthn zero-knowledge

Last synced: 19 days ago
JSON representation

Zero-knowledge personal credential vault — client-side Argon2id + AES-256-GCM encryption, the server stores only ciphertext. WebAuthn unlock, TOTP, PWA. Next.js + Supabase.

Awesome Lists containing this project

README

          

# Vault - Personal Zero-Knowledge Credential Vault

A single-user, end-to-end encrypted store for logins, wallet keys, seed phrases,
SSH keys, secure notes, and API keys. All encryption happens in your browser;
Supabase only ever stores ciphertext.

Built with Next.js (App Router) + Supabase (Postgres + Auth + RLS) + Tailwind v4.

## Security model (read this)

- **Zero-knowledge.** Your master password never leaves the browser. Encryption
and decryption happen client-side only - no plaintext passes through any
server route or action (enforced by `npm run guard`).
- **Envelope encryption.** A random 256-bit Data Encryption Key (DEK) encrypts
every item (AES-256-GCM). The DEK is wrapped by a key derived from your master
password (Argon2id) and, separately, by a key from your 24-word recovery key.
- **Email-derived auth salt.** Your Supabase login secret is
`Argon2id(master, salt = SHA-256(email))` with a fixed cost, so you can log in
from any device with just master + email - no server read needed first.
- **Strict RLS.** Every row is scoped to `auth.uid()`. Even with the public anon
key, rows are unreadable without your login and contain only ciphertext.
- **No "forgot password".** If you lose your master password, recover with your
24-word recovery key + your encrypted `.vault` backup (Settings -> Backup).
Lose both and the data is unrecoverable - that is the cost of zero-knowledge.
- **Residual risks (honest):** a web app re-downloads its crypto code on each
load, so a compromised host/dependency could serve malicious JS. Mitigated by
CSP, pinned deps, and self-hosting; not fully solvable for web vaults. A
compromised device (keylogger/malware) is also out of scope. See
`docs/security-model.md`.

## Setup

1. **Supabase:** create a project, copy the URL + anon key.
2. **Env:** `cp .env.local.example .env.local` and fill `NEXT_PUBLIC_SUPABASE_URL`,
`NEXT_PUBLIC_SUPABASE_ANON_KEY`. For `npm run db:reset` also set `SUPABASE_DB_URL`
(session-pooler connection string). See `supabase/README.md`. The vault email is
entered on the lock screen at first signup/unlock, not via env.
3. **Auth:** in Supabase, turn OFF "Confirm email".
4. **Schema:** apply `supabase/migrations/0001_init.sql` (SQL Editor, or
`npm run db:reset`).
5. **Verify:** `npm run verify:supabase you@gmail.com` (live end-to-end smoke test).
6. **Run:** `npm run dev` -> http://localhost:3000 -> create your vault.

## Scripts

| Script | Purpose |
| --------------------------------- | -------------------------------------------------------------- |
| `npm run dev` / `build` / `start` | Next.js dev / production build / serve |
| `npm test` | Crypto unit tests (Vitest) |
| `npm run typecheck` | `tsc --noEmit` |
| `npm run guard` | Fail if any server-context file imports the crypto/vault layer |
| `npm run verify:supabase` | Live engine smoke test (throwaway account) |
| `npm run db:reset` | Drop + re-apply migrations (DEV ONLY - wipes vault data) |

`npm run build` runs the guard first.

## Architecture

```
lib/crypto/ pure, framework-agnostic crypto (KDF, AES-GCM, envelope, recovery)
lib/supabase/ browser client, auth, vault_config, provisioning (ciphertext I/O)
lib/vault/ session (RAM DEK), unlock/lock, CRUD, search, export/import, settings
lib/ui/ icon map, clipboard hook, field config
components/ lock screen, app shell, sidebar, cards, drawer, modals, settings
app/ App Router shell + page orchestrator
supabase/ migration + setup guide
scripts/ verify, db-reset, zero-knowledge guard
```

Design system: `DESIGN.md` (Electric Azure on Obsidian, dark-only).
Implementation plan + history: `plans/260605-1204-zk-credential-vault/`.

In-app user guide (Vietnamese, with diagrams): the **`/docs`** route - storage
workflow, unlock flow, deployment A-Z, recovery, and FAQ. This README is the
English dev reference; `/docs` is the canonical user-facing guide.