Password Manager with Zero-Knowledge Architecture
Secure Vault is a web-based Password Manager Application, Encryption and decryption happen completely client-side. The server stores an encrypted data which is unlocked by the user's password (derived key) on the client.

Table of contents
Here, i will explain the core features of this application, namely how the encryption and decryption processes work in the authentication section and the items that will be stored by the user's.
Register an account
This registration process will be divided into 3 sections, The first section is telling you to submit a username and email, after submitting, you will get OTP verification for the next section to proof yourself if the email is really yours.
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/21751a5a106e30d424fac52cce7e5a6944396070-407x300.png)
The second stage is telling you to submit the OTP verification sent to your email.
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/0d8147c54cb74b2e1834d3885b3873acea59178f-331x213.png)
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/321108883683debdd15c96561f787b4547082940-601x429.png)
The last section, After OTP verified the user requested to create their password and all the encryption process is happen on the browser (client-side).
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/4e7eed9a2a62fb34ab83a51b7449f13860b05f8e-602x469.png)
Passwords are not simply hashed and then entered into the database. The system generates a random salt and uses the Argon2id algorithm to convert the master password into a master key. From this master key, the system also derives an auth_verifier using HKDF-SHA256 as proof of password knowledge. The master key then encrypts the Data Encryption Key (DEK) a 256-bit random key using XChaCha20-Poly1305 with a unique 192-bit nonce. The encrypted DEK (encrypted_DEK), nonce, salt, Argon2 parameters, and auth_verifier are stored in the database.
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/ddd8875d295870c6ac874493ebbedd4091af7454-1241x1171.png)
Login Processes
When logging in, the user enters the master password; the system takes the salt, nonce, and Argon2 parameters to regenerate the master key on the client side. The client then decrypts encrypted_DEK if decryption fails (Poly1305 authentication tag does not match), it means the password is incorrect.
Next, the client derives the auth_verifier and sends it to the server for constant-time verification against the stored value. With this architecture, the server never knows the user's master password (zero-knowledge). All sensitive data (e.g., Facebook password) is encrypted with a unique DEK and nonce, ensuring that the ciphertext is different even if the data is the same.
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/5c65a25b31bcd54ac6e0b043a3e431582117300e-472x382.png)
Vault Item Encryption
After the user successfully logs in, the decrypted DEK (Data Encryption Key) is temporarily stored in the browser's sessionStorage. This DEK is used to encrypt and decrypt all sensitive data in the vault without having to re-enter the master password. When the user saves a new item (e.g., Facebook account credentials), the encryption process occurs entirely on the client side using WebAssembly (WASM). The system generates a unique 192-bit random nonce for each item, then encrypts the data using the XChaCha20-Poly1305 algorithm with the DEK as the key and Additional Authenticated Data (AAD) as the validation context. The result is ciphertext that includes the encrypted data along with a 128-bit authentication tag to ensure integrity. The encrypted data (encrypted_data) and nonce are sent to the server for storage, while the DEK is never sent to the server. The decryption process occurs when the user wants to view the stored data.
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/40709af8749d3d6657d97c89bf5d82ee7ce615ad-675x289.png)
Vault Item Decryption
Client retrieves encrypted_data and nonce from the server, then uses the DEK stored in session Storage to decrypt. The XChaCha20-Poly1305 algorithm first verifies the authentication tag if it does not match, decryption is canceled because the data may have been modified (tamper detection). If valid, the plaintext is returned to the user.
![[Gambar tidak memiliki deskripsi]](https://cdn.sanity.io/images/7blsog1k/production/d83878508bcf0f3c6a9168311031cd5d210e2ed4-658x362.png)
That's it, those are all the core features of this application. There are still features such as rate limiting with Redis, but it seems that they don't need to be explained in the context of this password manager application.
Here is my github repository for this app: secure vault