在设备上存储所有数据时创建强密码方案

时间:2010-12-14 23:03:59

标签: java android encryption password-protection

背景
我一直在开发一个Android应用程序,它将数据存储在本地数据库中作为我的宠物项目。最近,我决定要密码保护应用程序并加密数据库。现在,我知道在运行中加密数据库的复杂性并且(考虑到我的应用程序的预期使用模式)决定只加密整个数据库文件而不是尝试存储加密的列值等。到目前为止,我已经实现了一个系统,该系统将在每次启动应用程序时或每当用户导航离开我的活动时提示输入密码(以说明用户按下主页键并且应用程序未及时被杀死)。

目前,我正在尝试确定如何对密码进行哈希处理以及在何处存储密码。鉴于所有内容都必须存储在设备上,我基本上将密码哈希和盐视为已经泄密,因为任何花了10分钟阅读的人都可以根据给定的设备访问我的数据库/首选项。

鉴于上述假设,我已经开发出了我认为仍应提供非常强大的安全性的东西。我希望从社区获得一些反馈,看看我的解决方案是否可行或是否有更好的方法。

我的想法是在应用程序的第一次运行时生成10个不同的随机盐值。这些值将与应用程序首选项(而不是数据库)中的实际最终密码哈希一起存储。请注意,只有一个密码,它用于用户身份验证和数据库解密。每当提出质询时,密码将按如下方式进行散列处理:

  1. 明文密码经过哈希处理。
  2. 哈希密码通过与标准UPC条形码相同的校验和算法运行。这将导致0到9(含)之间的值。
  3. 此校验和数字将用作salt值数组的索引。此单个salt值将附加到当前哈希值。
  4. 然后将对新的hash + salt值进行哈希处理,并重复步骤2 - 3。
  5. 我认为,这个过程进行5次迭代会产生5 ^ 10个不同的盐组合,并且应该使任何类型的彩虹攻击几乎不可能。一旦验证了最终的哈希值,它就可以用来解密数据库。

    现在,我意识到这听起来像一个简单的手机应用程序的矫枉过正。它是。但是,这是我的宠物项目,为什么不呢?

    问题:
    那么,在那段文字之后,这种方法是否合理还是有更好的方法?我认为,有了这个,最薄弱的环节是内存中的攻击还是我弄错了?非常感谢任何反馈。

    提前谢谢。

    -cheers

5 个答案:

答案 0 :(得分:5)

我不明白。如果要加密数据库,为什么需要在任何地方存储密码的哈希值?

使用PBKDF2之类的东西从密码中导出加密密钥,密码存储在用户的大脑中。用它来加密数据库。

当用户想要解密数据库时,提示他们输入密码。再次从中获取密钥,并解密数据库。

您存储密码哈希以进行身份​​验证。但这是加密,而不是身份验证。


假设您有一个哈希函数,它将salt,多次迭代和一个密码作为输入,并返回一个哈希作为输出:byte[] hash(byte[] salt, int count, char[] password)。在第一次运行应用程序时随机生成一个salt,并散列新选择的密码。将此salt和生成的哈希存储在应用程序首选项中。然后随机生成另一个盐,并用它散列密码。使用生成的哈希作为数据库加密密钥,但仅在应用程序首选项中存储新的盐。

稍后,当用户希望使用该应用程序时,提示输入密码,并使用第一个哈希值对其进行哈希处理。如果它与存储的哈希匹配,则用户已经证明他们知道解密密码。使用第二个盐再次哈希,并使用生成的密钥解密数据库。

加密密钥的后续推导可能就是您的意思;如果您打算直接使用密码作为加密密钥,我正在尝试明确该步骤。有两种不同的盐,一种用于身份验证,另一种用于加密,将允许您安全地使用相同的密码用于两种目的。

答案 1 :(得分:0)

我所做的是使用数据库行的记录ID作为salt。你可以散列行的id并将其用于一个更好的盐。

如果您只有十几个密码,那么它的安全性与您正在进行的密码大致相似。但是如果你有数百或数万,那么为每个ID计算一个字典表就变得不可行了。

答案 2 :(得分:0)

好的......假设你的哈希方法并不弱,那么盐是否已知并不重要 - 盐只是让2个拥有相同密码的用户有不同的哈希值 - 随便检查哈希值不会导致相同的密码显而易见。 Salt应该是每个用户唯一

假设(恶意)用户拥有root用户,那么你可以采取措施防止他们破坏你的应用程序,除了加密 - 具体来说,用户理论上可以获取你的二进制文件,对其进行反编译以确定如何对用户进行身份验证,绕过它然后只需遵循解密机制 - 由于加密密钥与您的方案中的用户PW无关,因此必须将其存储在某个地方 - 如果应用程序可以读取它,那么root

唯一真正安全的方法是拥有一个与DB加密密钥相关的单用户(或至少是单密码)。

除此之外,你可以期待的最好的办法是让恶意用户难以为之付出代价。

答案 3 :(得分:0)

即使有10个盐值,您仍然在技术上容易受到rainbow table攻击。他们只需要用你的盐制作10个彩虹表。他们需要一段时间来生成所有新的彩虹表,我们正在谈论几天或几周。一旦他们拥有了表格,就可以将其用于下载该应用程序的所有用户。如果您为每个密码存储一个唯一的盐,这将要求他们完成每个密码的整个过程,这对于一个密码来说只需要很多工作。问题是有人想要通过所有麻烦来获得一个密码。这是关于存储密码"You're Probably Storing Passwords Incorrectly"

的好文章

答案 4 :(得分:0)

我无法发现这个计划中的任何重大缺陷。但是,它没有增加最佳实践腌制的安全性;即,每次用户设置或更改其密码时,都会生成一个新的每用户盐。

此方案确实增加了一个额外的攻击点。如果盐的生成方式存在缺陷(例如可预测性),那么如果您将自己限制为同时生成的10种盐,则可能更容易开发。这可能会让攻击者更有能力猜测可能的盐是什么,从而创建彩虹表。

但是你的方法(IMO)的主要问题只是复杂性。