24

I don't like this idea. But I can not come up with a technical argument against it. Can somebody explain it to me? The basic idea is:

$passwd = 'foo';
$salt = hash($passwd);
$finalHash = hash($passwd . $salt);

The $finalHash is what would be stored in the database. I do understand that two users with the same password "foo" would have identical hashes. But that is only one weakness of this plan. And such collisions, while dangerous, are not the primary reason we use salts with hashes. But so far this the only technical objection I have come up with to argue against this.

My understanding is that salts should be random and should be unique for each use of the hash. And this scheme appears to violate both requirements. But I can't figure out how an attacker could benefit from this seemingly flawed use of salted hashing.

7
  • Really, just use bcrypt. There is a version for whatever language you're using. Commented Apr 1, 2013 at 1:14
  • 8
    "And such collisions, while dangerous, are not the primary reason we use salts with hashes." Actually, yes they are. Commented Apr 1, 2013 at 9:41
  • Actually, even i do not understand that why this is bad. As i saw few of other answers they say that if someone breaks into your database then they can easily break the hashes but what i think is that even if we use random salt each time then we have to store them with our hashed password for comparison and if someone breaks into the database then he will also get the salt used for hashing. In that case also the attacker can break the hashes as he knows the salt used for each password. Commented Apr 1, 2013 at 14:52
  • @ChirayuChiripal: You are correct that if the attacker has the salt and the hash then they can try to determine the password that produced that salted hash. That's not the point. The point of the random salt is so that the attacker cannot start the attack on the hash before they obtain the database. If the password hashes are not salted randomly then the attacker can spend hours, days, weeks, years, computing the unsalted hashes of billions of possible passwords, in preparation for the day that they manage to get the database. That day they would then have no work to do. Commented Apr 1, 2013 at 17:02
  • 6
    @EricLippert The point of the random salt is actually so that the attacker cannot use the results of an attempt on one password to gain information about all passwords. With the approach in the question, an attacker only has to hash pass123 once to learn if any users have that password. With unique salts, they would have to hash pass123 for every user before being able to move to the next guess. As a counterpoint, a constant site-wide salt stored in the database thwarts your concerns with precomputation, but does nothing to prevent what I've described. Commented Apr 1, 2013 at 18:26

5 Answers 5

16

If two users have the same password, then the salt will be the same, resulting in the same hash for both. This is undesirable, because it leaks information about passwords. If Alice breaks into your database and sees that Bob has the same hash as her, she can use that information. Pick something that is guaranteed to be unique.

Your biggest problem here, though, is that you're using hash without any information about what that hash is. Depending on the system, it might even be the old crappy 3DES implementation that strips everything after the 8th character. You should be using a proper KDF such as bcrypt or PBKDF2.

3
  • In the psuedocode I wrote, hash() represents any hashing algorithm. But I do plan to require some modern algorithm when we finally implement this.
    – joe user
    Commented Mar 31, 2013 at 20:48
  • 2
    If it was 3DES is would be dropping everything after the 24th character, which would be better; but, alas, the traditional Unix "crypt()" password hashing function is based on a modified DES, not 3DES.\ Commented Mar 31, 2013 at 20:59
  • @ThomasPornin My bad, that's correct.
    – Polynomial
    Commented Mar 31, 2013 at 21:03
27

To answer this, one has to understand why salts are needed in the first place. This is explained pretty well in How to securely hash passwords?; here's an excerpt from the accepted answer:


Salts: among the advantages of the attacker over the defender, is parallelism. The attacker usually grabs a whole list of hashed passwords, and is interested in breaking as many of them as possible. He may try to attack several in parallels. For instance, the attacker may consider one potential password, hash it, and then compare the value with 100 hashed passwords; this means that the attacker shares the cost of hashing over several attacked passwords. A similar optimisation is precomputed tables, including rainbow tables; this is still parallelism, with a space-time change of coordinates.

The common characteristic of all attacks which use parallelism is that they work over several passwords which were processed with the exact same hash function. Salting is about using not one hash function, but a lot of distinct hash functions; ideally, each instance of password hashing should use its own hash function. A salt is a way to select a specific hash function among a big family of hash functions. Properly applied salts will completely thwart parallel attacks (including rainbow tables).


So the problem of your salt is that it doesn't interfere with parallelizing breaking the hashes, which is the very purpose of salting. I strongly recommend you to read the original answer, it has further advice on salting.

