1

I've read on SO (and from other websites found on Google after I tried to look into it a little bit more) that the correct secure way to store passwords in a database is to store the hashed + salted value of a password. On top of that, the salt should be different for each user so hackers can't do harm even if they have the encrypted values.

I'm not quite sure what salting means. From my understanding, you hash the password, then you use another value that you hash (the salt) and combine those two together so the algorithm to retrieve the original password is different for every user.

So basically, what I'd have to do is hash a password, then use a different hash on a different value for each user (ie: the user name or email address) and then I can do a simple math operation on those two values to get the encoded password.

Is that correct or did I just not understand anything about password hashing + salting?

A simple explanation or example would prove to be helpful as the sites I've found don't quite explain clearly what salting a password is.

Edit: After reading comments and answers left so far, I understand that I didn't really understand what a salt was because I'm missing some key concepts and I was making false assumption.

What I'd like to know is: how do you consistently get the same salt if it is randomly-generated? If the salt is stored in the database like some people have mentioned, then I can see how you keep getting the same salt, but that brings another question: How does it make the passwords more secure if anyone with access to the database have access to the salt? Couldn't they just append the (known) salt to all the passwords they try and the result would be the same (bar some minor time loss) than not having one at all?

Jumbala
  • 4,764
  • 9
  • 45
  • 65
  • 1
    http://en.wikipedia.org/wiki/Salt_(cryptography) – Mitch Wheat Jul 31 '11 at 03:11
  • 1
    http://en.wikipedia.org/wiki/Password_cracking – Mitch Wheat Jul 31 '11 at 03:11
  • I read that first article when I was looking on Google but couldn't figure out how they were generating the random bits in a consistent way (if it is random, then when you try to authenticate the salt won't be the same, thus it won't work). That's what I don't quite get and I figured the bits must have been generated from somewhere else. – Jumbala Jul 31 '11 at 03:17
  • Related, but not a direct answer: A common method used to store passwords securely now days is to use bcrypt http://en.wikipedia.org/wiki/Bcrypt which stores a password with a public salt. The security lies in the fact that encrypting the password is slow so it makes brute force attacks more time consuming. – Charles Ma Jul 31 '11 at 03:18

7 Answers7

5

Let me try and clarify a little bit with a somewhat oversimplified example. (md5() is used for example purposes only - you should not use it in practice.)

A salt is just a random string of characters that is appended to the password before it is hashed. Let's say you have the password letmein, and you hash it like this...

 echo md5('letmein')

...you'll get the output 0d107d09f5bbe40cade3de5c71e9e9b7. If you google this, you'll get a number of pages telling you that this is the MD5 hash for letmein. A salt is intended to help prevent this sort of thing.

Let's suppose you have a function, randomStringGenerator() that generates a random $x-character string. To use it to salt a password, you'd do something like this:

 $password = 'letmein';
 $salt = randomStringGenerator(64); //let's pretend this is 747B517C80567D86906CD28443B992209B8EC601A74A2D18E5E80070703C5F49

 $hash = md5($password . $salt);

You'd be then performing md5(letmein747B517C80567D86906CD28443B992209B8EC601A74A2D18E5E80070703C5F49), which returns af7cbbc1eacf780e70344af1a4b16698, which can't be "looked up" as easily as letmein without a salt.

You'd then store BOTH the hash and the salt, and when the user types in their password to log in, you'd repeat the process above and see if the password the user entered with the stored salt appended hashes to the same thing as the stored hash.

However! Since general hashing algorithms like MD5 and SHA2 are so fast, you shouldn't use them for storing passwords. Check out phpass for a PHP implementation of bcrypt.

Hope that helps!

Chris Hepner
  • 1,552
  • 9
  • 16
  • It does help a lot, now I understand (mostly, I think) how it works, but if you read the edit part at the end of my OP, I still don't get how it makes the password encryption more secure if the salt is in the table. Couldn't they just try regular brute forcing and try a.salt, b.salt, etc? – Jumbala Jul 31 '11 at 03:43
  • 3
    @Adam Smith: Let's try this: the ONLY thing salting does is increase the amount of time necessary to crack a single password. By using a different salt for each password you are in effect causing the hacker to create a rainbow table *per password* as opposed to a single rainbow table that can be used against the entire db. – NotMe Jul 31 '11 at 03:48
  • @Adam Smith: Absolutely! It doesn't prevent against brute-force attacks at all (making the password longer *may* make it take a little longer to compute the hash, but not enough to be important). That's why you want to use a hashing algorithm that's *slow* by design, like bcrypt, rather than one that can be performed hundreds of millions of times a second, like MD5 or SHA2. – Chris Hepner Jul 31 '11 at 03:49
  • It makes sense now. Thanks a lot! I guess I was missing a couple of key concepts to really understand how it worked, I'm glad you could help me understand it, I really appreciate your help! – Jumbala Jul 31 '11 at 03:53
2

