I have a scenario where user entered passwords need to be stored for later use. I cannot use hashing because I need to get the original password for later use.
For example, consider an email sender app where a user would initially enter a password for his email account and the application would store it in encrypted form and when the application needs to send an email it would decrypt the password and use it to send the mail.
Now, here is what I am doing:
- The application stores a master key (generated using RNGCryptoServiceProvider) in the database
Both the Key and IV for AES are derived from the master key using Rfc2898DeriveBytes (password=masterkey and salt=user_id for Rfc2898DeriveBytes)
// the initial, one time masterkey generation, which will be used for all passwords byte[] masterKeyBytes = new byte[32]; new RNGCryptoServiceProvider().GetBytes(masterKeyBytes); // masterkey is saved in database string masterKey = Convert.ToBase64String(masterKeyBytes); // password encryption of a user's password var derivative = new Rfc2898DeriveBytes(masterKey, 128_bit_guid_of_user_id, numberOfIterations) var aes = new AesCryptoServiceProvider(); aes.Key = derivative.GetBytes(32); aes.IV = derivative.GetBytes(16); var encryptor = aes.CreateEncryptor(aes.Key, aes.IV); // get the encrypted password from encryptor ..... .....
Am I doing this the right way? Are there any corrections to be made? Also, are the sizes being used (for key size, masterkeysize, etc.) good enough?
Few more questions(just for the sake of knowing more):
Is deriving keys(seperate AES key for each user) from a high entropy master key considered not worthy(or worse)? (i.e using just the master key as AES key is more than enough). If so, why?, my argument is - should someone deduce the AES key for a particular user, he/she will still not be able to deduce the master key, so other users are safe. I came across - 'Key Diversification' which is used in some smart card apps where they derive a seperate AES key from a master key for each instance(does the same not apply here?)
Can we just use PBKDF to derive keys in this scenario, or should we use a KBKDF? if so, could you mention a library(preferably from .NET framework) that offers KBKDF? I know that RfcDerivativeBytes uses a PBKDF to derive a key, but i couldnt find out how to derive a key using KBKDF.