Tengo un escenario en el que el usuario debe guardar las contraseñas para usarlas más adelante. No puedo usar el hash porque necesito obtener la contraseña original para su uso posterior.
Por ejemplo, considere una aplicación de remitente de correo electrónico donde un usuario ingresaría inicialmente una contraseña para su cuenta de correo electrónico y la aplicación la almacenaría en forma cifrada y cuando la aplicación necesita enviar un correo electrónico, descifrará la contraseña y la usará para enviar el correo.
Ahora, esto es lo que estoy haciendo:
- La aplicación almacena una clave maestra (generada mediante RNGCryptoServiceProvider) en la base de datos
-
Tanto la Clave como la IV para AES se derivan de la clave maestra usando Rfc2898DeriveBytes (contraseña = clave maestra y salt = user_id para 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 ..... .....
¿Estoy haciendo esto de la manera correcta? ¿Hay correcciones por hacer? Además, ¿son los tamaños que se utilizan (para el tamaño de clave, tamaño de clave maestra, etc.) lo suficientemente buenos?
Algunas preguntas más (solo para saber más):
-
¿Se considera que las claves derivadas (claves AES separadas para cada usuario) de una clave maestra de alta entropía no son dignas (o peor)? (Es decir, usar solo la clave maestra como clave AES es más que suficiente). Si es así, ¿por qué ?, mi argumento es: si alguien deduce la clave AES para un usuario en particular, él / ella no podrá deducir la clave maestra, por lo que otros usuarios estarán seguros. Encontré: "Diversificación de claves", que se utiliza en algunas aplicaciones de tarjetas inteligentes en las que obtienen una clave AES separada de una clave maestra para cada instancia (¿no se aplica lo mismo aquí?)
-
¿Podemos simplemente usar PBKDF para derivar claves en este escenario, o deberíamos usar un KBKDF? Si es así, ¿podría mencionar una biblioteca (preferiblemente de .NET framework) que ofrece KBKDF? Sé que RfcDerivativeBytes usa un PBKDF para derivar una clave, pero no pude averiguar cómo derivar una clave usando KBKDF.