3
  • 1
    Based on reading that, I do see that the problem with my example is that the salt is not guaranteed to be unique. But I still don't understand how an attacker could exploit this lack of randomness (besides the collision of two users with the same password).
    – joe user
    Commented Mar 31, 2013 at 20:51
  • 2
    @joeuser Let's say you have a database with N hashed passwords that gets stolen. Using your scheme, each guess the attacker makes has to be hashed twice, then it can be compared against all N (which is usually trivial compared to the cost of hashing). With unique salts, the attacker would have to perform N hash operations to see if the guess is correct for anything. The attacker also wouldn't realistically be able to pre-compute any hashes as part of a rainbow table attack (assuming a reasonable sized hash), while yours does nothing to thwart a rainbow table attack.
    – Kitsune
    Commented Mar 31, 2013 at 21:19
  • 10
    To simplify @Kitsune's example, assume I'm brute-forcing my way through your password database. If I compute the hash for pass123, I know immediately if any of your users have that password, even if it's only one of them. On the other hand, if you were using unique salts, I would have to hash pass123 for every one of your users. Commented Apr 1, 2013 at 2:53
25

If you use the password as "salt" then you are not using any salt at all; you are just hashing the password.

If two users choose the same password, they end up with the same hashed password. That's what is often told as if it explained the problem, but it seems that most people get it wrong. They imagine that this means "collision", which, for some reason, is considered by many to be a bad word when talking about password hashing. But that's wrong, and not the point.

The point is determinism. Suppose that I, wantonly, grab a copy of the hashed passwords for 1000 users (e.g. I retrieved an old backup tape from your garbage bin). Then I can "try" potential passwords: I hash a potential password (using the password itself as "salt") and then I look up the value among the 1000 hashed values. This means that by paying the computational price of one hashing, I actually try one thousand user+password pairs. I am attacking one thousand of hashed passwords in parallel, for the same cost as attacking a single one. This kind of parallelism can express itself under several guises, including rainbow tables.

We really prefer it when attacking 1000 hashed passwords costs 1000 times the cost of attacking 1 hashed password. To do that, you need real salts, i.e. salts which are distinct for distinct users, even when they happen to use the same password -- and, actually, when they potentially use the same password. When there is no real salt, the parallel attack works not because some users do choose the same password, but because if they had chosen the same password then they would have obtained the same hashed value. They don't actually need to choose the same password to trigger the weakness.

Using the user name as salt is much better. It is not good, mind you; but still better. What is even better, to the point of being actually decently secure, is to use random salts.

0

Using a username or password as a salt doesn't sound like a good idea to me.

An attacker might reasonably guess that you're using the username or password as the salt. Depending on your setup it might be very reasonable to assume an attacker could gain access to usernames.

Also depending on how strict your system is at enforcing passwords the attacker could take advantage of passwords that appear in a dictionary of known/common passwords, and as these are used as the salt your system would be vulnerable to this kind of attack.

Using a salt that doesn't rely on user input is a much better idea.

1
  • Doesn't matter too much if the attacker knows the salt, as long as every password has a different salt. The salting makes sure that the attacker has to attack one user at a time, instead of a parallel attack against the whole database.
    – gnasher729
    Commented Jun 23, 2014 at 15:17
0

There have been cases recently where more than 100,000,000 hashes have been leaked. Hopefully they were salted. I think a big number like this makes the effect of salting much more obvious.

Let's say there are passwords that are not really unsafe, but not quite secure enough, because the chance that a random user uses one of these passwords is one in 10 billion. If I try just 100 such passwords, then I can expect to guess the password of one of these 100 million people. Since the password was hashed, then salted with the hash and hashed again, I can easily figure out what is stored in the database for each of these passwords, so after 100 hashes I found a password.

If the passwords were properly salted, each with a different salt, even if each salt is known, I have to calculate 10 billion hashes to get the same result.

2
  • What hash dump contained 100 million passwords? LinkedIn was the largest I can think of a 6.5 million. There's only a handful of sites with 100 million users, and that'd be a big deal...
    – David
    Commented Jun 23, 2014 at 15:43
  • @David Last estimate I saw for the Adobe final tally was 150 million, and Ebay was at least 145 million, though if they're playing fast and loose with their press release wording (as some suspect) and inactive accounts were affected as well, it could be in the multiple hundreds of millions.
    – Xander
    Commented Jul 18, 2014 at 23:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .