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

我说的是这样做:

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

而不是这样:

$hashed_password = hash($plaintext_password);

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

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

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

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


当前回答

只有当我在客户端对密码进行哈希,然后将该哈希(使用不同的盐)保存在服务器上时,双哈希才有意义。

这样,即使有人黑进了服务器(从而忽略了SSL提供的安全),他仍然无法获得清晰的密码。

是的,他将拥有入侵系统所需的数据,但他不能使用这些数据来破坏用户拥有的外部帐户。众所周知,人们几乎在任何事情上都使用相同的密码。

他获得清晰密码的唯一方法是在客户端安装一个keygen——这已经不是你的问题了。

简而言之:

客户端上的第一个散列可以在“服务器泄露”场景中保护您的用户。 如果有人掌握了数据库备份,那么服务器上的第二次哈希可以保护您的系统,这样他就不能使用这些密码连接到您的服务。

其他回答

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

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

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

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

我要大胆地说,在某些情况下,它更安全……不过先别给我投反对票!

从数学/密码学的角度来看,它不太安全,我相信其他人会给你一个比我更清楚的解释。

然而,存在大量的MD5哈希数据库,其中更可能包含“密码”文本而不是它的MD5。所以通过双重哈希,你会降低这些数据库的有效性。

当然,如果你使用盐,那么这个优点(缺点?)就消失了。

Yes.

绝对不要使用传统哈希函数的多次迭代,比如md5(md5(md5(password)))。在最好的情况下,您将获得安全方面的边际增加(这样的方案几乎不能对GPU攻击提供任何保护;直接把它输送出来。)在最坏的情况下,每次添加迭代都会减少哈希空间(从而减少安全性)。在安全性方面,明智的做法是做最坏的打算。

请使用由合格的密码学家设计的密码,该密码是有效的密码哈希,并能抵抗暴力破解和时空攻击。其中包括bcrypt、scrypt,在某些情况下还包括PBKDF2。基于glibc sha -256的散列也是可以接受的。

只有当我在客户端对密码进行哈希,然后将该哈希(使用不同的盐)保存在服务器上时,双哈希才有意义。

这样,即使有人黑进了服务器(从而忽略了SSL提供的安全),他仍然无法获得清晰的密码。

是的,他将拥有入侵系统所需的数据,但他不能使用这些数据来破坏用户拥有的外部帐户。众所周知,人们几乎在任何事情上都使用相同的密码。

他获得清晰密码的唯一方法是在客户端安装一个keygen——这已经不是你的问题了。

简而言之:

客户端上的第一个散列可以在“服务器泄露”场景中保护您的用户。 如果有人掌握了数据库备份,那么服务器上的第二次哈希可以保护您的系统,这样他就不能使用这些密码连接到您的服务。

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

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