How should passwords be stored in the database?
Suppose you are writing a PHP web application that needs to save username and passwords to MySQL database. How should the passwords be saved?
Do not store as plain text
You probably know that you should not just store it a plain text. Because if your some got accessed to your database, then they can see people’s password (which is often the same password they use for their bank). And I’m not talking just about hackers. It could even be an unscrupulous database administrator.
Not Encryption Either
Basically, users passwords should be stored in such a way that it can not be “reversed” or “figured out”. What about encrypting it before saving to database? Nope. By definition, encrypting means that it can be reversed by decrypting. Better than plain text, but certainly not good enough.
Even Hashing is Not Good Enough
What about hashing? Hashing by definition is an one-way function where password goes in and out comes a “hash” of that password. To validate the password, the entered password must be hashed the same way and compared with the stored hashed. Just by knowing the hash, there is no function or algorithm that was reproduced the original password from which is was hashed from.
This is certainly better and there are various hashing algorithm out there such as MD5, SHA1, SHA2. Or the more advanced SHA256, SHA512, RipeMD, or WHIRLPOOL.
But nevertheless, hashing is not good enough. Take for example MD5 hash. Virtually every dictionary word, common word combination, and weak password candidates has been passed through the MD5 algorithm and its hash has been determined and are in “tables”. Hackers just do “kind of” a reverse-lookup of the hash and obtain the original password. While there are no function that algorithmically take a hash and return its original password. There are “tables” that give you original password, when you know the hash. They are not really “tables” as in pages in a book. But more electronically sophisticated version of kind of the same thing. And if you build a program that looks up those tables, then effectively you got a kind of function that returns the original password.
Passwords should be hashed, salted, and stretched
As of the time of this writing in 2014, passwords should be hashed, salted, and stretched before storing. I say at the time of this writing in 2014, because technology changes. In the future, surely this will also be no longer be good enough. But at least it is good enough for now. Afterall, there was once a point in time (such as maybe 20 years ago) where MD5 hash is good enough. But surely now MD5 hash is not good enough.
Hashing is a cryptographic hashing (like MD5 hash). Salting mean introducing a random salt to the process such as two same password will return two different results. And stretching “kind-of” means iterate this a few times. It helps introduce entropy and take a bit more CPU power for an attacker using a brute force method.
How to Implement?
“But I don’t even know what these things mean, how am I going to implement it?” You don’t. And even if you do know how, you shouldn’t. You might introduce bugs and may not do it correctly.
What you do is use a library that has all this implemented for you and have been used for a while by many people. One such open source library is “phpass“. It is the password hashing framework that is currently used by WordPress and Drupal. And they wrote a good article about how to manage users and passwords in a PHP application and some security issues and how to use phpass to mitigate the security issues. Here is a quote for the article …
“…phpass transparently generates random salts when a new password or passphrase is hashed, and it encodes the hash type, the salt, and the password stretching iteration count into the “hash encoding string” that it returns. When phpass authenticates a password or passphrase against a stored hash, it similarly transparently extracts and uses the hash type identifier, the salt, and the iteration count out of the “hash encoding string”. Thus, you do not need to bother with salting and stretching on your own – phpass takes care of these for you.”
It is a must-read for any PHP developer working with usernames and passwords.
But if you already know the theory and just want the syntax of how to use phpass, here is a quick tutorial with some sample code that is pretty good. It includes checking that password is 72 characters or less (to prevent denial-of-services attacks). It also check that the returned hash is equal or greater than 20 characters because phpass (at time of this writing) returns something 20 chars or more.