I want to implement a salt into my login system but am a bit confused on how this is supposed to work. I can't understand the logic behind it. I understand md5 is a one-way algorithm and all of the functions that I have come across seem to hash everything together. If this is the case, how does one get the password back out for comparison? My biggest question is, how is salting a users' password safer than just hashing the password? If a database was ever to be compromised, the hash along with the salt is in the database. Isn't this all that a hacker would need?
I also found another post here on SO where another developer said :
"Ensure your salt and algorithm are stored separately from the database"
I would like to store the salt in the database. Is this really a problem if I do?
I'm looking for some help on understanding how this works and also what the best practice might be. Any help is greatly appreciated.
EDIT: I want to thank everyone for their responses and ideas. Even though I may be more confused now, it has certainly been a learning experience for me. Thanks again guys.
An hash function always return the same value for the same input string. Let's say my user (Alice) has the password
secret
. Hashingsecret
usingmd5()
leads to the following hashUsing a dictionary (a list of common words and password) or one of the various sites that offer you that service, the attacker (Mallory) can easily find out the password is secret when he sees in his dictionary that
5ebe2294ecd0e0f08eab7690d2a6ee69 = secret
.The process of salting before hashing makes it harder to use a dictionary attack without knowing your salt. Consider the following:
The resulting hash is now
b58ad809eece17322de5024d79299f8a
but Alice's password is stillsecret
. Now if Mallory gets her hands on the salted hash, chances are she will not find the answer in her dictionary. If she does, the dictionary will give her the wrong answer.Never store a static salt in your database. Preferably store it with your application's configuration (which by the way should not be available from the web).
If you are going to use a dynamic salt, you are going to need to use the database. Use a non-null column of existing valid data to build your salt on (blowfish-encrypted string of username based on a secret encryption key is usually cryptographically secure). Do not use a separate column for the salt. If you cannot use an existing column, incorporate your salt in the same column than your hash. For example, use the first 32 characters for your 128-bits salt and then the last 40 for your 160-bits hash. The following function will generate such an hash:
If an attacker gets in your database using SQL injection, at least the hashes he/she retrieves won't be useful since he/she won't have access to your application configuration. If your server gets rooted, it's pretty much game-over no matter what you do.
Note: There are other types of attack possible on
md5()
which is why you use more secure hashing algorithm,sha1()
for example. Or, even better, use the Portable PHP password hashing framework, which has been designed with security in mind and is backwards compatible with pretty much any PHP version.Salting a user's password is possibly safer than just hashing the password because it can protect against precomputation attacks.
For instance, if a hacker gets access to your database, and the passwords are not salted, then he can look up the hashes in his database of hashes (see http://en.wikipedia.org/wiki/Rainbow_table) to get the original passwords.