105

在工作中,我们有两种相互竞争的盐理论。我工作的产品使用用户名或电话号码之类的东西来加盐。本质上,对于每个用户来说都是不同的,但我们很容易获得。另一款产品为每个用户随机生成一个salt,并在用户每次更改密码时更改。然后在数据库中加密盐。

我的问题是第二种方法是否真的有必要?我可以从纯理论的角度理解它比第一种方法更安全,但从实用性的角度来看呢。现在要对用户进行身份验证,salt 必须未加密并应用于登录信息。

在考虑之后,我只是没有看到这种方法真正的安全收益。将盐从一个帐户更改为另一个帐户,即使攻击者知道如何快速确定每个帐户的值,仍然使某人尝试暴力破解散列算法非常困难。这是在假设密码足够强的情况下进行的。(显然,找到一组密码的正确哈希值,其中它们都是两位数字,比找到正确的 8 位密码哈希值要容易得多)。我的逻辑是不正确的,还是我遗漏了什么?

编辑:好的,这就是为什么我认为加密盐真的没有实际意义的原因。(让我知道我是否走在正确的轨道上)。

对于下面的解释,我们假设密码总是 8 个字符,salt 是 5,所有密码都由小写字母组成(这只是为了让数学更容易)。

每个条目使用不同的盐意味着我不能使用相同的彩虹表(实际上,如果我有一个足够大的大小,我可以使用,但我们暂时忽略它)。据我了解,这是真正的关键,因为要破解每个帐户,我必须重新发明轮子,可以说每个帐户。现在,如果我知道如何将正确的盐应用于密码以生成散列,我会这样做,因为盐实际上只是扩展了散列短语的长度/复杂性。所以我会减少我需要生成的可能组合的数量,以“知道”我的密码+盐从 13^26 到 8^26,因为我知道盐是什么。现在这使它变得更容易,但仍然非常困难。

因此,对盐进行加密。如果我知道盐是加密的,我不会先尝试解密(假设我知道它有足够的加密级别)。我会忽略它。而不是试图弄清楚如何解密它,回到前面的例子,我只生成一个更大的彩虹表,其中包含 13^26 的所有密钥。不知道盐肯定会减慢我的速度,但我认为它不会增加尝试首先破解盐加密的艰巨任务。这就是为什么我认为这不值得。想法?

这是一个链接,描述了密码在蛮力攻击下可以保存多长时间: http ://www.lockdown.co.uk/?pg=combi

4

10 回答 10

103

Hiding a salt is unnecessary.

A different salt should be used for every hash. In practice, this is easy to achieve by getting 8 or more bytes from cryptographic quality random number generator.

From a previous answer of mine:

Salt helps to thwart pre-computed dictionary attacks.

Suppose an attacker has a list of likely passwords. He can hash each and compare it to the hash of his victim's password, and see if it matches. If the list is large, this could take a long time. He doesn't want spend that much time on his next target, so he records the result in a "dictionary" where a hash points to its corresponding input. If the list of passwords is very, very long, he can use techniques like a Rainbow Table to save some space.

However, suppose his next target salted their password. Even if the attacker knows what the salt is, his precomputed table is worthless—the salt changes the hash resulting from each password. He has to re-hash all of the passwords in his list, affixing the target's salt to the input. Every different salt requires a different dictionary, and if enough salts are used, the attacker won't have room to store dictionaries for them all. Trading space to save time is no longer an option; the attacker must fall back to hashing each password in his list for each target he wants to attack.

So, it's not necessary to keep the salt secret. Ensuring that the attacker doesn't have a pre-computed dictionary corresponding to that particular salt is sufficient.


After thinking about this a bit more, I've realized that fooling yourself into thinking the salt can be hidden is dangerous. It's much better to assume the salt cannot be hidden, and design the system to be safe in spite of that. I provide a more detailed explanation in another answer.


