为什么PHP crypt()将salt添加到哈希?

时间:2011-01-26 17:22:22

标签: php security encryption hash

我正在研究构建一个登录系统,当你将2位数的盐传递给crypt()函数时读取php手册后,它返回一个哈希字符串,字符串的前2位是盐你用过。

示例:

$salt = "kr";
echo crypt("mysecret",$salt); //returns "kreOI.F7eOQMY"

我的第一个想法是,这不会帮助那些试图扭转哈希值的人吗?

我在维基百科上查了salt说:

  

为了最好的安全性,盐值保密。

所以我不明白为什么crypt函数会返回所有使用salt值前面的哈希值?

这有什么理由吗?这应该是一个安全问题吗?

6 个答案:

答案 0 :(得分:29)

维基百科文章的作者将盐与搜索空间的概念混为一谈,暗示盐是一种阻止暴力攻击的方法。混淆这些想法并没有改善安全性;无法识别和描述这两个问题的人不是一个可靠的指南。

salt的目的是阻止预先计算的查找表(如Rainbow表)。 Salt可以防止攻击者在“时间”内交换“空间”。每一点盐都会使表的存储要求翻倍;两个字节的盐会产生很大的(65536倍)差异,但是八个字节需要不存在的“yottabyte”存储设备用于查找表。

盐必须存放在某处。如果你有一个有效的方法来保持“秘密”,为什么不用它来存储密码而忘记完全散列?没有;如果你想要真正的安全性,你需要将系统设计为免受强力攻击,即使攻击者知道盐。 该文章假设盐可以保密,应视为 false。

通过密钥加强(应用哈希函数数千次)和密码选择规则(最小长度,数字,特殊字符)可以最好地防止暴力攻击。

假设盐不能保密,鼓励更好的密钥加强和密码选择,这将导致更安全的系统。

答案 1 :(得分:9)

我应该评论Crypt没有Marc B听起来那么糟糕,并且实际上可能是获得良好哈希的最简单方法,只要你不依赖它像MD5这样较弱的方案。

见:

How do you use bcrypt for hashing passwords in PHP?

http://uk.php.net/manual/en/function.crypt.php

http://www.openwall.com/phpass/

答案 2 :(得分:3)

是的,盐应该保密,但密码哈希也是如此。他们在同一个地方保持同样的秘密是完全可以接受的。要根据哈希检查密码,您必须将salt与密码组合,然后根据哈希检查它。因此,任何有权查看密码哈希的用户或进程也应该有权查看salt,因为密码哈希本身对于检查密码没有用(除非您要强制使用盐)。

盐的目的是,如果两个不同的用户拥有相同的密码,他们将散列到不同的东西。这也意味着字典攻击要复杂得多,因为您不能只散列所有可能的密码,然后根据用户密码哈希列表检查它们以查找多个用户的密码。相反,您必须尝试单个盐的密码才能找到一个用户的密码,或尝试使用多种盐的可能密码的所有组合来查找匹配。但是盐的知识本身并不意味着你可以反转密码哈希。它只是意味着您可以对密码哈希进行字典攻击。

如果你能找到一种方法来保持盐的安全性比哈希值更安全,那肯定不会是坏事,但是当任何需要访问的程序需要访问时,很难看出这是如何可行的。两者。

答案 3 :(得分:1)

crypt()函数已过时。在使用影子密码支持之前,它被用于散列旧式Unix系统的密码。盐在那里增加了强制密码的暴力的复杂性。但是,由于密码子系统随机生成盐,因此必须以明文形式存储,以便将来的任何密码操作都能正常工作。如果在加密之前将盐嵌入密码中,则没有实用的方法来验证密码 - 无论何时进行密码检查,您都必须尝试每一种可能的盐 - 非常不切实际。因此,盐被添加到加密密码之前,因此您可以将其再次取出以备将来使用。

crypted password: xxabcdefghijklmn
                  ^^- salt
                    ^^^^^^^^^^^^^^-- crypted pw

if ('xx' + crypt('xx' + password) == 'crypted string') then
     password is ok
endif

这些天,crypt()是谷物盒解码器环的安全等价物。出于历史目的,低安全性“谁关心它是否被破解”存储。对于任何现代密码使用,你最好使用更现代的哈希,例如sha1 / sha256 / md5。甚至md5这些天被认为是破碎的,sha1边缘有裂缝,并且(最后我检查过)sha256仍然是安全的。

答案 4 :(得分:1)

将salt附加到has,以便在获取密码时知道要使用哪个salt,并希望查看它是否与哈希相匹配。这里的想法是为每个密码使用不同的盐,以便某人无法预先计算哈希表。

您还可以为每个密码添加第二个盐(对所有密码都相同),而不是告诉任何人它是什么。

答案 5 :(得分:1)

PHP crypt从UNIX crypt()函数继承此行为,该函数用于在UNIX passwd文件中生成密码哈希值。有必要将盐存储在某处,或者您以后无法验证密码是否正确。对于passwd文件,简单的行为只是将salt(总是两个字符)添加到加密密码的开头,这使得将它存储在单个字段中变得简单。

盐值应保密的说法可以被误解。为了获得最佳实践,您不应该以不应发布密码哈希值的方式发布盐。为攻击者提供哈希和盐,使他们可以轻松地进行暴力攻击,而不会给您的系统带来可疑的流量。但是,即使攻击者可以同时看到salt和哈希密码,系统仍然应该是安全的。

事实上,没有任何地方可以存储哈希,原则上哈希不会以与哈希密码完全相同的方式对其进行攻击。如果密码检查代码可以访问它,那么您必须假设某个受到系统攻击的人也可以访问它。