3

Since the introduction of Rainbow tables, and using only hashed passwords (e.x: MD5) to stored passwords in database is not the best secured way.

When people talk about salted hashes, the always use it in this way hash(password . salt) or even hash(hash(password) . salt).

I don't know why to use salt, and add extra entry for each password to store the salt? Why don't we just use hash(hash(password)), or even hash(hash(hash(password)))?

Is it more secure to put salt? or just the sense of being more complex?

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Yousf
  • 3,957
  • 3
  • 27
  • 37
  • 1
    possible duplicate of [What is the purpose of the "salt" when hashing?](http://stackoverflow.com/questions/1884598/what-is-the-purpose-of-the-salt-when-hashing) – Lucero Dec 19 '10 at 13:48
  • 9
    Why do you think hashing the hash would increase the security of the password without salting it? It's just like whisking batter for another 10 minutes without adding any extra condiments from the secret recipe. – BoltClock Dec 19 '10 at 14:00

8 Answers8

23

You can build a rainbow table based on a dictionary for hash(hash(pwd)) in just twice the time as for hash(pwd) (even less because performance is mainly about disc writes) and it wouldn't even be larger. Using salt greatly expands the size needed for the table up to the amount where it becomes impractical.

Also (even more important), users often have the same password. Without an individual salt per user, if you've broken one users password, you've broken all other users that have the same password.

TToni
  • 9,145
  • 1
  • 28
  • 42
  • But how would you know the exact number of iterations to hash? Doesn't that also count as salting? Regarding your second paragraph, it's only a solution if you use nonces and not static salts. – Alix Axel Jan 02 '11 at 03:35
  • 2
    Hrm..second paragraph never occurred to me. That's a good argument for per-user salts. – mpen Jan 02 '11 at 04:47
  • @Alix Axel: That's right of course. I just implied per user salts and since the Q&A seems quite popular I will amend the answer accordingly. – TToni Jan 09 '11 at 07:14
12

To keep things simple, let's imagine everyone uses digits as their passwords.

If everyone uses 8 digits as their password, that's 100,000,000 possibilities. If you're trying to break the system, you need to hash all those possibilities. If you have a "hash of hash of hash", you still just need to hash those 100,000,000 possibilities - just in a slightly more complicated way.

Now let's pretend we have a 4 digit salt as well. Now, instead of 100,000,000 possibilities there are 1,000,000,000,000... we've given a potential attacker 10,000 times the work to do, instead of just 3 times as much work to do.

Basically, think of a salt as a way of artificially making everyone's password longer, and thus extending the space that a dictionary attack has to work on.

EDIT: Just to be clear, given that the salt is provided in plain-text as well, you would still only have 100,000,000 possibilities to try to attack any one hash. However, it means that after trying those possibilities for one password, the attacker wouldn't have any useful information for attacking another password. Without a salt, an attacker could create a dictionary of 100,000,000 possibilities and then know all the passwords in a database, given only their hashes. In other words, salts help to prevent bulk attacks. They also mean that you can't pregenerate the dictionary: in order to attack a single password effectively, you have to know the salt beforehand. Without a salt, you could compute the hash of every possible password before you get access to the hashes themselves.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    I didn't downvote, but I think your explanation is a little misleading. Because the salt is known it does not make guessing an individual password any harder. It just makes building a table to attack more than one password harder, and only if every user has an unpredictable salt. – President James K. Polk Dec 19 '10 at 14:56
7

If you don't use a salt then an attacker can build a single rainbow table can be used to attack every password in your database. Hashing multiple times does not protect you without a salt, because rainbow tables work by chaining hashes together in exactly the way you describe: hash(hash(password)).

If you add a random salt for each user then the attacker cannot re-use the same table to crack two passwords so their work becomes much harder. As an added benefit, two users with the same password will hash to different values if a salt is used.

Your idea of iterating the hash is still good, but you need the salt too. If you do this:

function hashPassword(password, salt) {
    result = hash(salt . password)
    for (i = 0; i < 1000; i++) {
        result = hash(salt . result)
    }
    return result
}

then you make the attacker's work 1000 times harder with a negligible effect on legitimate users. Note that attackers can test millions of candidate passwords each second on a single, low-end computer - hash functions are designed to be fast. This 1000 iteration loop can change a feasible attack into one that will take 100 years or more. When computers speed up in 18 months time just change the number of iterations to 2000.

The salt, hashing algorithm and iteration count do not need to be secret and can be stored in your database alongside the computed hash. You can choose a fixed iteration count and hash algorithm, but the salt must be randomly generated for each user.

Cameron Skinner
  • 51,692
  • 2
  • 65
  • 86
4

Both iterating the hash and using a salt increase the security of password hashing. But they protect against completely different attacks.

Iterating the hash increases the work required for brute-force attacks. But you shouldn't use a naive iteration as you suggest, but an algorithm designed for it, such as PBKDF2

A salt protects against pre-calculated tables, so it should be different for every website and user.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
0

The point of the salt is to make dictionary attacks moot. Now no matter how much you rehash a hash, the same input is always going to yield the same output hash, and therefore one can build a dictionary for that. So while multiple hashing may make it more difficult for brute-force attacks, it doesn't do anything for dictionary attacks.

Lucero
  • 59,176
  • 9
  • 122
  • 152
  • the point of a hash is to protect agains precomputation attacks. Dictionary attacks are still possible. – Jacco Dec 19 '10 at 16:18
  • @Jacco: "the point of a **hash** is to protect agains precomputation attacks" - come again? – Lucero Dec 19 '10 at 16:27
  • hmm, didn't reread my comment. The point of salting your hash is to protect against precomputation attacks. – Jacco Dec 19 '10 at 16:50
  • @Jacco, I agree with that. But that implies that it does help against dictionary-based attacks, assuming that by dictionary a set of precomputed values is meant (maybe my dictionary definition is wrong). – Lucero Dec 19 '10 at 16:53
  • 1
    A dictionary attack makes use of the fact that many passwords are based upon actual words (as collected in a dictionary). The entropy of a 8 character string created from sequences of characters found in a dictionary is a lot lower than if it where a random string. The salt, *being non-secret by definition*, does not change the entropy of the hashed string. It does however (tries to) make sure that each and every hash is different. So an attacker trying a dictionary attack needs to attack every hashed value separate. In other words, the computational result of the attack cannot be reused. – Jacco Dec 19 '10 at 17:04
  • From the context I assumed Lucero meant a *precomputed* dictionary -> hash table, i.e. a precomputation attack. – President James K. Polk Dec 19 '10 at 17:38
  • @GregS, exacly. Not being a native English speaker I may fail to express myself precisely enough in some cases... – Lucero Dec 19 '10 at 17:57
0

Nothing stops anyone for building a Rainbow table for doubly hashed passwords.

Petter
  • 37,121
  • 7
  • 47
  • 62
0

I use a comparible method to hash passwords for users that login. A salt (random value) is generated in the session and is sent to the client. The user enters their password, which is then hashed with the salt and sent back. This makes sure that the value sent from the server is different each time, making it harder to break in using a man in the middle attack.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
-1

The salt is a site- or user-specific value. That means that in order to retrieve the passwords, an attacker must have both access to the database AND know the salt.

In addition, the attacker could additionally generate a table once and then use it against multiple sites. However, with salts, attackers must generate one table per site or even once per user(making the attacks slower).

Site-specific salts add very little to the security of a website. As said in comments, having a combination of site-specific and user-specific salts can significantly improve security over just a site-specific salt.

A few years ago I asked here on stackoverflow a question about password storage which might be helpful to you. See Secure hash and salt for PHP passwords.

Community
  • 1
  • 1
luiscubal
  • 24,773
  • 9
  • 57
  • 83
  • 5
    The salt would usually be in the database though. After all, you want a different salt for every user - otherwise two users with the same password would have the same hash, which is a security vulnerability. Having a single site-specific key means that if that single key is compromised, *all* your users are vulnerable from just a single dictionary recomputation. – Jon Skeet Dec 19 '10 at 13:44
  • 2
    @Jon is correct: the salt is not "site-specific". It should be randomly generated for each user. Note that the salt does not need to be a secret and should not be considered as such. – Cameron Skinner Dec 19 '10 at 13:51
  • 1
    Of course, you can use multiple salts, such as one for the site *and* one per user... – Lucero Dec 19 '10 at 13:57
  • 1
    @Jon Skeet - Why not have a mix of both? Partially site-specific and NOT in the database, and another part user-specific and in the database? EDIT: @Lucero Ops. Didn't see your comment... – luiscubal Dec 19 '10 at 14:02
  • 1
    @Lucero: No point. Just have a single, random salt for each user. This means less code and (probably) fewer bugs. Don't go claiming that having more salts makes it harder for the attacker: it doesn't. That's security through obscurity which we all know is not security at all. – Cameron Skinner Dec 19 '10 at 14:04
  • 1
    @Cameron Skinner - Read my edit. If some salts are user-specific and others are site-specific, then you get the best of both worlds. On one hand, the attacker still needs to find out the site salt and, on another hand, the combination of all salts still changes from user to user. – luiscubal Dec 19 '10 at 14:09
  • @luiscabal: Your initial statement of "The salt is a site-specific value" is still at best misleading. In my experience, salts typically *aren't* site-wide - they're specific to a particular user. – Jon Skeet Dec 19 '10 at 15:47
  • @luiscabal, if a product is used at different sites and two users happen to get the same salt, having an additional site salt does enhance security. This has nothing to do with security through obscurity. – Lucero Dec 19 '10 at 15:52
  • @Luiscubal: Salts are *not secret* and should not be considered as such. Adding a site-wide constant adds virtually nothing to the strength of your security. If I'm going to add bits to the salt then make them random rather than fixed. That means those extra bits are unguessable. By adding a site-wide salt you're essentially *reducing* the cost of guessing the salt, not increasing it. @Lucero: If your salt is a randomly-generated 128-bit number then the chances of a collision are astronomically small so the security "enhancement" is absolutely negligible. – Cameron Skinner Dec 19 '10 at 16:03
  • See Jon Skeet's updated answer for a concise explanation of this: a site-wide salt does not help prevent *bulk attacks* because it is the same for each user. – Cameron Skinner Dec 19 '10 at 16:05
  • A salt is random by definition. See also: http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190 (if it is not random, we call it a key) – Jacco Dec 19 '10 at 16:16
  • Fixed the answer to focus more on user-specific salts. – luiscubal Dec 19 '10 at 17:48