I'm trying to get a per-user encryption key scheme off the ground and need some validation from wiser crypto pros. Consider the following procedure:

  1. User provides registration information to include a password.
  2. Generate a random salt.
  3. Hash the password+salt using bcrypt.
  4. Generate a key to be used for data encryption (known as the DEK).
  5. Generate a second key derived from the hashed password+salt.
  6. Generate a 12-byte IV.
  7. Encrypt the DEK using the AES-128-GCM cipher, the password-derived key, and the IV.
  8. Store the encrypted DEK, the salt, and the IV in the database.

Any time I need to decrypt user data:

  1. Ask for the user's password.
  2. Pull the salt, IV, and encrypted DEK from the database.
  3. Hash the password+salt.
  4. Generate the key to decrypt the DEK using hashed password+salt.
  5. Decrypt the DEK using the generated key and the IV.
  6. Decrypt the user's data.

To my eye, this seems to be the correct procedure to manage encryption keys in a system where the data and keys are stored on the same system. But encryption is hard so I could be getting something wrong. So what say you? Any obvious omissions in this scheme?

Many thanks.

EDIT: For clarity's sake, this is a web application storing PII in the database as well as on disk. There are no instances where one user should be able to access another user's sensitive data. The user has been warned that forgetting their password means losing access to their data.

  • $\begingroup$ Some information you can find on Dropbox blog: blogs.dropbox.com/tech/2016/09/… $\endgroup$
    – ventaquil
    Mar 2, 2019 at 23:47
  • 2
    $\begingroup$ Is this system intended to prevent the server from being capable of decrypting the user's data? If so, you'll need to perform all of the crypto client-side, and either use different passwords for authentication and data security or generate password-verification hashes and DEK-wrapping-key derivation differently plus never send the raw password to the server (even at registration). $\endgroup$
    – CBHacking
    Mar 3, 2019 at 0:19
  • $\begingroup$ No, the server will need to access some of the PII data mostly for PDF generation and the like. So that PII needs to be encrypted for storage in the database. With that data, the server is intended to generate documents containing PII which are then encrypted and stored on disk for some undetermined length of time (3 months is likely). $\endgroup$
    – dbarbour
    Mar 3, 2019 at 0:25
  • 1
    $\begingroup$ The intent is to protect the company from inadvertently exposing the PII to an unauthorized user. Once the authorized user gets the server-generated documents, what they do with it is on them. $\endgroup$
    – dbarbour
    Mar 3, 2019 at 0:26

1 Answer 1


It all has to do with your requirements. If you want the server to have access to the data when the user logs in but not allow the server offline access. Then this scheme seems reasonable. You have a second key which may or may not be needed. If each user has exactly one password and exactly one random key then you could use the password derived key directly. You did specify how you encrypt the data, but AES GCM again would be reasonable. You want to make sure you can verify they password. Use of GCM for the key or use of GCM for the data would suffice. If the data encrypted is large, a second key allows changing password without reencrypting all of it. For small data I may recommend skipping the second key. Be sure you use secure random number generators. Be sure the password is sent to the server over a secure line(e.g SSL). Some would advocate for doing hashing client side, which makes the server never have the clear text, and the client does the heavy computation, preventing some DOS attacks and some timing attacks.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.