Store encrypted user data in database

You can use a key derivation function to convert the user's password into an encryption key. Then you would use a cryptographically secure pseudorandom number generator to generate a separate key that would encrypt the user's data. You would then use the derived key to encrypt the generated key. The resulting ciphertext of the data encryption key could then be stored safely in the user table of your database (call the field "encryptedkey" if you like). In this way, the user's password will become the means to decrypt the user's encrypted key. The key that actually encrypts the data is only decrypted long enough to decrypt the data that it encrypted. You'll need to store that key in the session in order to avoid the need to ask the user for his password on each decryption occurance.

Alternatively, you can store the key encryption key on a Key Management Service such as that offered by Amazon AWS. This way you would retrieve the key from Amazon over TLS using only a reference to the key. Of course in this case you will still need to store the authentication credentials for the KMS somewhere in your architecture, possibly in a remotely retrieved highly secured config file.

  1. Random Number Generator ⟶ Helps create Key #1.
    This key encrypts your data. It stays constant over time. You must generate this key when the user first registers. Use a CSPRNG (cryptographically secure pseudo-random number generator) to ensure sufficient randomness and unpredictability.

  2. Password ⟶ Converted into Key #2 with PBKDF2.
    This key, Key #2, is used to encrypt Key #1. You'll want to persist Key #2 in the user's session. Store the encrypted form of Key #1 in the user table, in a field called (perhaps) "encryptedkey".

  3. Changing passwords
    Whenever the user changes their password, you only have to execute step #2 again, rather than encrypting all of your data, all over again. Just convert the new password into a key (Key #2), re-encrypt Key #1, and overwrite the old value for the encrypted form of Key #1.

  4. Encrypting/decrypting data
    When the user has logged in, execute step #2. Once you have the password converted into a key, just decrypt Key #1. Now that you have Key #1 decrypted, you can use Key #1 to encrypt and decrypt your data.


Not sure if this can be effective as a comment, instead of an answer: happy to change for the better.

The only purpose is to give a visual representation of @vrtjason's accepted answer, as that includes a number of scenarios and involves using a couple of (encryption) keys. Here you go:

scenarios and used keys

For completeness, keys involved in such protocol play roles that are known in literature as:

  • User-Key: DEK, Data Encryption Key
  • Password-Key: KEK, Key Encryption Key

HTH