The article says to give each password its own unique salt and then store the salt (as well as the salted hash) in the database.
This seems like a bad idea to me. If a hacker gets access to the salted passwords, in this case he'll probably figure out how to get access to the salts too.
I figure if the salt is stored in the code (or a config file...) rather than the database itself, at least it's two different hacks to get (1) the salted hashes, and (2) the salt.
1. Avoid precomputed hash attacks ("rainbow table") where the attacker has a big list of hashes:password, and can just walk the table of (leaked) password hashes to get the cleartext. A global salt is sufficient for that, and where it's stored does not matter (can be a config file or a config table or whatever)
2. Avoid the attacker being able to brute-force the whole collection at once, there each password needs its own salt: the attacker needs a pair of (salt, hash) to be able to brute-force each and every password, it can't just compute a million (salted) hashes and cross-check all the table, it has to do so for each and every password it wants to crack. This requires a unique salt per password/hash, and the salt can just be stored with the hash.
Salts are not secrets, they just exist to make the hashing of a given user's password unique. They are generally returned as part of the hash function's result (alongside the number of rounds, so the result has the shape (cost, salt, hash)), it's understood and expected that the attacker knows them: it does not matter to their purpose.
Furthermore, it's important that the salt be unique per password. If you had a single common salt in your code, then two users with the same password would produce the same hash.
Using the same salt for every password in the database protects against an attacker using a pre-computed dictionary ("rainbow tables" are something like this) to attack your stored hash values. Using (and storing) a separate salt for each password protects against that and ALSO protects against the attacker building a dictionary of common passwords with a certain salt and then using that dictionary to crack ALL the passwords in the database at once.
So one-salt-per-user is clearly better, but one-salt-for-all is still better than no-salt-at-all.
Not exactly. Having a salt at all mitigates rainbow table attacks, having a unique salt per password also limits brute-force attacks (you can't brute-force the whole table trying out cleartexts with a given salt, you have to brute-force each password individually).
Having a global unique salt is already better than no salt at all.
I have heard of doing both, though I have not seen it yet in production. It gives the benefit of having to get the code and the database while also requiring dictionaries to be build per password.
I think the considered opinion of "the people in the know" is that getting the code is just not that hard, and the global secret technique offers more illusory security than real security.
This is only a problem in the sense that once one hash has been cracked the so is the other, however most authentication is done using some user/email attribute also.
Usually we fetch user/email, hash password, compare to hash in database - authenticate if match or deny if not.
No it's not a bad idea and essentially it's what BCrypt does.
Think about it. If you use the same salt for all passwords then I can easily create a rainbow table consisting of "keyword" + salt hashes and doing so I can crack multiple passwords.
However if there is a different salt for each password then this type of attack becomes more difficult as I have to essentially do the same amount of work for only a single password.
Finally, we need to store the salt in the database because it's needed in order to recreate the hash using the user's password for authentication.
Further, the same salt for every password opens the door a class of rainbow type attacks that precompute the rounds of the hash containing the salt, then computing the remaining rounds for each list in the dictionary of passwords. When done well, this can reduce huge piles of computational effort required to scan a dictionary or passwords. This same concept is also why hash(password+salt) is really weak, you can precompute a lot of the rounds of a lot of different paswords and then go from there with the known salt.
There are deeper attacks too, but the above are just what can be derived from a bit of reading up on how the SHA family of hashes works.
For a closely related problem/solution, reading up on HMAC is quite enlightening.
> If you use the same salt for all passwords then I can easily create a rainbow table consisting of "keyword" + salt hashes and doing so I can crack multiple passwords.
That's not a rainbow table, a rainbow table is a list of precomputed hashes (which you'd just do once on a cluster you pay — of buy from a guy who did — and then store/stash)
But you're brute-forcing the whole table (you can look for matches after each computation) instead of having to individually brute-force each password. But you wouldn't keep the forced salted hashes around since there's no need for them once you've tested the leaked hashes.
You are. The salt is just to stop the use of rainbow tables, which are pre-generated maps between plaintext passwords and their hashes.
Anyway, you want to store a new salt (not just a system-wide 'this is my salt' salt) for each stored password anyway, so you will need to store that data somewhere. You could obfuscate a little by storing the salts elsewhere, but it seems a little extreme.
Yup. The main purpose of salt (aside from increasing entropy by increasing the length and complexity of the hashed value) is that it prevents rainbow table attacks where an attacker pre-computes (or downloads precomputed) hashes for common passwords, dictionary words, and brute-force style variations of same.
A hash unique to the site would require the attacker to create a site-specific rainbow table, but once created it can be used for all passwords. Having a unique hash per password means that the attacker would have to generate unique password tables per user, which for a suitable salt & algo is impractical, even if (as they normally are) the salts are stored with the passwords.
I was always under the impression that the main point of salting a password before hashing (unique or not, stored in cleartext or otherwise) was to prevent the hash from being referenced against a rainbow table of precomputed hashes. Obviously this is in the case of using md5/sha1 for your hashing.
As an example, find the md5 of a dictionary word and google it, its original value is bound to be in the first or second result. Now find the md5 of that word and a random string (aka a salt)... google and there shouldn't be any results. and even if there was due to a collision, that password wouldn't work, because it would be resalted prior to the comparison happening.
The individual salts are added only to prevent an attack with a list of pre-calculated hashes.
You could also store another common salt ("pepper"?) in the code.
This seems like a bad idea to me. If a hacker gets access to the salted passwords, in this case he'll probably figure out how to get access to the salts too.
I figure if the salt is stored in the code (or a config file...) rather than the database itself, at least it's two different hacks to get (1) the salted hashes, and (2) the salt.
Am I misunderstanding?