12

I've read through many of the questions on SO about this, but many answers contradict each other or I don't understand.

You should always store a password as a hash, never as plain text. But should you store the salt (unique for each user) next to the hashed password+salt in the database. This doesn't seem very clever to me as couldn't someone gain access to the database, look for says the account called Admin or whatever and then work out the password from that?

Jonathan.
  • 53,997
  • 54
  • 186
  • 290

6 Answers6

26

A lot of people are saying "to stop rainbow tables" without explaining what rainbow tables do or why this stops them.

Rainbow tables are a clever way of precomputing a large number of hashes and storing them in less memory than would naively be required, and you can use them to very quickly reverse a hash. Tables for bare functions such as hash = md5(password) and hash = sha1(password) are common.

However, they can be generated for ANY hash function which can be described as output = f(input). If you use a site-wide salt for all user passwords, for example hash = md5(salt+password), you could construct a function f, f(password) = md5(salt+password). Therefore you could generate rainbow tables for this function, which would take a long time, but would then let you crack every single password in the database very rapidly.

If the salt is different for each password, you can't generate a rainbow table that will crack all passwords in the database. You could generate a new one for every user but that would be pointless - naive brute-forcing would be no slower. So having a seperate salt for each user stops the rainbow tables attack.

There are several ways to do accomplish this. Popular ways include:

  • A separate salt for each user, stored alongside their other details in the database: hash = hashfunction(salt + password)
  • A global salt and some unique value per user: hash = hashfunction(salt + password + user_id) for example
  • A global salt and a per-user salt: hash = hashfunction(global_salt + user_salt + password)

Having a global salt could add a little extra complexity to cracking the passwords, as it could be stored outside of the database (in the code, for example) which attackers may not gain access to in the event of a database breach. Cryptographically I don't think it adds much, but in practice it could slow them down.

Finally, to answer your actual question:

Storing the salt alongside the user data does not weaken the hash. Hash functions are one-way: Given the hash of a password, even an unsalted one, it is very difficult to find that password. The motivation behind salting is not to make an individual hash more secure, but to make the collection of multiple hashes more secure. There are several vectors of attack for a collection of unsalted hashes:

  • Rainbow tables
  • Hashing common passwords (123, password, god) and seeing if any exist in the database, and then compromise those accounts
  • Look for identical hashes in the database, which means identical passwords (probably)
Thom Wiggers
  • 6,938
  • 1
  • 39
  • 65
ZoFreX
  • 8,812
  • 5
  • 31
  • 51
  • By "A global hash and a per-user hash" you mean "A global **salt** and a per-user **salt**", right? Similar in other sentences... – David Balažic Jun 22 '14 at 23:06
  • does the "+" in "salt + password" mean literal addition ? – HopefullyHelpful Jun 29 '17 at 11:06
  • The + is used to represent combination, which is often concatenation in practice. However I don't want to say "this is the right way to do it" because honestly, I don't know if there are any subtle bugs to avoid in this construction. The Right Answer is that you should use a modern password hashing library that handles this for you - such details should not be under your control. – ZoFreX Jul 16 '17 at 22:12
6

