Tổng quan & Bảo mật
Vault là kho lưu trữ thông tin nhạy cảm cho cá nhân: mật khẩu đăng nhập, private key ví, seed phrase, SSH key, ghi chú bảo mật, API key. Toàn bộ việc mã hóa và giải mã diễn ra ngay trong trình duyệt của bạn. Máy chủ (Supabase) chỉ lưu dữ liệu đã mã hóa và không bao giờ thấy nội dung gốc.
Zero-knowledge nghĩa là gì?
Master password của bạn không bao giờ rời khỏi trình duyệt. Kẻ tấn công chiếm được cơ sở dữ liệu Supabase cũng chỉ lấy được các khối ký tự vô nghĩa (ciphertext). Đây chính là mô hình mà Bitwarden và 1Password dùng.
Mã hóa kiểu "phong bì" (envelope)
Một khóa dữ liệu ngẫu nhiên 256-bit (gọi là DEK) mã hóa mọi mục bằng AES-256-GCM. DEK được "bọc" lại bởi hai khóa khác nhau: một khóa dẫn từ master password (qua Argon2id), và một khóa dẫn từ recovery key 24 từ. Đổi master password chỉ cần bọc lại DEK, không phải mã hóa lại toàn bộ dữ liệu.
Thuật toán
Argon2id(64 MiB, 3 vòng) biến mật khẩu thành khóa, chống brute-force mạnh.AES-256-GCMmã hóa từng mục; thẻ xác thực (auth tag) tự động từ chối nếu dữ liệu bị sửa hoặc sai khóa.- Recovery key dùng chuẩn
BIP39(24 từ tiếng Anh).
Luồng lưu trữ & mở khóa
Khi bạn lưu một mục
Dữ liệu được mã hóa ngay tại trình duyệt bằng DEK trước khi gửi đi. Supabase chỉ nhận về ciphertext, kèm hai trường công khai duy nhất là type và favorite (để đếm và lọc theo nhóm mà không cần giải mã).
Khi bạn mở khóa
Mật khẩu đăng nhập Supabase được dẫn từ master + email nên tính được ngay mà không cần đọc cơ sở dữ liệu trước. Sau khi đăng nhập, ứng dụng tải cấu hình (vẫn là ciphertext), dẫn ra KEK và mở khóa DEK.
Các lớp bảo vệ khác
- RLS nghiêm ngặt: mọi dòng gắn
auth.uid() = user_id; lộ anon key cũng chỉ đọc được ciphertext. - Tự khóa: xóa DEK khỏi RAM sau thời gian rảnh hoặc khi chuyển tab (tùy chỉnh trong Settings).
- Tìm kiếm trong bộ nhớ: giải mã một lần khi mở khóa rồi tìm fuzzy ngay tại client, không lộ gì cho máy chủ.
- Tự xóa clipboard: sau khi copy, clipboard được xóa sau 10-30 giây (tùy chỉnh), kèm đồng hồ đếm ngược.
Triển khai A-Z (Vercel + Supabase)
Toàn bộ quy trình từ con số 0 đến khi app chạy thật trên Vercel. Cần một tài khoản Supabase (miễn phí) và một tài khoản Vercel.
- 1Tạo Supabase projectVào supabase.com, tạo project mới. Mở
Project Settings → API, copy Project URL và anon public key. Tuyệt đối không dùngservice_rolekey trong app. - 2Điền .env.localSao chép
.env.local.examplethành.env.localrồi điền 3 biến (biến tùy chọn cuối chỉ cần cho lệnhdb:reset):
Cả 3 biếnNEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOi... NEXT_PUBLIC_VAULT_EMAIL=ban@gmail.com # tùy chọn - cho "npm run db:reset" (chứa mật khẩu DB, giữ bí mật) SUPABASE_DB_URL=postgresql://postgres.xxxx:MATKHAU@aws-0-region.pooler.supabase.com:5432/postgresNEXT_PUBLIC_*đều công khai an toàn - bí mật của bạn được bảo vệ bởi master password, không suy ra được từ chúng. - 3Tắt xác nhận emailTrong Supabase:
Authentication → Sign In / Providers → Email, tắt Confirm email. App tạo tài khoản rồi đăng nhập ngay bằng mật khẩu dẫn ra; nếu bật xác nhận thì phiên đầu sẽ bị chặn. - 4Tạo schema (bảng + RLS)Cách nhanh: mở
SQL Editor, dán toàn bộsupabase/migrations/0001_init.sqlrồi Run. Hoặc nếu đã đặtSUPABASE_DB_URL:npm run db:reset - 5Kiểm tra engine (live)Chạy smoke-test đầu cuối với tài khoản nháp (không đụng vault thật):
Phải qua đủ 8 PASS: provision, đăng nhập, RLS, mở khóa, recovery key, mã hóa CRUD.npm run verify:supabase - 6Chạy local
Mở trình duyệt, tạo vault và lưu kỹ 24 từ recovery.npm install npm run dev # http://localhost:3000 - 7Deploy lên VercelĐẩy code lên GitHub. Vào Vercel: Add New → Project rồi import repo. Trong phần Environment Variables, thêm đúng 3 biến
NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_ANON_KEY,NEXT_PUBLIC_VAULT_EMAIL. Vercel tự nhận Next.js và build (npm run buildđã chạy sẵn CI guard).
.env.local chứa key và đã được gitignore. Chỉ commit .env.local.example. Đặt biến môi trường thật trực tiếp trên Vercel.Khôi phục, FAQ & Lưu ý
Khôi phục khi quên master password
Mô hình khôi phục dùng file backup mã hóa (Option A): RLS luôn nghiêm ngặt, không có đường đọc dữ liệu từ cloud nếu chưa đăng nhập. File .vault tự chứa mọi thứ cần thiết (đều là ciphertext, an toàn để lưu ở Drive/USB).
- 1Export định kỳ khi còn nhớ masterVào
Settings → Backup → Exportđể tải file.vault. Nên làm định kỳ. - 2Khi lỡ quên masterTạo vault mới (master mới) trên bất kỳ thiết bị nào.
- 3Import bằng recovery keyVào
Settings → Backup → Import, chọn file.vault, tick "dùng recovery key", nhập 24 từ. App giải mã các mục từ file rồi mã hóa lại bằng DEK của vault mới.
Đổi master password
Trong Settings → Account. Thao tác này chỉ bọc lại DEK chứ không mã hóa lại các mục, và recovery key của bạn vẫn còn nguyên hiệu lực.
Giới hạn cần biết
Một app chạy trên web tải lại mã nguồn (gồm cả mã mã hóa) mỗi lần mở. Nếu máy chủ hoặc một thư viện phụ thuộc bị xâm nhập, về lý thuyết nó có thể phục vụ mã độc đánh cắp master password lúc bạn gõ. Zero-knowledge không chống được điều này. Giảm thiểu bằng CSP, ghim phiên bản dependency, và tự host.
Mối đe dọa: trong và ngoài tầm bảo vệ
- Trong tầm (đã giảm thiểu): lộ cơ sở dữ liệu Supabase, nghe lén đường truyền, người trong Supabase, lộ anon key - tất cả chỉ thấy ciphertext.
- Ngoài tầm: thiết bị của bạn dính keylogger/malware; chuỗi cung ứng web (mã độc phục vụ từ host); mất cả master và recovery key.
Câu hỏi thường gặp
Dùng Gmail thường làm email vault được không?
Được. Email chỉ là định danh đăng nhập và là salt; không có thư nào được gửi (đã tắt Confirm email). Không cần domain riêng.
Vì sao chỉ có 5 loại mục?
Login, Wallet, SSH key, Secure note, API key - đủ bao phủ nhu cầu nêu ra. Seed phrase nằm trong Wallet; cụm từ bảo mật dùng Secure note.
Sắp có gì tiếp theo?
v1.5: mở khóa bằng vân tay/Face (WebAuthn) và bộ tạo mã TOTP. v2: CSP dùng nonce, kiểm tra độ mạnh mật khẩu offline, đóng gói PWA.