Cryptography
A summary of the cryptographic flows used in Zero-TOTP
Keys generation process
In the different cryptographic flows, we use different keys. This section defines these keys and details their generation process.
User derived key
- Name : User derived key.
- Notation :
derived_key
. - Purpose : Encrypt/decrypt the
zke_key
. - Storage : NOT stored.
- Generation process :
- The
derived_key
is a cryptographic derivation from the user's passphrase. - The salt is retrieved from the database.
- Algorithm : PBKDF2 with 700 000 iterations and SHA256 as hash algorithm. The key is derived into an AES-GCM 256 key.
- Where : In the browser, by the frontend (deriveKey())
- Used by: The frontend only. This key never leaves the browser and is never stored, even client side
Zero-Knowledge Encryption Key
- Name : Zero-Knowledge Encryption Key.
- Notation :
zke_key
. Encrypted version :zke_key_enc
- Purpose : Encrypt/decrypt the user vault.
- Storage : Stored ENCRYPTED in the database. The encryption is performed by the
derived_key
. - Generation process :
- At signup the
zke_key
is generated by the browser from 32 bytes of cryptographically secure random bytes. - It is a AES-256 random key.
- This key is encrypted by the
derived_key
and stored encrypted in the database. - At login, the key is retrieved from the database and decrypted by the browser with the
derived_key
. - Where : In the browser, by the frontend (generateZKEKey() and decrypt)
- Used by: The frontend only. This key never leaves the browser in clear and is only stored in clear in the angular service (which is restricted to the current tab session. This means this value is proper to each page (re-)loading and is wiped-out when the tab is reloaded or closed. It cannot be restored).
User creation flow
- A ZKE key is randomly generated by the browser. This is
zke_key
. - The user's passphrase is derived using PBKDF2 and a random salt by the browser. This is
derived_key
. derived_key
is used to encryptzke_key
. This iszke_key_enc
- The user's passhrase is hashed by the browser with SAH256 and a random salt. This is
pass_hash1
pass_hash1
, its salt,zke_key_enc
andderived_key
's salt are sent by the browser to the API for storage.- Before being stored, the
pass_hash1
is hashed using Bcrypt and a random salt
User login flow
- The
pass_hash1
's salt is retrieved from the API before anything using the user's email as identifier. - The user's passphrase is hashed using the retrieved hash, producing
pass_hash1
. pass_hash1
is sent to the API for authentification. It will be hashed using BCrypt and compare to the hash generated during signup.- If the auth is not successful, this is the end of the flow.
- If the auth is successful, the API store a JWT cookie used to authenticate the future user's API calls. The API also returns the user's
derived_key
's salt. - The browser uses the
derived_key
's salt derive the user's passphrase. This isderived_key
. - An API call is made by the browser with the JWT to retrieve the user's
zke_key_enc
. derived_key
is used by the browser to decryptzke_key_enc
. This iszke_key
derived_key
is forgotten andzke_key
is stored in the Angular service, so in tab live session.
Vault encryption flow
Note
To maintain the integrity of the entire vault, secrets are encrypted one by one. Among all information associated with secrets (secret, URI, color, etc ...) the only information kept in clear is its uuid.
- All the secret information are encrypted using
zke_key
. - Encrypted secret is sent to the backend for storage.
- If google drive backup option is enabled, the whole vault is backed up to google drive
Vault decryption flow
- Secret (or secrets) is (are) retrieved from the API. They are all encrypted.
zke_key
is used to decrypt each secret.