I have been thinking about writing a series of blog posts about security topics, and I figured I would start from the basics, with the concept of salting hashes.
I'm going to assume that you are all familiar with how hashing works, but just in case you are not, hashing is a cryptographic one way function that turns data into a hash (random looking noise). It cannot be reversed (turned back into data), and the same data always produces the same hash.
Hashing very useful when it comes to storing passwords. You can store only the hash, and then when the user enters his or her password, you run the same function and compare the hashes. This means of course that if an attacker gets the table with the hashes, he or she can't just read the passwords.
But there is a problem with this approach, and it's called rainbow tables. Because the same password always becomes the same hash, the attacker can use pre-computed hashes. Even the longest hashes take only about 100 bytes to store. There are a few hundred million passwords that have leaked thus far, I think it's safe to say that most of them are duplicates. So if you would store 10 million unique passwords of 100 bytes each, or let's say 500 bytes, so you can cover all of the most used hashes. That would amount to 5 GB of data, you can store that on a smaller USB drive. And that probably includes several of your passwords. So if you ever re-use passwords, you are vulnerable to this kind of attack.
The solution to this problem is to salt the passwords. Salting means adding a bit of extra data (salt) to the password in order to change the hash. It's easy to think that the salt should be best kept secret, not stored in the same place as the hashes, but this means that the salt pretty much has to be the same for all password. While this defeats rainbow tables, it still means that if an attacker has all the hashes, and are brute-force guessing passwords, he or she can compare to all hashes for each guess instead of just one.
So one should use a different salt for each password. This pretty much means that the salt needs to be stored in the database with the password. This might seem like a weakness, but when dealing with good security one should assume that all your secrets are known. Security through obscurity is bad security, this is something history teaches us time and again. A bit of obscurity doesn't hurt, but one might easily start adding it to the calculation when assessing the strength of your system. You should always assume that a determined attacker knows how your system operate.
One can actually go one step further and store the type of hash as well as the number of times you hash the password along with the salt in the same table as the hash. The bonus of doing this is that you can update the strength of your new password hashes by just updating the code that stores your password. That way all the old ones will continue to work when comparing to them. If you enforce good passwords and salt your hashes, any leaked user databases are fairly well protected. If such a breach occurs there are of course a lot of steps that should be taken, but technically the passwords can still be used to authenticate users. Preferably in addition to a second factor.