One uses a salt to avoid the attacker creating a rainbow table, e.g. a table containing all (usual) passwords and the corresponding hashes, sorted (or somehow easily accessible) by hash. If the attacker has such a table or can create it, and then gets your password database with unsalted hashes, he can easily look up the passwords, even for all of your users at once.

If the hashes are salted (and the attacker gets the salt with the hashes), he will still be able to do the same attack (with only slightly more work to input the salt) - but now this work of building a rainbow table is useless for the next hash with another salt, which means this will need to be done for each user again. This alone is the goal of the salt. A dictionary attack on your single account still needs the same time as before, just the rainbow table is useless. (To do something against the dictionary attack, see below.)


How exactly the salt is used depends on the algorithm in use. Some hash algorithms (for example bcrypt, which is specially made for password hashing) have a special salt input parameter (or generate the salt themselves and include it in the output):

H = bcrypt(password, hardness) or H = bcrypt(salt, password, hardness)

(The first variant generates the salt itself, while the second takes it from the outside. Both include the hash and the hardness parameter in the output.)

Others need to be used in some special mode to use the salt. A simple variant which works for most hash algorithms would be using HMAC, with the salt as "message" input, the password as key:

HMAC(password, salt) = Hash(password ⊕ opad || Hash(ipad ⊕ password || salt) )

where opad and ipad are some constant padding values.

Then you store the salt together with the hash. (For a slightly higher barrier, you could store the hash in another location than the salt. But you will still need both for login.) For login, you then will give the password and the stored salt to your hash function, and compare the result with the stored hash. (Most bcrypt libraries have a "password verification" function build in, which do this.)


For password storage it is important to use a slow hash algorithm, not a fast one, to avoid (or really: slow down) brute force or dictionary attacks on the passwords, as most people will have quite short passwords. bcrypt is an algorithm which was made just for this goal (its slowness is adaptable by a parameter).

If you use a fast hash function, be sure to repeat it often enough to be slow again. (But better, really: use bcrypt.)

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
2

Although @Chris and @Pualo have very good answers. I wanted to add one more thing about salting passwords that hasn't been expressed.

Salting a password is not a real protection mechanism. It doesn't matter if you are using bcrypt or any other mechanism. It is simply a delaying tactic, nothing more.

By using a different salt value per password you are forcing the hacker to create a rainbow table per password in order to crack them. This increases the amount of time it takes, but by no means does it make it impossible. Bear in mind that with cloud based computing you can spin up a large number of machines to create the rainbow tables and you can see that the delay is pretty small.

Further, most of the zombie machines out there are available for rent...

That said, the reason why you go through the trouble is to buy time. Time to notice that you've been breached, repair it and inform your users of the breach. That's it.

If an attacker obtained enough access to your database to pull the list of passwords, then it is pretty much guaranteed that they've obtained everything else. So, by this point you've already lost everything. The only question is how long does it take you to plug the hole, reset everyone's password and tell them that they should reset the passwords on any other account they may have where they used the same one. If you're Sony, then this time is apparently measured in months, if not years... ;) Try to be a little faster than that.

So, although it is the responsible thing to do it is only one part of your defensive tool belt. If you've been breached then you can bet those usernames and passwords will show up on a site somewhere at some point in the near future. Hopefully before then you've already cleaned up your house.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • I'm glad you answered as well to add what hadn't been said. As you've said, it's only one tool in my defensive tool belt; do you have a link to recommend me other good practices to keep my data secure or just other things I should be aware of? – Jumbala Jul 31 '11 at 04:14
  • @Adam Smith: Start here: https://www.owasp.org/ Specifically, https://www.owasp.org/index.php/Category:Principle – NotMe Jul 31 '11 at 04:21
  • With bcrypt you can specify the cost. Is a couple years per password enough? Don't throw it in the same category as message hashes or dismiss it as "just a delaying tactic". – ErikE Jul 31 '11 at 04:39
  • 1
    @ErikE: sure... if your users want to take that long to log into your site... You have to keep the cost low enough to keep your site responsive *on your hardware*. Consider it this way let's say I'm a hacker and I rent time on a botnet which gives me access to a hundred thousand machines. Even if the cost is 5 seconds per hash (which is a long time for logging into a site), this means I can generate 2 million keys a minute. I wonder, how many do I have to generate to get a collision? Given what most people use for passwords I'd say not that many. – NotMe Jul 31 '11 at 04:47
  • @ErikE: Also, don't bring up substituting numbers for letters etc. The common (and even uncommon) ones have been part of dictionaries for years. – NotMe Jul 31 '11 at 04:50
  • @ErikE: A way to allow greater iteration counts without slowing down the login server would be to let the client do this: [Is using slow password hashing on the client side easier attackable than on the server side?](http://crypto.stackexchange.com/q/116/58) Of course, this is only be doable if you can design your own protocol. – Paŭlo Ebermann Aug 02 '11 at 21:50
1

Using salt prevent precomputed rainbow-tables usage, as an example if a user use "Password" as a password, MD5("Password"), SHA1("Password"), or WhatEver("Password") may be well-known results stored in some rainbow tables. If you use a different salt value per person - called a nonce - you'll get MD5(HMAC("Password","RandomSaltValue")), SHA1("Password","AnotherRandomSaltValue"), ... that mean two different hashed password values for the same initial password. Now the question about storing these salts value...i think they can be stored into the database, the idea of salts are to prevent rainbow-style attack, not the database compromised issue.

mmorel
  • 424
  • 2
  • 7
  • I see, so using a salt on your password doesn't really help again brute-forcing techniques that iterate every single possible value, it's to protect you from dictionary attacks and the such. It makes sense, I thought salting it protected the passwords against regular brute-forcing as well. That explains the salt being stored not really causing additional security holes. – Jumbala Jul 31 '11 at 03:50
1

Although bcrypt slows the process significantly down, it still would probably be feasible to attack your scheme if lots of computations can be made in parallel. I know it's unlikely and this would have to be a quite resourceful attacker indeed, but let's imagine the site you protect would contain photos and documents from Area 51 :) In that case, given enough parallelization, you could still be in trouble even if using bcrypt.

