我不太明白盐对密码的作用。据我所知,它的主要用途是阻止彩虹桌的攻击。然而,我所看到的实现这一点的方法似乎并没有真正使问题变得更难。
我看过很多教程,建议盐可以这样使用:
$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散列…相当大的进步。
大多数打破基于哈希的加密的方法依赖于暴力攻击。彩虹攻击本质上是一种更有效的字典攻击,它的设计目的是使用低成本的数字存储来创建一个映射,将大量可能的密码子集映射到哈希表,并促进反向映射。这种攻击之所以有效,是因为许多密码要么相当短,要么使用几种基于单词的格式模式之一。
Such attacks are ineffective in the case where passwords contain many more characters and do not conform to common word based formats. A user with a strong password to start with won't be vulnerable to this style of attack. Unfortunately, many people do not pick good passwords. But there's a compromise, you can improve a user's password by adding random junk to it. So now, instead of "hunter2" their password could become effectively "hunter2908!fld2R75{R7/;508PEzoz^U430", which is a much stronger password. However, because you now have to store this additional password component this reduces the effectiveness of the stronger composite password. As it turns out, there's still a net benefit to such a scheme since now each password, even the weak ones, are no longer vulnerable to the same pre-computed hash / rainbow table. Instead, each password hash entry is vulnerable only to a unique hash table.
Say you have a site which has weak password strength requirements. If you use no password salt at all your hashes are vulnerable to pre-computed hash tables, someone with access to your hashes would thus have access to the passwords for a large percentage of your users (however many used vulnerable passwords, which would be a substantial percentage). If you use a constant password salt then pre-computed hash tables are no longer valuable, so someone would have to spend the time to compute a custom hash table for that salt, they could do so incrementally though, computing tables which cover ever greater permutations of the problem space. The most vulnerable passwords (e.g. simple word based passwords, very short alphanumeric passwords) would be cracked in hours or days, less vulnerable passwords would be cracked after a few weeks or months. As time goes on an attacker would gain access to passwords for an ever growing percentage of your users. If you use a unique salt for every password then it would take days or months to gain access to each one of those vulnerable passwords.
As you can see, when you step up from no salt to a constant salt to a unique salt you impose a several orders of magnitude increase in effort to crack vulnerable passwords at each step. Without a salt the weakest of your users' passwords are trivially accessible, with a constant salt those weak passwords are accessible to a determined attacker, with a unique salt the cost of accessing passwords is raised so high that only the most determined attacker could gain access to a tiny subset of vulnerable passwords, and then only at great expense.
这正是现在的情况。您永远无法完全保护用户不受糟糕密码选择的影响,但您可以提高泄露用户密码的成本,使泄露一个用户密码的代价变得高昂。
我正在寻找一个好的方法来应用盐,发现这篇优秀的文章与示例代码:
http://crackstation.net/hashing-security.htm
作者建议对每个用户使用随机salt,这样访问salt就不会使整个哈希列表容易被破解。
To Store a Password:
Generate a long random salt using a CSPRNG.
Prepend the salt to the password and hash it with a standard
cryptographic hash function such as SHA256.
Save both the salt and the hash in the user's database record.
To Validate a Password :
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same hash function.
Compare the hash of the given password with the hash from the database. If they
match, the password is correct. Otherwise, the password is incorrect.