当用户第一次登录时,您的软件将要求输入新密码。此时数据库应该是空的。
现在您有一个UserPassword和一个空数据库。因此,软件生成一个新的随机DBdataKey,用于加密/解密 DB 内容。要加密/解密,请使用许多已知算法之一,如 AES 或类似算法。
现在您创建 2 个随机盐字符串:PasswordSalt和DBdataKeySalt。将PasswordSalt和DBdataKeySalt以明文形式存储在数据库中。
使用带有UserPassword和DBdataKeySalt的散列函数(如 pbkdf2(或类似 SHA2 或更好的东西))来获取DBdataKeyEncryptionKey
现在:
DBdataKey是您用来加密/解密数据库内容
的密钥DBdataKeyEncryptionKey是您用来加密/解密DBdataKey的密钥
使用像 pbkdf2(或类似 SHA2 或更好的东西)这样的哈希函数和UserPassword和PasswordSalt来创建HashedSaltedUserPassword ,这是UserPassword的加盐哈希版本,然后使用DBdataKey在将HasedSaltedUserPassword存储到数据库之前对其进行加密。
从现在开始,您可以使用DBdataKey加密/解密来自/来自 DB 的数据。
现在,当用户打开应用程序时,您向他询问密码,然后使用输入的密码和DBdataKeySalt(以明文形式存储)重新生成DBdataKeyEncryptionKey,然后使用获得的DBdataKeyEncryptionKey解密DBdataKey,这样您就可以使用解密的DBdataKey读取数据库。
现在使用DBdataKey解密HashedSaltedUserPassword并将其与使用输入的密码和PasswordSalt(以明文形式存储)重新生成的密码进行比较,以再次检查登录信息是否正确。
如果用户输入了错误的密码,当您使用DBdataKeyEncryptionKey解密DBdataKey时,解密函数会给您一个不同的值(垃圾)。使用该(错误的)值来解密HashedSaltedUserPassword将导致更多垃圾值,这些值与哈希不匹配。
当用户更改UserPassword时 ,您只需要用旧密码解密DBdataKey 并用新密码重新加密,但DBdataKey不会改变,因此您不需要重新加密db内容时用户更改其密码。
参考:我没有发明任何东西,这只是两种众所周知的技术的混合:
- 如何完成用户登录和密码加盐/散列
- 如何实现动态磁盘加密(应用于数据库加密/解密)