That's why I like the approach of scrypt - not only does it involve computational cost, but also it imposes memory constraints, specifically to introduce cost in terms of space and to make these kinds of parallel attacks infeasible. I can only recommend reading the paper that is linked on that site, it illustrates the concept really well.

Although, it seems that bcrypt and even more scrypt seem to get less attention in terms of cryptanalysis than PBKDF2outlined in RSA's PKCS#5. See this discussion for details.

emboss
  • 38,880
  • 7
  • 101
  • 108
0

What about Secure hash and salt for PHP passwords? It even has examples in PHP.

Community
  • 1
  • 1
Shi
  • 4,178
  • 1
  • 26
  • 31
  • 1
    @Paŭlo Ebermann "Please do not leave answers that should be comments. Answers should attempt to answer the question." - Didn't my answer answer the question? I thought that copying the text over here again is not a good idea. – Shi Jul 31 '11 at 03:27
  • Actually, the best way is to mark the question for closing while linking to that question. It's essentially the same thing. SO will automatically append it as a comment. – NotMe Jul 31 '11 at 03:29
  • I have, but there are key concepts I'm missing, such as how to consistently get the same salt (that is randomly generated). It seems like it is stored, so that would answer my question, but then how is it secure if people trying to hack the passwords already have the salt? – Jumbala Jul 31 '11 at 03:34
0

I'd say first of all that security is very hard to do right, and that you really should rely on existing libraries to do as much as possible for you. For basic operations like password storage and validation that's definitely true.

EDIT: Removed erroneous info. I'll stick with the only good advice I had, which was not to roll your own.

Matt Tsōnto
  • 1,518
  • 1
  • 15
  • 30
  • All possible salt values? Are you sure about that? Seems a bit off to me. – ErikE Jul 31 '11 at 03:16
  • 1
    If it tries all possible salt values and the salt was merged by XOR, it will work with every password. – Paŭlo Ebermann Jul 31 '11 at 03:23
  • 1
    I would give +1 for this: **I'd say first of all that security is very hard to do right, and that you really should rely on existing libraries to do as much as possible for you.** But then a -1 for your "brute force on login" idea. – Paŭlo Ebermann Jul 31 '11 at 03:26
  • @Emdot: um... no. The salt is stored. It's usually stored in the same record as the password itself. When the user enters their password, you take the password and combine it with the salt and hash it. Then you compare the hash values. If they match you're good to go. The system does NOT compare all possible hash values in order to see if the entered password is correct. That would take way too long. – NotMe Jul 31 '11 at 03:26
  • Read http://codahale.com/how-to-safely-store-a-password/ to get some new info that makes the answers and comments here questionable. – ErikE Jul 31 '11 at 03:28
  • @ErikE That's actually what I don't get about salting... The value is randomly generated and not stored anywhere, so how can you keep reusing the same salt? And iterating through all possible values doesn't seem to make any sense since it would take a while to try them all out and kind of defeat the purpose... – Jumbala Jul 31 '11 at 03:30
  • @Chris Lively That's what I'd like explained... If the salt is stored in the database, then how is salting the password more secure if the hackers that get access to the database already have the correct salt to combine the passwords they try with? – Jumbala Jul 31 '11 at 03:32
  • 2
    @Adam: salting is only to help about rainbow tables (e.g. someone precomputes the hashes for all passwords and then simply looks up the passwords from the hash). With salt, the attacker has to create a rainbow table for each individual salt in use (or for all of them, which gets larger than can be stored on earth, if the salt is long enough). – Paŭlo Ebermann Jul 31 '11 at 03:41
  • @Adam: I agree 100% with Paulo. – NotMe Jul 31 '11 at 03:45
  • Yes @Adam salts are just to prevent rainbow attacks that work on the entire data set. – ErikE Jul 31 '11 at 04:41