在存储密码之前对密码进行两次哈希比只进行一次哈希更安全还是更不安全?

我说的是这样做:

$hashed_password = hash(hash($plaintext_password));

而不是这样:

$hashed_password = hash($plaintext_password);

如果它不太安全,你能提供一个好的解释(或一个链接)吗?

另外,使用哈希函数有区别吗?如果混合使用md5和sha1(例如),而不是重复相同的哈希函数,会有任何区别吗?

注1:当我说“双重哈希”时,我指的是对密码进行两次哈希,以使其更加模糊。我说的不是解决碰撞的技术。

注2:我知道我需要添加一个随机的盐,以真正使它安全。问题是用同一个算法进行两次哈希运算对哈希是有利还是有害。


当前回答

大多数答案都是由没有密码学或安全背景的人回答的。但他们错了。使用一个盐,如果可能的话,每个记录都是唯一的。MD5/SHA/等等太快了,与你想要的相反。PBKDF2和bcrypt较慢(这很好),但可以被asic /FPGA/ gpu击败(现在非常实惠)。因此需要一个内存硬的算法:输入scrypt。

这里是关于盐和速度的一个外行解释(但不是关于内存硬算法)。

其他回答

根据我所读到的,实际上可能建议将密码重新哈希数百或数千次。

其思想是,如果您可以花费更多的时间来编码密码,那么攻击者就需要做更多的工作来进行多次猜测以破解密码。这似乎是重哈希的优势——并不是说它在密码学上更安全,而是它只是需要更长的时间来生成字典攻击。

当然,计算机一直在变得更快,所以这种优势会随着时间的推移而减弱(或者需要您增加迭代)。

是的——它减少了可能匹配字符串的数量。

正如你已经提到的,咸散列更好。

这里有一篇文章:http://websecurity.ro/blog/2007/11/02/md5md5-vs-md5/,试图证明为什么它是等价的,但我不确定逻辑。一方面,他们假设没有软件可以分析md5(md5(文本)),但很明显,生成彩虹表是相当简单的。

我仍然坚持我的答案,md5(md5(文本))类型哈希的数量比md5(文本)哈希的数量少,增加了碰撞的机会(即使仍然是一个不太可能的概率),并减少了搜索空间。

我只是从实际的角度来看这个问题。黑客的目的是什么?为什么,当通过哈希函数时,产生所需哈希的字符组合。

你只保存最后一个哈希,因此,黑客只需要暴力破解一个哈希。假设在每个蛮力步骤中遇到所需哈希的概率大致相同,那么哈希的数量是不相关的。你可以做一百万次哈希迭代,它不会增加或降低一点安全性,因为在行的末尾仍然只有一个哈希需要破坏,并且破坏它的几率与任何哈希相同。

也许之前的发帖者认为输入是相关的;它不是。只要你在哈希函数中输入的东西产生了所需的哈希,它就会让你通过,正确的输入或错误的输入。

现在,彩虹桌是另一个故事。由于彩虹表只携带原始密码,因此哈希两次可能是一个很好的安全措施,因为包含每个哈希的每个哈希的每个哈希的彩虹表太大了。

当然,我只考虑OP给出的例子,它只是一个被散列的明文密码。如果你在散列中包含用户名或盐,情况就不同了;哈希两次是完全没有必要的,因为彩虹表已经太大了,无法实际包含正确的哈希。

不管怎样,我不是安全专家,但这只是我的经验之谈。

是的,重哈希减少了搜索空间,但不,这无关紧要——有效的减少是微不足道的。

重散列增加了强制执行所花费的时间,但只执行两次也是次优的。

您真正想要的是使用PBKDF2对密码进行哈希,这是一种经过验证的使用盐和迭代的安全哈希的方法。看看这个SO回应。

编辑:我几乎忘了-不要使用MD5!!!!使用现代加密哈希,如SHA-2家族(SHA-256, SHA-384和SHA-512)。

就我个人而言,我不会为多个散列而烦恼,但我会确保也散列UserName(或另一个User ID字段)以及密码,这样两个具有相同密码的用户最终不会得到相同的散列。为了更好地度量,我可能还会在输入字符串中加入其他常数字符串。

$hashed_password = md5( "xxx" + "|" + user_name + "|" + plaintext_password);