Salt is used to increase the time that an attacker would have to spend to find a password matching the hash stored in database. Typically lookup table such as rainbow table (see http://en.wikipedia.org/wiki/Rainbow_table) is used to achieve this.

What costs time is not the lookup itself, but the time to compute the rainbow table. Adding a salt forces the attacker to recompute a new rainbow table, even if it is known by the attacker who would compromise the database

Grimmy
  • 836
  • 6
  • 16
  • 8
    A salt also makes the stored hashes unique, even if two users have the same password. – Anders Abel Apr 06 '10 at 07:20
  • @Anders Abel - Only statistically speaking. Of course, this does depend on the size of the salt and the user base, but with the bad old UNIX DES-based password hashes, there's only 12 bits of salt, so if we have 4097 users with the same password, at least two will have identical password hashes. – Vatine Apr 06 '10 at 11:15
  • Computing a rainbow table is totally worth it for say, 100,000 users. The point is that you cannot do it if the salt is different for each user - computing 100,000 rainbow tables would be pointless. – ZoFreX Apr 20 '10 at 17:15
3

The salt is meant to disturb existing rainbowtables. It's no security threat to know the salt. If you know the salt, you would still need to know the password.

Ikke
  • 99,403
  • 23
  • 97
  • 120
  • but surely if salt + password = hash then hash - salt = password? – Jonathan. Apr 06 '10 at 13:37
  • 1
    loosely, but remember that hash is a one-way algorithm. [ do_hash( salt + password) = hashed_password. ] If a salt is known, the attacker must execute do_hash(salt + password_guess) for each password attempt, in order to build a rainbow table or brute-force/dictionary attack each password. Change the salt for each user and this leaves a Very Large search space. – Cheekysoft Apr 06 '10 at 16:15
  • but why would the attacker want all the users passwords surely he would just look for admin etc. – Jonathan. Apr 06 '10 at 16:24
  • @Jonathan It's not only the admin's password which is at large. Many people use the same password on different sites. This way, you can keep their password more safe so attackes cannot get their passwords from your database. – Ikke Apr 07 '10 at 07:36
2

Well well well .. so many discussions ... so much information. so many questions ... i see that after all the questions are answers here is the summary.

  1. Why Salt?
  2. Why Salt is stored alongwith the hash of (password + salt).

Here is my understanding.

  1. Hackers have rainbow table for all the dictionary words which he made with great great effort. Every rainbow table making gets the hell out of the hacker. In simple words its very tough.
  2. As by point 1, if we make the hacker compute rainbow table for each user then he'll be getting old by the time he knows the password. And if the user frequently changes the password, then even hacker's grand children will get old by the time they know the password.
  3. Ok. So use different salt for each user. This makes the hacker use seperate attack to know the password of every single user.
  4. I see that various readers pointed out , that instead of banging head on every single user a great hacker will put all his effort towards admin account and then he is done :). So in this case, we will go a step ahead and then use some different method to compute the hash. Lets say the salt is not exactly what is stored. It may be half of the actual hash. The other half is stored somewhere else in some other way (computed in some other way). This is just an extra security measure. And we know thwt in current times, the calculation power of computers is increasing. So ethical people know that worlds fastest super computer will take 1 year to crack admin password (just an example). So they force a policy which says change admin password every 3 months. by the time hacker knows the old password , the new one is in effect. Or say the database is compromised, then good guys come to know of it by the time hacker cracks the password. And the good guys changs the things by then ( remember upgrade of alogorithms ..sha1 sha2 and now sha3 ).....

Ok..though not fully complete, but my point is bad guys take lot of time .... but good guys are a step ahead to ensure that they know the technology which bad guys will be using to crack. So just devise a better technology by time.

Take care ....

skyineyes
  • 31
  • 1
2

Well first of all, the primary purpose of the salt is to disable brute-forcing of the passwords, for example it prevents the usage of rainbow tables for quick compromising of a password.

Even if an attacker gains access to a database, it's not that easy to work out the real passwords from the salts (especially if you don't have the code and don't know how the password is hashed). However what I like to do for additional security is to also hash a password with a static hash that is specified in the code. This way it's not enough that you compromise the database. An example of such method (in PHP):

$hashed_password = sha1($user_password . $user_salt . $static_salt);

$user_salt is the salt in the database unique to each user, $static_salt is the salt specified in your code's settings somewhere.

reko_t
  • 55,302
  • 10
  • 87
  • 77
  • I'm not convinced this does significantly more than give a false sense of security. – Tom Hawtin - tackline Apr 06 '10 at 11:36
  • 1
    Like Grimmy stated, if someone compromises the database and gets user's hashed passwords and salts, they can use those to generate new rainbow tables (assuming they know the hashing method used, which you can easily figure out in case of open-source software). If you also include a salt not stored in the database in the hashed password, an attacker can't generate a new rainbow table by only compromising the database. It's not just false sense of security. – reko_t Apr 06 '10 at 12:04
  • You can't generate rainbow tables if there are different salts for each user. I see what reko_t suggested used a lot and I too am unsure if it really adds security. I have an idea for one situation where it does: If you had a very large database, and every password hash was like he said, but without the static salt: You could run some queries for example for each user, hash "1234" + user_salt and store matches. You'd be guaranteed to compromise a handful of accounts. If there was an unknown site-wide hash, this vector would not be possible, and finding the hash would be extremely hard. – ZoFreX Apr 20 '10 at 17:13
1

If you don't store the salt, how will you check if the correct password was provided?

wRAR
  • 25,009
  • 4
  • 84
  • 97