Skip to content
Jeffery (Zeyu) Zhao edited this page Aug 7, 2020 · 9 revisions

This page introduces encryption mechanism.

mechanism

Key Generation

Function definition:

  • WKeyGen(password, salt) = PBKDF2_SHA512(password, salt, iterations: 1e4)
  • SKeyGen(password, salt) = PBKDF2_SHA512(password, salt, iterations: 1e6)
  • REDUCED_INFO is a function to drop one character information.

Procedure for standard login (password stands for your login password):

  • password_0 = REDUCED_INFO(password)
  • secret_key = SKeyGen(password_0, WKeyGen(username, JSsalt)))
  • confusion_key = WKeyGen(password, secret_key)
  • login_signature = WKeyGen(secret_key, username)
  • submit login_signature to server for authentication

Procedure for PIN login

See PIN Authentication

Password From User Screen to Server

  1. User input account and corresponding password into web browser.
  2. POST login_signature to server for authentication. At server side, PBKDF2_SHA3-512 will be used to hash login_signature
  3. Web browser calculate the mapping alphabet which is from SHA512(entry_account_name) and confusion_key.
  4. Using the mapping alphabet to map the raw password into a confusion password. Same characters in original password might map to different characters in confusion password to prevent the attackers getting the pattern of your password.
  5. Using AES256-CBC to encrypt confusion mapped password, as well as account and using secret_key as key.
  6. POST each AES256 encrypted account and password entry to server.

Password from Server to User Screen

  1. POST login_signature to server as authentication. At server side, PBKDF2_SHA3-512 will be used to hash login_signature
  2. Web browser calculate the mapping alphabet which is from SHA512(entry_account_name) and confusion_key.
  3. Server retrieve data from database, send back all encrypted strings.
  4. Using AES256-CBC to decrypt confusion mapped password, as well as account and using secret_key as key.
  5. Using the mapping alphabet to map the confusion password into raw password, based on confusion_key.

Files

From v9.09, Password Manager supports small binary file storage along with an account. This feature is enabled by default but users might turn it off in funciton/config.php by setting $FILE_ENABLED = False. This feature is useful when you want to store a ssh key, a certificate or some small images. However, it should not be used as another dropbox. In current design, file is base64 encoded and stored in database after encryption. If file becomes too large, the performance of the system will be undermined. Thus, we recommend you to keep files stored per entry within 500KiB. Since file part is much larger compared to text part, different design is adopted for files.

  • File name is encrypted with secret_key as passphrase by AES256.
  • A random key is generated and encrypted with secret_key, file_name with WKeyGen. This random key is permanently associated with this file.
  • Data is first encoded with base64 and then encrypted with the random key.
  • Encrypted file name, key and data will be uploaded to server.
  • Therefore, Data decryption is only related to the random key. If the user changes something, we only need to re-encrypt the random key associated with the data instead of the data itself.

PIN Authentication

  1. User input PIN
  2. Web browser generates a random salt of length 100 and put it in localstorage
  3. web browser send SKeyGen(pin, salt) as pin_sig to server (server furture hash this pin_sig with PBKDF-SHA3)
  4. server receives pin_sig and generates an random server_key with length 512 bits, send server_key to web browser
  5. web browser encrypt secret_key and confusion_key with WKeyGen(PIN+server_key, salt) and store them in localstorage. server_key won't be stored in browser
  6. When login, after inputing PIN, web browser send SKeyGen(pin, salt) to server
  7. Server receives pin_sig, if it's correct, send back server_key, otherwise, increase the error_try by 1
  8. if error_try > 3, server delete this PIN record, the user needs to input username/password.
  9. After receiving server_key, web browser is able to decrypt secret_key and confusion_key
  10. By using WKeyGen(secret_key, username), web browser gets login_sig and it uses username in cookie and this login_sig to login.

Safety

Suppose attackers can't get the screen access when you use password manager. Let's discuss some worst cases.

Attacker tries to enumerate possible passwords

If you put reasonable complexity on the login password, this can take several hundred of years.

Attacker gets root shell access to your server

If you did not enable client-side source file check, you are doomed. So if you can't 100% trust your server (e.g. VPS), you should always enable client-side source file check.

If you enabled client-side source file check, attacker can't change your client-side code without alerting you. But all server side encryption is useless in this case if attacker can change server side code. However, we have strong encryption at client side so you are still safe. (Say attacker will only need 100 years now to hack your password instead of several hundred)

Attacker gets your clients (PC / Cellphone)

If you didn't set PIN, the attacker can only enumerate possible passwords. If you set PIN, note part of the decryption information is stored at server side and the attacker needs to enumerate your PIN to get the information from server. Enumerating PIN is easier than login password but after 3 failed attempts, the server will permanently delete the information at server side and then PIN becomes useless.

Attacker gets your database dump

PIN is useless to attacker on this case because he doesn't have access to pin_salt. If he tries to enumerate your password, remember that you did 1e6 rounds of PBKDF2_SHA512 at client side

Attacker gets both your database dump and your client

If you didn't set PIN, you are still safe as your client is useless. Otherwise, attacker can easily (much easier than all above cases) gets your secret key by enumerating your PIN so that SKeyGen(PIN, pin_salt)=pin_sig. Since PIN is relatively easier, you can suppose attacker will get your data in several hours.

This is a very extreme case and you should notice if it happens.

About confusion_key

This design is inherited from several years ago for fail-safe and I don't think it's needed anymore. However, I'll just keep it in case some part of my encryption algorithm has security flaws...

  • confusion_key contains all information in your login password, part of which is not involved in server-side authentication.
  • Any information for the above part (I(confusion_key) - I(login_sig)) will not be uploaded to server.
  • Using wrong login password you might be able to login (as long as login_sig induced is the same with the correct one), but will see incorrect passwords (very different from the correct ones). But the design of REDUCE_INFO calculation ensures that incorrect login passwords by mistake won't log you in (for two passwords that generate same login_sig, they are same or different at all letters). So only attackers that enumerate your login passwords might run into this case.
  • Change the extra information in confusion_key actually changes the pseudo-passwords.
  • Except that the user sees completely different passwords on screen, inputing wrong login password that happens to generate the correct login_sig won't cause any errors. And since all passwords uses alphabet-based confusion, it's hard to tell whether the password is correct directly. Hopefully you will get alert when the attacker attempts to login to some sites with wrong passwords.

Performance

  • The login might take around 1 second on modern computer or cellphone. Other than that, user will not notice the time lag caused by encryption / decryption.
  • If you feel the Password-Manager is slow, most likely your server side PBKDF2_ITERATION is too large. This value can be configured at src/function/config.php
  • If you are sure the client side crypto is slow, you can adjust the client side PBKDF2 number of iterations in function SgenerateKeyWithSalt at src/js/common/cryptoWrapper.js. This is not recommended. Not only you lower the security level, the backup / recovery function will be impacted. That said, when you want to recover your backup, you need this edited cryptoWrapper.js

Other

  • Kick out client after sometime of no action (done by JavaScript)
  • Kick out client after sometime of no interaction with server (done by server)
  • Block account and IP address for certain time after too many error attempts
  • Email based two step verification on new device (default is off)
  • Configurable global salt.