背景:
我一直在开发一个Android应用程序,该程序将数据存储在本地数据库中作为我的宠物项目。最近,我决定要用密码保护应用程序并加密数据库。现在,我知道了动态加密数据库的复杂性,并且(考虑到我的应用程序的预期使用模式)决定只加密整个数据库文件,而不是尝试存储加密的列值等。到目前为止,我已经实现了一个系统,该系统将在每次启动应用程序时或每当用户离开我的 Activity 时提示输入密码(以说明用户按下Home键并且未及时杀死应用程序)。
目前,我正在尝试确定如何对密码进行散列以及将密码存储在何处。鉴于所有内容都必须存储在设备上,因此我基本上将密码散列和盐类视为已被破坏,因为花了10分钟阅读内容的任何人都可以创建给定的设备并访问我的数据库/首选项。
考虑到上述假设,我已经开发出我认为仍然应该提供非常强大的安全性的工具。我想从社区中获得一些反馈,以查看我的解决方案是否可行或是否有更好的方法。
我的想法是在应用程序的第一次运行时生成10个不同的随机盐值。这些值将与实际的最终密码哈希一起存储在应用程序首选项中(而不是存储在数据库中)。请注意,只有一个密码,并且该密码用于用户身份验证和数据库解密。每当提出挑战时,密码将按以下方式进行哈希处理:
我认为将这个过程进行5次迭代将单独给出5 ^ 10种不同的盐组合,并且几乎不可能使任何类型的彩虹攻击。一旦最终哈希值正确无误,就可以用来解密数据库。
现在,我意识到这听起来像一个简单的手机应用程序的杀伤力。它是。但是,这是我的宠物项目,为什么不呢?
问题:
那么,在那段文字之后,这种方法是合理的还是有更好的方法?我认为,有了这一点,最薄弱的环节就是内存攻击,或者我误会了?任何反馈,不胜感激。
先感谢您。
-干杯
最佳答案
我不明白如果要加密数据库,为什么需要在任何地方存储密码的哈希值?
使用PBKDF2之类的东西,从存储在用户大脑中的密码中获取加密密钥。用它来加密数据库。
当用户想要解密数据库时,提示他们输入密码。再次从中派生密钥,然后解密数据库。
您存储密码哈希用于身份验证。但这是加密,而不是身份验证。
假设您有一个哈希函数,该函数将salt,多次迭代和一个密码作为输入,并返回一个哈希作为输出:byte[] hash(byte[] salt, int count, char[] password)
。在应用程序的第一次运行中随机生成一个盐,并哈希新选择的密码。将这种盐和生成的哈希存储在应用程序首选项中。然后随机生成另一个盐,并用它来哈希密码。将所得的哈希用作数据库加密密钥,但仅在应用程序首选项中存储新的salt。
稍后,当用户希望使用该应用程序时,提示输入密码,并使用第一个汉字对其进行哈希处理。如果它与存储的哈希匹配,则用户已证明他们知道解密密码。再次用第二种盐将其哈希,然后使用生成的密钥来解密数据库。
随后的加密密钥派生可能就是您的意思。如果您打算将密码直接用作加密密钥,则我想使这一步骤明确。具有两种不同的盐,一种用于身份验证,另一种用于加密,将使您可以安全地将相同的密码用于这两个目的。