用 Java 加密 SQLite 数据库中的数据 - 如何存储密钥?

信息安全 加密 爪哇 数据库
2021-09-05 18:40:55

因此,在我开始之前先了解一些上下文可能会很方便。我正在开发一个 Java 桌面应用程序,它将使用 SQLite 数据库来存储/处理数据。该应用程序将利用身份验证来访问程序以编辑数据、添加/删除数据等。但我不希望攻击者能够在没有先对 Windows 进行身份验证的情况下拉出笔记本电脑的硬盘驱动器并访问数据。

我的问题是,如果我要在插入 SQLite 数据库之前使用...AES256 对某些数据进行加密,是否可以在无需用户插入密码且无需在应用程序中硬编码密码的情况下解密数据?我真的认为用户必须记住 2 个密码(一个用于应用程序身份验证,一个用于数据库加密/解密)的开销是不可行的,因为如果他们忘记了加密/解密密码,他们的数据就消失了。

你们有没有遇到任何可以分享或提出一些可能有帮助的想法的解决方案?

1个回答

当用户第一次登录时,您的软件将要求输入新密码。此时数据库应该是空的。

现在您有一个UserPassword和一个空数据库。因此,软件生成一个新的随机DBdataKey,用于加密/解密 DB 内容。要加密/解密,请使用许多已知算法之一,如 AES 或类似算法。

现在您创建 2 个随机盐字符串:PasswordSaltDBdataKeySaltPasswordSaltDBdataKeySalt以明文形式存储在数据库中。

使用带有UserPasswordDBdataKeySalt的散列函数(如 pbkdf2(或类似 SHA2 或更好的东西))来获取DBdataKeyEncryptionKey

现在: DBdataKey是您用来加密/解密数据库内容 的密钥DBdataKeyEncryptionKey是您用来加密/解密DBdataKey的密钥

使用像 pbkdf2(或类似 SHA2 或更好的东西)这样的哈希函数和UserPasswordPasswordSalt来创建HashedSaltedUserPassword ,这是UserPassword的加盐哈希版本,然后使用DBdataKey在将HasedSaltedUserPassword存储到数据库之前对其进行加密

从现在开始,您可以使用DBdataKey加密/解密来自/来自 DB 的数据。

现在,当用户打开应用程序时,您向他询问密码,然后使用输入的密码和DBdataKeySalt(以明文形式存储)重新生成DBdataKeyEncryptionKey,然后使用获得的DBdataKeyEncryptionKey解密DBdataKey,这样您就可以使用解密的DBdataKey读取数据库。

现在使用DBdataKey解密HashedSaltedUserPassword并将其与使用输入的密码和PasswordSalt(以明文形式存储)重新生成的密码进行比较,以再次检查登录信息是否正确。

如果用户输入了错误的密码,当您使用DBdataKeyEncryptionKey解密DBdataKey时,解密函数会给您一个不同的值(垃圾)。使用该(错误的)值来解密HashedSaltedUserPassword将导致更多垃圾值,这些值与哈希不匹配。

当用户更改UserPassword时 ,您只需要用旧密码解密DBdataKey 并用新密码重新加密,但DBdataKey不会改变,因此您不需要重新加密db内容时用户更改其密码。

参考:我没有发明任何东西,这只是两种众所周知的技术的混合:

  • 如何完成用户登录和密码加盐/散列
  • 如何实现动态磁盘加密(应用于数据库加密/解密)