views:

645

answers:

6

An article that I stumbled upon here in SO provided links to other articles which in turn provided links to even more articles etc.

And in the end I was left completely stumped - so what is the best way to store passwords in the DB? From what I can put together you should:

  • Use a long (at least 128 fully random bits) salt, which is stored in plaintext next to the password;
  • Use several iterations of SHA-256 (or even greater SHA level) on the salted password.

But... the more I read about cryptography the more I understand that I don't really understand anything, and that things I had thought to be true for years are actually are flat out wrong. Are there any experts on the subject here?

Added: Seems that some people are missing the point. I repeat the last link given above. That should clarify my concerns.

http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/

A: 

I think there no extra iteration on the password needed, juste make sure there is a salt, and a complexe one ;) I personnaly use SHA-1 combined with 2 salt keyphrases.

mdcarter
Erm... http://www.schneier.com/blog/archives/2005/02/sha1_broken.html
chaos
1-pass hashing has a vulnerability. You can enumerate a very likely set of candidates that lead to the hash. Multiple passes cause the rainbow tables to grow rapidly, hence the 256x hashing. http://en.wikipedia.org/wiki/Rainbow_table
S.Lott
I use SHA-512, as space (and algorithm time) is not an issue, and there is a paper out showing collisions in SHA-1... however I am just paranoid.
Mike Curry
One pass hashing is laughable. Use at least 1000, might as well do 2000.
erickson
A: 

In truth it depends on what the passwords are for. You should take storing any password with care, but sometimes much greater care is needed than others. As a general rule all passwords should be hashed and each password should have a unique salt.

Really, salts don't need to be that complex, even small ones can cause a real nightmare for crackers trying to gain entry into the system. They are added to a password to prevent the use of Rainbow tables to hack multiple account's passwords. I wouldn't add a single letter of the alphabet to a password and call it a salt, but you don't need to make it a unique guid which is encrypted somewhere else in the database either.

One other thing concerning salts. The key to making a password + salt work when hashing is the complexity of the combination of the two. If you have a 12 character password and add a 1 character salt to it, the salt doesn't do much, but cracking the password is still a monumental feat. The reverse is also true.

Kevin
A: 

The length of the salt doesnt really matter, as long as it is unique to a user. The reason for a salt is so that a given generated attempt at a hash match is only useful for a single row of your users table in the DB.

Visage
It does matter. What your salt is effectively doing is increasing the size of the rainbow table that has to be used to crack your hashes. A short salt doesn't do very much that way. (One of the main problems salts are overcoming is that users choose short passwords.)
chaos
It does matter, but only to a point. For each bit of salt you add, you double the space requirements needed for a dictionary attack (or the attacker has to cut his dictionary in half). If there's a good password selection policy (minimum length, requirement for mixed case, digits, punctuation), you would probably be safe with the old 12-bit salts. However, might as well use 64 bits and be safe everywhere. No one really has room for 10^19 dictionaries, even if they are really tiny.
erickson
A: 

Simply said, use a cryptographically secure hash algorithm and some salt for the passwords, that should be good enough for 99.99% of all use cases. The weak link will be the code that checks the password as well as the password input.

Lucero
As long as giving a better security is only as complicated as 5 more trivial lines of code, I'd like to go for the better option in all the use cases.
Vilx-
I don't think you're gonna get that in "5 more trivial lines of code"... but I'll also be reading the other answers and comments here, maybe they are going to prove me wrong.
Lucero
Five more lines of code and a database column.
chaos
+1  A: 

Use:

  1. Hashed password storage
  2. A 128+ bit user-level salt, random, regenerated (i.e. you make new salts when you make new password hashes, you don't persistently keep the same salt for a given user)
  3. A strong, computationally expensive hashing method
  4. Methodology that is somewhat different (hash algorithm, how many hashing iterations you use, what order the salts are concatenated in, something) from both any 'standard implementation guides' like these and from any other password storage implementation you've written
chaos
128 bits is overkill. Even 64-bits is overkill, so that's what I use. There's also no need for a "system level salt" unless the "user level salt" is somehow predictable for a user (like using their name). It's easier and more secure just to use a cryptographic RNG for the salt.
erickson
Overkill? I like overkill. The system-level salt is defense-in-depth for the event that your database contents are compromised without your source code being compromised. Agreed that salts should be noise, not user information.
chaos
I don't get it. Done properly, the digest, salt, and source code could all be disclosed it would still be infeasible for an attacker to discover the password. When you say the database could be compromised, what do you mean? What do you mean by compromised?
erickson
By 'compromised' I mean the attacker has the database contents or source code. If the attacker has your salt, you've lost its benefit against rainbow table generation. So by having multiple salts obtained from difference sources, you guard against any n-1 of them being discovered.
chaos
Creating a new rainbow table for a given key space is more expensive than a brute force search of the space. A dictionary attack is only fast when you already have the correct dictionary. You don't lose anything if an attacker has the salt. That is the point of the article cited by the OP (twice): if you are still worried about rainbow tables, you have no business protecting anyone's data.
erickson
To say "If the attacker has your salt, you've lost its benefit" it incorrect. Salt is meant to be public knowledge. Salt's two purposes are to make the password include some truly random bits and to make two identical passwords hash to different values.
Eyal
Ahh. I seem to have gotten a false impression that generating a rainbow table variation given a known salt was in some way better than brute force. (For a set of passwords that used *only* a system-level salt, like you'd have in Jeff Atwood's example that the article references, a rainbow table off of the salt would be useful; I think I wound up with a false inference from that.) The system-level salt doesn't seem helpful, and the article suggests some differences of emphasis; editing accordingly.
chaos
+11  A: 

You got it right. Only two suggestions:

  1. If one day SHA1 becomes too weak and you want to use something else, it is impossible to unhash the old passwords and rehash them with the new scheme. For this reason, I suggest that attached to each password a "version" number that tells you what scheme you used (salt length, which hash, how many times). If one day you need to switch from SHA to something stronger, you can create new-style passwords while still having old-style passwords in the database and still tell them apart. Migrating users to the new scheme will be easier.

  2. Passwords still go from user to system without encryption. Look at SRP if that's a problem. SRP is so new that you should be a little paranoid about implementing it, but so far it looks promising.

Edit: Turns out bcrypt beat me to it on idea number 1. The stored info is (cost, salt, hash), where cost is how many times the hashing has been done. Looks like bcrypt did something right. Increasing the number of times that you hash can be done without user intervention.

Eyal
+1 for the idea of recording a version for the passwords. I can see that being useful in the future....
Matt
That's actually a bad idea since it unnecessarily over complicates the solution by accounting for a problem that doesn't exist yet. Classic violation of the YAGNI principle.
Kiff
+1 for dealing with a real problem. Kiff's sweeping denial is easily disproved with examples of the problem being asked about here on SO. As someone who has had to asked tens of thousands of users to choose new passwords in a short period of time, I wish I could have had a smoother migration path.
erickson
@Kiff - What is YAGNI about this? Hashes that were once considered strong have turned out to be weak (e.g. MD5), putting in place a plan to deal with SHA1 having a flaw or becomong depricated is not YAGNI, it's learning from history. In fact, experts are already questioning SHA1.
Steve Haigh