I'm developing a kind of secret vault server application. The basic principle is similar to DPAPI where each secret will have its own unique random KEY/IV pair and and that KEY/IV pair will be encrypted with a PBKDF2 derived key from user password.
I have doubts as to how properly handle key derivation and authentication. This is what I came up with:
User registration:
- User supplies username and password
- Generate random salt using CPRNG. Store the salt with user record.
- Derive a KEY and IV from password using PBKDF2
- Generate a random master KEY/IV pair and encrypt this master pair with generated KEY/IV pair from step 3 using AES-GCM. Store encrypted KEY and encrypted IV separately in two records, store TAG in third record.
User verification:
- User supplies username and password
- Use stored salt and supplied password to derive a KEY and IV
- Use derived KEY/IV pair to try to decrypt master key. If verification fails, authentication fails and user is not let in
All encryption is done on server side. Communication is secured with TLS but this is not the topic nor is the sizes of key, IV or salt. Let's assume I will choose the sizes correctly. The scheme I choose to use must protect the data even if database is stolen.
My questions about this are:
- Is it safe to generate IV along with KEY from PBKDF2 when using and storing salt for each user or should IV also be randomly generated and stored along with salt? When generating IV from PBKDF2 I'm basically choosing for it to be part of the key, ie a secret. Using a sufficiently large salt per user would guarantee that no two generated KEY/IV pairs exist even if users have same passwords.
- Should randomly generated master KEY pair be stored with both KEY and IV encrypted or should IV be stored in plain text?
- If you store both encrypted, it is safe to store them in two separate records or should they be encrypted together (concatenated) and stored in a single record? This is regarding IV reuse since two records are now encrypted with same KEY/IV pair.
Thank you!