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:
- User provides registration information to include a password.
- Generate a random salt.
- Hash the password+salt using bcrypt.
- Generate a key to be used for data encryption (known as the DEK).
- Generate a second key derived from the hashed password+salt.
- Generate a 12-byte IV.
- Encrypt the DEK using the AES-128-GCM cipher, the password-derived key, and the IV.
- Store the encrypted DEK, the salt, and the IV in the database.
Any time I need to decrypt user data:
- Ask for the user's password.
- Pull the salt, IV, and encrypted DEK from the database.
- Hash the password+salt.
- Generate the key to decrypt the DEK using hashed password+salt.
- Decrypt the DEK using the generated key and the IV.
- 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?
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.