CipherVault
Client-side encrypted file storage with a server-blind architecture.
CipherVault is a file-storage application I built around a simple question:
What if the server never had access to the user's plaintext files or encryption password?
Instead of uploading plaintext files and relying on the backend to protect them, CipherVault encrypts files inside the browser before they are uploaded.
The backend receives and stores only encrypted data.
The idea
The important part is that encryption and decryption happen in the browser, not on the server.
The server stores the encrypted blob and metadata, but does not need the user's encryption password.
Why client-side encryption?
A traditional storage application can look like:
Browser → Server → Storage
│
└── Plaintext may be accessibleCipherVault instead uses:
Browser → Encrypt → Server → Encrypted StorageThis creates a clear security boundary between the storage system and the contents of the files.
The backend can authenticate sessions, manage metadata, and store encrypted blobs without needing to understand the files themselves.
Cryptography
CipherVault uses the browser's native Web Crypto API rather than implementing cryptographic primitives manually.
Password-based key derivation
The user's password is converted into an AES-256 key using:
- PBKDF2
- SHA-256
- 200,000 iterations
- Random 16-byte salt
The salt is stored with the encrypted payload. It is not secret and allows the same password to derive the same key during decryption.
File encryption
Files are encrypted using:
AES-256-GCM
GCM provides authenticated encryption, meaning that modified or corrupted ciphertext should fail authentication during decryption rather than silently producing altered plaintext.
Each encryption operation also uses a fresh random 96-bit nonce.
Filename encryption
The original filename is encrypted as well.
This means the server does not need to store filenames such as:
tax-return.pdf
personal-notes.txtThe original filename is recovered only after successful client-side decryption.
Data flow
During an upload:
File + Password
│
▼
Browser
│
├── Generate random salt
├── Derive AES-256 key
├── Encrypt file
└── Encrypt filename
│
▼
Encrypted Payload
│
▼
FastAPI
│
├── SQLite → Metadata
└── Storage → Encrypted BlobDuring a download, the process is reversed:
Encrypted Blob
│
▼
Browser
│
├── Extract salt + nonce + ciphertext
├── Derive key from password
├── Authenticate + decrypt file
└── Decrypt filename
│
▼
Original FileA wrong password causes AES-GCM authentication to fail because the derived key cannot authenticate the ciphertext.
Backend architecture
The backend is built with FastAPI.
It handles:
- Session creation and authentication
- Encrypted file uploads
- Encrypted file downloads
- File listing
- SQLite metadata
The database stores metadata such as:
file_id
owner_id
file_size
upload_timestamp
blob_pathThe encrypted file itself is stored separately from the database.
This keeps the database focused on metadata while the storage layer handles encrypted blobs.
Server-blind storage
One of the simplest ways I tested the architecture was opening a stored encrypted .bin file directly from the server's storage directory.
Instead of the original document, the server only contains ciphertext.
The important distinction is:
The server stores the ciphertext, not the plaintext.
This does not make the application invulnerable, but it means that obtaining the stored blob alone should not reveal the original file without the user's password.
What I learned
CipherVault taught me that secure storage is less about choosing an encryption algorithm and more about designing the entire data flow around the security property.
The project gave me practical experience with:
- Client-side cryptography
- PBKDF2, salts, and nonces
- AES-GCM authentication
- Handling binary file data
- Encrypting metadata such as filenames
- Separating encrypted storage from database metadata
- Designing frontend/backend communication without transmitting the encryption password
The biggest lesson was:
Security properties have to be designed into the architecture from the beginning.
Encrypting a file at one point in the application is not enough if plaintext or encryption keys are later sent to the server.
Current status
Complete
CipherVault currently supports:
- Client-side file encryption
- AES-256-GCM
- PBKDF2 key derivation
- Random salts and nonces
- Client-side filename encryption
- Encrypted file storage
- SQLite-backed metadata
- Session-based authentication
- Client-side decryption
- Original filename restoration
- Multiple file types
The implementation is intentionally a learning-focused project rather than a production-grade password manager or enterprise storage system.
Future improvements
If I continued the project, the main areas would be:
- Stronger authentication and session management
- Automated cryptographic integration tests
- File lifecycle and deletion management
- Large-file streaming encryption
- Rate limiting and abuse protection
- More rigorous security testing