However, recent recommendations from NIST encourage the use of an additional, secret "salt" (I've seen others call this additional secret "pepper"). One additional iteration of the key derivation can be performed using this secret as a salt. Rather than increasing strength against a pre-computed lookup attack, this round protects against password guessing, much like the large number of iterations in a good key derivation function. This secret serves no purpose if stored with the hashed password; it must be managed as a secret, and that could be difficult in a large user database.

于 2008-10-18T15:28:19.650 回答
45

The answer here is to ask yourself what you're really trying to protect from? If someone has access to your database, then they have access to the encrypted salts, and they probably have access to your code as well. With all that could they decrypt the encrypted salts? If so then the encryption is pretty much useless anyway. The salt really is there to make it so it isn't possible to form a rainbow table to crack your entire password database in one go if it gets broken into. From that point of view, so long as each salt is unique there is no difference, a brute force attack would be required with your salts or the encrypted salts for each password individually.

于 2008-10-17T19:03:00.123 回答
6

A hidden salt is no longer salt. It's pepper. It has its use. It's different from salt.

Pepper is a secret key added to the password + salt which makes the hash into an HMAC (Hash Based Message Authentication Code). A hacker with access to the hash output and the salt can theoretically brute force guess an input which will generate the hash (and therefore pass validation in the password textbox). By adding pepper you increase the problem space in a cryptographically random way, rendering the problem intractable without serious hardware.

For more information on pepper, check here.

See also hmac.

于 2013-10-10T21:16:34.810 回答
3

My understanding of "salt" is that it makes cracking more difficult, but it doesn't try to hide the extra data. If you are trying to get more security by making the salt "secret", then you really just want more bits in your encryption keys.

于 2008-10-17T18:57:24.033 回答
3

The second approach is only slightly more secure. Salts protect users from dictionary attacks and rainbow table attacks. They make it harder for an ambitious attacker to compromise your entire system, but are still vulnerable to attacks that are focused on one user of your system. If you use information that's publicly available, like a telephone number, and the attacker becomes aware of this, then you've saved them a step in their attack. Of course the question is moot if the attacker gets your whole database, salts and all.

EDIT: After re-reading over this answer and some of the comments, it occurs to me that some of the confusion may be due to the fact that I'm only comparing the two very specific cases presented in the question: random salt vs. non-random salt. The question of using a telephone number as a salt is moot if the attacker gets your whole database, not the question of using a salt at all.

于 2008-10-17T19:05:39.103 回答
3

... something like a user name or phone number to salt the hash. ...

My question is if the second approach is really necessary? I can understand from a purely theoretical perspective that it is more secure than the first approach, but what about from a practicality point of view?

From a practical point of view, a salt is an implementation detail. If you ever change how user info is collected or maintained – and both user names and phone numbers sometimes change, to use your exact examples – then you may have compromised your security. Do you want such an outward-facing change to have much deeper security concerns?

Does stopping the requirement that each account have a phone number need to involve a complete security review to make sure you haven't opened up those accounts to a security compromise?

于 2012-07-15T03:04:56.663 回答
2

Here is a simple example showing why it is bad to have the same salt for each hash

Consider the following table

UserId  UserName,   Password
     1  Fred       Hash1 =  Sha(Salt1+Password1)    
     2  Ted        Hash2 =  Sha(Salt2+Password2)    

Case 1 when salt 1 is the same as salt2 If Hash2 is replaced with Hash1 then user 2 could logon with user 1 password

Case 2 when salt 1 not the same salt2 If Hash2 is replaced with Hash1 then user2 can not logon with users 1 password.

于 2008-10-17T19:14:50.817 回答
1

There are two techniques, with different goals:

  • The "salt" is used to make two otherwise equal passwords encrypt differently. This way, an intruder can't efficiently use a dictionary attack against a whole list of encrypted passwords.

  • The (shared) "secret" is added before hashing a message, so that an intruder can't create his own messages and have them accepted.

于 2008-10-17T18:58:55.857 回答
0

I tend to hide the salt. I use 10 bits of salt by prepending a random number from 1 to 1024 to the beginning of the password before hashing it. When comparing the password the user entered with the hash, I loop from 1 to 1024 and try every possible value of salt until I find the match. This takes less than 1/10 of a second. I got the idea to do it this way from the PHP password_hash and password_verify. In my example, the "cost" is 10 for 10 bits of salt. Or from what another user said, hidden "salt" is called "pepper". The salt is not encrypted in the database. It's brute forced out. It would make the rainbow table necessary to reverse the hash 1000 times larger. I use sha256 because it's fast, but still considered secure.

于 2018-06-04T22:17:25.743 回答
-1

Really, it depends on from what type of attack you're trying to protect your data.

The purpose of a unique salt for each password is to prevent a dictionary attack against the entire password database.

Encrypting the unique salt for each password would make it more difficult to crack an individual password, yes, but you must weigh whether there's really much of a benefit. If the attacker, by brute force, finds that this string:

Marianne2ae85fb5d

hashes to a hash stored in the DB, is it really that hard to figure out what which part is the pass and which part is the salt?

于 2008-10-17T19:16:43.137 回答