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

我说的是这样做:

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

而不是这样:

$hashed_password = hash($plaintext_password);

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

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

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

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


当前回答

一般来说,它不会为双重哈希或双重加密提供额外的安全性。如果你能分解一次散列,你就能再分解一次。不过,这样做通常不会损害安全性。

在使用MD5的例子中,您可能知道有一些碰撞问题。“双重哈希”并不能真正帮助防止这种情况,因为相同的碰撞仍然会导致相同的第一个哈希,然后您可以再次MD5以获得第二个哈希。

这确实可以防止字典攻击,比如那些“反向md5数据库”,但盐也是如此。

在切线上,双重加密某些东西并不能提供任何额外的安全性,因为它所做的只是导致一个不同的密钥,这是实际使用的两个密钥的组合。因此寻找“钥匙”的工作不会加倍,因为实际上不需要找到两把钥匙。这对于哈希并不适用,因为哈希的结果通常与原始输入的长度不同。

其他回答

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

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

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

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

正如本文中的一些回应所建议的,在某些情况下,它可能会提高安全性,而在其他情况下,它肯定会损害安全性。有一种更好的解决方案肯定会提高安全性。不是将计算哈希的次数翻倍,而是将盐的大小翻倍,或者将哈希中使用的比特数翻倍,或者两者都做!从SHA-245跳到SHA-512。

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

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

一般来说,它不会为双重哈希或双重加密提供额外的安全性。如果你能分解一次散列,你就能再分解一次。不过,这样做通常不会损害安全性。

在使用MD5的例子中,您可能知道有一些碰撞问题。“双重哈希”并不能真正帮助防止这种情况,因为相同的碰撞仍然会导致相同的第一个哈希,然后您可以再次MD5以获得第二个哈希。

这确实可以防止字典攻击,比如那些“反向md5数据库”,但盐也是如此。

在切线上,双重加密某些东西并不能提供任何额外的安全性,因为它所做的只是导致一个不同的密钥,这是实际使用的两个密钥的组合。因此寻找“钥匙”的工作不会加倍,因为实际上不需要找到两把钥匙。这对于哈希并不适用,因为哈希的结果通常与原始输入的长度不同。

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

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