7

使用多种算法会使密码更安全吗?(或更少?)

为了清楚起见,我不是在谈论做这样的事情:

key = Hash(Hash(salt + password))

我说的是使用两个单独的算法并匹配两者:

key1 = Hash1(user_salt1 + password)
key2 = Hash2(user_salt2 + password)

然后在进行身份验证时要求两者匹配。我已经看到这是一种消除冲突匹配的方法,但我想知道意想不到的后果,例如创建“最弱链接”场景或提供使用户数据库更容易破解的信息,因为这种方法提供的数据比一个键就可以了。例如,将信息与哈希结合起来以更容易地找到它们。此外,如果真正消除了冲突,理论上您可以暴力破解实际密码,而不仅仅是匹配密码。实际上,您必须完全强制系统。

我实际上并不打算实现这一点,但我很好奇这是否实际上是对 single 标准实践的改进key = Hash(user_salt + password)

编辑:

很多好的答案,所以只是在这里推测,这应该是显而易见的,但是你确实通过使用两者来创建一个最薄弱的链接,因为可以尝试两种算法中较弱的匹配。例如,如果您使用弱(快速)MD5 和 PBKDF2,我会先暴力破解 MD5,然后尝试我找到的任何匹配项,因此通过使用 MD5(或其他),您实际上会使情况变得更糟。此外,即使两者都属于更安全的集合(例如 bcrypt+PBKDF2),您也会将其中一个破坏的风险加倍。

4

4 回答 4

7

这将有助于减少碰撞的可能性。正如您所提到的,有几个缺点(最弱的链接是一个大的)。

如果目标是减少冲突的可能性,最好的解决方案就是使用bcrypt具有更大散列的单个安全算法(例如)。

于 2013-01-15T16:00:28.803 回答
6

现代散列算法不关心冲突。关键不是要确保数据库中的每个散列都是唯一的。真正的重点是确保在您的数据库被盗或意外泄露的情况下,攻击者很难确定用户的实际密码。现代散列算法将错误密码识别为正确密码的机会实际上为零——这可能比你在这里得到的更多。

需要明确的是,您可能担心碰撞有两个主要原因。

  1. “正确”密码和提供的“错误”密码之间的冲突可能允许使用“错误”密码的用户进行身份验证。
  2. 如果用户 B 的密码已知,则两个用户密码之间的冲突可能会“泄露”用户 A 的密码。

问题 1 是通过使用强大/现代的哈希算法来解决的(并避免非常反智能的事情,例如仅根据密码哈希查找用户记录)。问题 2 可以通过适当的加盐来解决——每个密码都有一个“冗长”的唯一加盐。让我强调一下,适当的腌制仍然是必要的

但是,如果你在混合中添加哈希,你只是给潜在的攻击者更多的信息。我不确定目前是否有任何已知的方法可以从一对散列中“三角化”消息数据(密码),但是通过包含另一个散列并没有获得显着收益。办法利用附加信息的风险是不值得的。

于 2013-01-15T16:02:29.640 回答
4

要回答您的问题:

拥有独特的盐比拥有通用盐更好。H(S1 + PW1) , H(S2 + PW2) 使用多种算法可能比使用单个 H1(X) , H2(Y) 更好(但可能不是,正如 svidgen 提到的那样)

然而

这个问题的精神有点错误,原因有两个:

  1. 没有安全专家的指导,您不应该提出自己的安全协议。我知道这不是您自己的算法,但大多数安全问题都是因为使用不正确而开始的;算法本身通常是密封的。

  2. 您不应该使用 hash(salt+password) 将密码存储在数据库中。这是因为散列被设计为快速而不安全。使用今天的硬件(尤其是使用 GPU 处理)在旧算法中查找哈希冲突有点容易。您当然可以使用更新的安全散列算法(SHA-256 或 SHA-512),其中冲突不是问题 - 但为什么要冒险呢?

您应该研究基于密码的密钥派生函数( PBKDF2 ),该函数旨在缓慢地阻止此类攻击。通常它需要结合加盐、安全散列算法 (SHA-256) 并迭代几十万次。

对于登录时他们不会注意到这种减速的用户来说,使该功能花费大约一秒钟是没有问题的。但是对于攻击者来说,这是一场噩梦,因为他们必须为每次尝试执行这些迭代;显着减慢任何蛮力尝试。

看看支持 PBKDF 加密的库,这是一种更好的方法。 Jasypt是我最喜欢的 Java 加密之一。

请参阅这个相关的安全问题:如何安全地散列密码 和这个松散相关的SO 问题

于 2013-01-15T16:02:52.627 回答
0

将盐添加到密码哈希中以防止使用通用的预构建哈希表。攻击者将被迫根据他们的单词列表和你的随机盐生成新表。

如前所述,哈希被设计为快速是有原因的。要将它们用于密码存储,您需要减慢它们的速度(大量嵌套重复)。

您可以创建自己的特定于密码的哈希方法。本质上,将您喜欢的散列嵌套在salt+password和 上。

string MyAlgorithm(string data) {
  string temp = data;
  for i = 0 to X {
    temp = Hash3(Hash2(Hash1(temp)));
  }
}
result = MyAlgorithm("salt+password");

其中“X”是大量重复,足以使整个事情在体面的硬件上至少需要一秒钟。正如其他地方所提到的,这种延迟对普通用户(知道正确密码并且只等待一次)来说是微不足道的,但对攻击者(他们必须为每个组合运行这个过程)来说很重要。当然,这一切都是为了学习,使用适当的现有 API 可能更简单。

于 2013-01-15T16:28:54.907 回答