我不太明白盐对密码的作用。据我所知,它的主要用途是阻止彩虹桌的攻击。然而,我所看到的实现这一点的方法似乎并没有真正使问题变得更难。

我看过很多教程,建议盐可以这样使用:

$hash =  md5($salt.$password)

原因是哈希现在映射的不是原来的密码,而是密码和盐的组合。但是输入$salt=foo和$password=bar和$hash=3858f62230ac3c915f300c664312c63f。现在有一张彩虹表的人可以反向哈希,得到输入“foobar”。然后他们可以尝试所有的密码组合(f, fo, foo,…)Oobar, obar, bar, ar)获取密码可能还需要几毫秒的时间,但仅此而已。

我看到的另一种用法是在我的linux系统上。在/etc/shadow中,散列密码实际上与salt一起存储。例如,salt为“foo”,password为“bar”将哈希为$1$foo$te5SBM.7C25fFDu6bIRbX1。如果黑客以某种方式获得了这个文件,我不知道盐有什么用途,因为te5SBM的反向哈希。已知7C25fFDu6bIRbX包含“foo”。

感谢大家对这件事的解释。

编辑:谢谢你的帮助。总结一下我的理解,salt使散列密码更加复杂,从而使它不太可能存在于预先计算的彩虹表中。我之前误解的是,我假设所有哈希表都存在一个彩虹表。


当前回答

其他答案似乎并没有解决你对这个话题的误解,所以下面是:

盐的两种不同用途

我看过很多教程,建议盐可以这样使用: $hash = md5($salt.$password) […] 我看到的另一种用法是在我的linux系统上。在/etc/shadow中,散列密码实际上与salt一起存储。

您总是必须将salt与密码存储在一起,因为为了验证用户根据密码数据库输入的内容,您必须将输入与salt结合起来,对其进行哈希,并将其与存储的哈希进行比较。

哈希的安全性

现在有一张彩虹表的人可以反向哈希,得到输入“foobar”。 […] 因为te5SBM的反向哈希。已知7C25fFDu6bIRbX包含“foo”。

这样反转哈希是不可能的(至少在理论上是这样)。“foo”的哈希和“saltfoo”的哈希没有任何共同之处。即使在加密哈希函数的输入中改变一个比特,也会完全改变输出。

这意味着你不能用普通密码构建一个彩虹表,然后用一些盐“更新”它。你必须从一开始就把盐考虑进去。

这就是为什么你首先需要一张彩虹桌的全部原因。因为您无法从哈希中获得密码,所以您将预先计算最有可能使用的密码的所有哈希值,然后将您的哈希值与它们的哈希值进行比较。

盐的质量

但是输入$salt=foo

“foo”是一个非常糟糕的盐选择。通常你会使用一个随机值,用ASCII编码。

此外,每个密码都有自己的盐,(希望)不同于系统上的所有其他盐。这意味着,攻击者必须单独攻击每个密码,而不是希望其中一个哈希值与数据库中的一个值匹配。

这次袭击

如果黑客以某种方式拿到了这份文件,我不明白盐有什么用,

彩虹表攻击总是需要/etc/passwd(或任何使用的密码数据库),否则如何比较彩虹表中的哈希值和实际密码的哈希值?

至于目的:假设攻击者想要为10万个常用英语单词和典型密码(想想“秘密”)构建一个彩虹表。如果没有盐,她将不得不预先计算10万个哈希值。即使使用2个字符的传统UNIX salt(每个字符都是64个选项之一:[a-zA-Z0-9. /]),她也必须计算和存储4,096,000,000散列…相当大的进步。

其他回答

据我所知,盐是为了使字典攻击更加困难。

众所周知,许多人会使用常见的单词作为密码,而不是看似随机的字符串。

因此,黑客可以利用这一点,而不是仅仅使用蛮力。他不会找像aaa, aab, aac这样的密码……而是使用单词和常用的密码(比如指环王的名字!,))

所以如果我的密码是Legolas,黑客可以尝试一下,并通过“几次”尝试来猜测它。但是,如果我们对密码加盐,它就变成了fooLegolas,哈希值就会不同,所以字典攻击就会不成功。

希望有帮助!

盐的一个目的是打败预先计算的哈希表。如果某人有一个包含数百万预计算哈希值的列表,他们将无法查找$1$foo$te5SBM。7C25fFDu6bIRbX1在表中尽管他们知道哈希和盐。他们还是要用蛮力。

另一个目的,正如Carl S提到的,是使暴力强制哈希列表更加昂贵。(给它们不同的盐)

即使盐是公开的,这两个目标仍然可以实现。

盐会导致彩虹表攻击失败的原因是,对于n位盐,彩虹表必须比没有盐的表大2^n倍。

你使用“foo”作为盐的例子可以使彩虹表变大1600万倍。

以卡尔的128位盐为例,这使表变大了2^128倍,这很大了,换句话说,要多久才会有人有这么大的便携式存储器?

当破解单个密码时,公共盐不会使字典攻击更加困难。正如您所指出的,攻击者可以访问散列密码和salt,因此在运行字典攻击时,她可以在试图破解密码时简单地使用已知的salt。

公共盐做了两件事:使破解大量密码列表更加耗时,并使使用彩虹表变得不可行的。

To understand the first one, imagine a single password file that contains hundreds of usernames and passwords. Without a salt, I could compute "md5(attempt[0])", and then scan through the file to see if that hash shows up anywhere. If salts are present, then I have to compute "md5(salt[a] . attempt[0])", compare against entry A, then "md5(salt[b] . attempt[0])", compare against entry B, etc. Now I have n times as much work to do, where n is the number of usernames and passwords contained in the file.

To understand the second one, you have to understand what a rainbow table is. A rainbow table is a large list of pre-computed hashes for commonly-used passwords. Imagine again the password file without salts. All I have to do is go through each line of the file, pull out the hashed password, and look it up in the rainbow table. I never have to compute a single hash. If the look-up is considerably faster than the hash function (which it probably is), this will considerably speed up cracking the file.

但是如果密码文件被加了盐,那么彩虹表就必须包含“salt”。pre-hashed密码”。如果盐是完全随机的,这是不太可能的。在我的常用预哈希密码列表(彩虹表)中,我可能会有“hello”、“foobar”和“qwerty”这样的东西,但我不会预先计算“jX95psDZhello”或“LPgB0sdgxfoobar”或“dZVUABJtqwerty”这样的东西。这将使彩虹桌大得令人望而却步。

因此,salt将攻击者减少到每行每次尝试一次计算,当加上足够长、足够随机的密码时,(一般来说)是不可破解的。

我假设您正在使用PHP——md5()函数和$前面的变量——那么,您可以尝试查看本文的影子密码HOWTO特别是第11段。

另外,如果您害怕使用消息摘要算法,则可以尝试真正的密码算法,例如mcrypt模块提供的算法,或者更强大的消息摘要算法,例如提供mhash模块的算法(sha1、sha256等)。

我认为更强的消息摘要算法是必须的。已知MD5和SHA1存在冲突问题。