Cuando el usuario inicie sesión por primera vez, su software le pedirá una nueva contraseña.
En este momento el DB debe estar vacío.
Ahora tienes un UserPassword y una base de datos vacía.
Por lo tanto, el software genera una nueva DBdataKey aleatoria que se utilizará para cifrar / descifrar el contenido de la base de datos. Para cifrar / descifrar utilice uno de los muchos algoritmos conocidos, como AES o uno similar.
Ahora creas 2 cadenas de sal aleatorias: PasswordSalt y DBdataKeySalt .
Almacene PasswordSalt y DBdataKeySalt en la base de datos como un texto claro.
Use una función hash como pbkdf2 (o algo como SHA2 o superior) con UserPassword y DBdataKeySalt para obtener un DBdataKeyEncryptionKey
Ahora:
DBdataKey es la clave que utiliza para cifrar / descifrar el contenido de la base de datos
DBdataKeyEncryptionKey es la clave que utiliza para cifrar / descifrar la DBdataKey
Use una función hash como pbkdf2 (o algo como SHA2 o superior) con UserPassword y PasswordSalt para crear HashedSaltedUserPassword , un hasted salh versión de UserPassword , luego use DBdataKey para cifrar HasedSaltedUserPassword antes de almacenarlo en la base de datos.
De ahora en adelante, puede utilizar DBdataKey para cifrar / descifrar los datos desde / hacia la base de datos.
Ahora, cuando el usuario abre la aplicación, pídale la contraseña, luego use la contraseña ingresada con DBdataKeySalt (que se almacena en texto claro) para regenerar la DBdataKeyEncryptionKey , y luego usa el DBdataKeyEncryptionKey para descifrar el DBdataKey , y así puedes usar el DBdataKey descifrado para leer el DB.
Ahora use DBdataKey para descifrar el HashedSaltedUserPassword y compárelo con el que regeneró usando la contraseña ingresada y el PasswordSalt (que es almacenado en texto claro) solo para verificar que la información de inicio de sesión sea correcta.
Si el usuario ingresa la contraseña incorrecta, cuando use DBdataKeyEncryptionKey para descifrar la DBdataKey , la función de descifrado le dará un valor diferente (basura). Usar ese valor (incorrecto) para descifrar el HashedSaltedUserPassword dará como resultado más valores de basura, que no coincidirán con el hash.
Cuando el usuario cambia la Contraseña del usuario , solo necesita descifrar la DBdataKey con la contraseña anterior y volver a cifrarla con la nueva contraseña, pero la DBdataKey no cambiará, por lo que no tendrá que volver a cifrar el contenido de la base de datos cuando el usuario cambie su contraseña.
Referencia: No he inventado nada, esto es solo una mezcla de dos técnicas bien conocidas: