Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing master password that is used for encryption

I want to store some data encrypted, for example like a password manager where your master password unlocks all the underlying app/site passwords.

Looking around I found some examples like this, but they seem to use the password as a part of the encryption, similar to a salt in hashing. This means that to decrypt you need the exact same password, so you cannot ever change the password. This doesn't seem great from a security/usability standpoint; if a PW gets compromised, you'd have to remake the whole database under a different PW.

How would you make a system where you can change the master password? Do you you do a simple login check, and then use a string to encrypt/decrypt? Wouldn't the static nature plus storage of that string be unsafe?

I know some PHP and a smidge of Javascript, so if you have examples in those languages that would be nice, but a more general high level explanation is also very much appreciated.

like image 271
PixelSnader Avatar asked Jul 21 '17 08:07

PixelSnader


People also ask

Can you change master password?

Click the Security. Click Change Password. First, you'll need to enter your Current Master Password. After that, enter your New Master Password and confirm it.

Do password managers use encryption?

Not only do password managers help securely house your passwords, but they can also generate passwords that are unique and complex, which makes them more difficult to crack or guess. To do this, password managers use encryption algorithms.

How often should you change master password?

Cybersecurity experts recommend changing your password every three months. There may even be situations where you should change your password immediately, especially if a cybercriminal has access to your account.


2 Answers

There are a couple of approaches that work. Jannes's answer alludes to a workable solution (although beware of vulnerabilities in openssl_private_decrypt()).

If you're using Defuse Security's PHP encryption library, password-protected keys are abstracted away. (There's currently an open pull request to tackle making "change password" operations seamless and easy-to-use.)

See also: https://github.com/defuse/php-encryption/blob/master/docs/classes/KeyProtectedByPassword.md

How would you make a system where you can change the master password?

Something like this:

  1. Generate a strong random key. We'll call this secret.
  2. Derive a separate key from the user's master password and a static salt (generated once from a cryptographically secure random number generator). We'll call this passwordKey.
    • Argon2id(password, salt) => passwordKey
  3. Encrypt secret with the passwordKey, using a secure AEAD mode with a random nonce, and store the result alongside the salt.
    • $saved = $salt . $nonce . sodium_crypto_secretbox($secret, $nonce, $passwordKey);
  4. The actual data itself will be encrypted with secret, not passwordKey.

If you need to change the password, just repeats step 2 and 3 with the new password (and a different salt).

For Argon2id, you can use sodium_crypto_pwhash() on PHP 7.2 and newer.

like image 125
Scott Arciszewski Avatar answered Sep 18 '22 15:09

Scott Arciszewski


You could use public-key cryptography, using the public key to encrypt data and with a password in your private key, that can be changed.

One solution would be: 1) Generate rsa private and public keys (on Ubuntu):

openssl genrsa -des3 -out private.key 1024
openssl rsa -in private.key -pubout > public.key

2) Use the public key to encrypt:

$key = file_get_contents('/path/to/public.key');
openssl_public_encrypt("password", $encryptedData, $key);

Save $encryptedData to your database(you cannot use this string as password hash to match for login, as the $encryptedData have random bits added before encryption, you will still need to use a hash function for the passwords).

3) Use the private key to decrypt, providing the password:

$key = openssl_pkey_get_private(file_get_contents('/path/to/private.key'), $password);

if($key === false) {
    // false password
    die;
}
openssl_private_decrypt($encryptedData, $decryptedData, $key);

4) Change the password:

openssl rsa -des3 -in private.key -out private.key

This gives you 2 advantages:

  • Separate encryption & decryption applications, encryption does not require private key or password.
  • Password does not need to be saved inside the application.

This will serve your main requirement of being able to change the password and not re-encrypt the data.

If you want to further secure your private key(to not allow php to directly access your private key, which is useful in case your app is hacked), you can create a decrypt service in your system, that you can use to send the encrypted data with the password and get the decrypted data.

like image 20
Jannes Botis Avatar answered Sep 17 '22 15:09

Jannes Botis