Secure Vault is a server-side encrypted password and secrets vault. It uses password-based key derivation and authenticated symmetric encryption to protect user data. The system consists of a FastAPI backend, a React + TypeScript frontend, and a modular SQLite-backed storage layer.
mini project/
├── api/
│ └── main.py # FastAPI entry point
├── src/
│ ├── auth_manager.py # Registration/login logic
│ ├── crypto_utils.py # PBKDF2 + Fernet utilities
│ ├── database_manager_sqlite.py # SQLite operations
│ └── vault_manager.py # Vault CRUD operations
├── frontend-react/
│ ├── src/
│ │ ├── components/
│ │ ├── services/
│ │ └── App.tsx
│ ├── package.json
│ └── tsconfig.json
├── tests/ # Unit tests
└── README.md
- Passwords are hashed using bcrypt (salt embedded).
- A per-user symmetric master key is generated during registration.
- The master key is encrypted using a password-derived key (PBKDF2-HMAC-SHA256) and stored as an encrypted blob.
- During login, the password-derived key is recomputed and used to decrypt the master key.
- Vault entries are encrypted and decrypted using
cryptography.Fernet. - The design provides protection for secrets at-rest but does not implement strict client-side zero-knowledge behavior.
- Secure registration and login with bcrypt
- PBKDF2-based encryption of per-user master keys
- Authenticated symmetric encryption via Fernet
- SQLite-backed, pluggable database layer
- FastAPI backend with OpenAPI docs
- React + TypeScript UI
- Python 3.8+
- Node.js 16+
- npm
cd "mini project"
python -m venv venv
# Windows
.\venv\Scripts\activate
# macOS/Linux
# source venv/bin/activate
pip install --only-binary=all fastapi uvicorn[standard] bcrypt cryptography python-multipart pydantic
cd frontend-react
npm install
.\venv\Scripts\activate
cd api
python main.py
Backend:
cd frontend-react
npm start
Frontend:
- Open the frontend in a browser.
- Register a new account.
- Log in with your credentials.
- Add, view, update, or delete vault entries.
- Use the API docs for testing or integrating the backend.
-
POST /api/register Registers a new user. Stores bcrypt hash, PBKDF2 salt, and encrypted master key.
-
POST /api/login Verifies password using bcrypt, re-derives PBKDF2 key, decrypts master key, and returns it (current design).
-
POST /api/logout Clears session or client-side state (implementation dependent).
-
GET /api/check-username/{username} Checks if a username already exists.
-
POST /api/vault/entries Creates a new vault entry. Client must supply decrypted master key.
-
GET /api/vault/entries Returns all encrypted vault entries for the authenticated user.
-
GET /api/vault/entries/{service_name} Fetches the encrypted entry for a specific service name.
-
PUT /api/vault/entries/{entry_id} Updates an existing encrypted entry.
-
DELETE /api/vault/entries/{entry_id} Deletes an encrypted entry.
- DELETE /api/user/delete Removes the user account and all associated vault data.
- bcrypt password hash
- PBKDF2 salt used to derive the wrapping key
- encrypted master key (Fernet key wrapped with PBKDF2-derived key)
- user ID
- service name
- encrypted blob (Fernet ciphertext)
- timestamps (created/updated)
- bcrypt is used for hashing.
- Salt is embedded within the bcrypt output; no separate salt column is required.
- PBKDF2-HMAC-SHA256
- Salt: 32 bytes
- Iterations: 100,000
- Output key used to encrypt/decrypt the per-user master key.
Registration
- Generate a random Fernet master key.
- Generate PBKDF2 salt.
- Derive wrapping key using password + salt.
- Encrypt master key with wrapping key and store it.
Login
- Verify password with bcrypt.
- Re-derive the PBKDF2 wrapping key.
- Decrypt the stored encrypted master key.
- Master key is returned to the client (current implementation) and exists in server memory during this process.
- Entries are encrypted client-side or server-side using the decrypted master key.
cryptography.Fernetensures integrity and confidentiality.
- TLS is required in production to prevent credential and key interception.
The system does not implement strict client-side zero-knowledge security.
The server generates the master key at registration, decrypts it during login, and returns it to the client. This means the master key exists in server memory at critical points. A true zero-knowledge architecture would require the client to generate, encrypt, and manage the master key without the server ever accessing plaintext key material.
This implementation protects against attackers who steal only the database but does not defend against a compromised or malicious server.
- Compromised server access where plaintext master keys may be observed in process memory
- Lack of TLS during development or insecure deployments allowing MITM interception
- Credential reuse attacks enabling vault decryption if user passwords are reused and leaked elsewhere
- Migrate to client-side master key generation to achieve true zero-knowledge behavior
- Replace PBKDF2 with Argon2id for memory-hard protection against GPU/ASIC cracking
- Remove plaintext master key from login responses entirely
- Enforce TLS with HSTS in all production environments
- Provide tooling for re-wrapping and migrating existing encrypted master keys when parameters change
- Ensure logs never contain sensitive data and clear decrypted key material from memory as soon as possible
from auth_manager import register_user, login_user
from vault_manager import create_entry, get_entry
register_user("alice", "StrongPassword123")
info = login_user("alice", "StrongPassword123")
master_key = info["master_key"]
create_entry("alice", master_key, "API Key", "abcd-1234")
entry = get_entry("alice", master_key, "API Key")
print(entry["secret"])
- Python 3.8+ and Node.js 16+ required
- Activate the Python venv before running the backend
- Run frontend and backend in separate terminals
- Tests can be run using pytest or individual test scripts