Every developer should know that storing any type of password in plain text is the worst possible decision anyone can make in a secure environment. Between security and confidentiality which one will you choose? Nowadays hacking are perform through social engineering or an inside job, by an employee or trusted person. How exactly confident are you towards securing your stuff and confidentiality of your user? Most of us will know that the Reddit suffer from such problem when all their username and password were compromised as their password wasn't hashed and stored as plain text. And twitter was attacked through social engineering recently. We won't want this to happen to us right? Therefore, in this article you will get to know some ways to better hash your password in PHP and some ways to improve your security.
What is Hashing?
Hashing is a term used in encryption to perform a deterministic procedure that takes an arbitrary block of data and returns a fixed-size bit string. Any accidental or intentional attempt to change the data will change the hash value. Moreover, different message will have different hash value. There should not be an exact hash value with different message. And it is infeasible to find a message that has a given hash. Hence, many information security application uses hashing to protect or authenticate the confidentiality of the content of the application such as digital signatures, message authentication codes (MACs), and other forms of authentication.
Authenticate User
We use cryptographic hash function to hash our password. And all of us should not be aware of what is being placed as password in the table. So how do we authenticate these users password since hash value is a one way encryption? This can easily be achieve through comparing the hash value against the one user has keyed in and the one stored in our database!
Rainbow table Attack
A rainbow table attack is a form of lookup table that aim to decode the hash value in order to make hashing feasible to find a message that has a given hash. Rainbow table attack is usually used against cryptographic hash function after they have retrieved a hash value. However, we can better protect ourselves by adding SALT onto our plain text to make it more infeasible for rainbow table to retrieve pain text with a given hash value.
SHA-1 and MD5
We all know that hashing is necessary in term of any password. But i would still like to stress such importance. We are very dependency on encryption algorithm such as MD5 or SHA-1. However, these two algorithm is no longer that secure as compared to the older days. On Wednesday, February 16, 2005 SHA-1 has been broken by three china research. Although its more towards collision attack rather than pre-image one we can assure one thing is that SHA-1 can be broken and its weaker than we thought. You can read more about it on Bruce Schneier article. On the other hand, you can find MANY MD5 cracker online nowadays through Google. eg. md5crack.com. But similarly they are all collision attacks or rainbow table. Wiki explains MD5 vulnerability in a way you will discourage using it. Its time to encrypt your users password using SHA-2 such as sha256, sha384, sha512 or better.
Hashing your password
If you are using PHP 5.12 or above, there is a new function, hash that supports SHA-2.
$phrase = 'This is my password'; $sha1a = base64_encode(sha1($phrase)); $sha1b = hash(’sha1′,$phrase); $sha256= hash(’sha256′,$phrase); $sha384= hash(’sha384′,$phrase); $sha512= hash(’sha512′,$phrase);
For people who are using PHP 5.12 and below, you can try to use mhash which is an open source class for PHP.
$phrase = 'This is my password'; $sha1a = base64_encode(sha1($phrase)); $sha1b = base64_encode(bin2hex(mhash(MHASH_SHA1,$phrase))); $sha256= base64_encode(bin2hex(mhash(MHASH_SHA256,$phrase))); $sha384= base64_encode(bin2hex(mhash(MHASH_SHA384,$phrase))); $sha512= base64_encode(bin2hex(mhash(MHASH_SHA512,$phrase)));
SHA-2 should be used to secure your future application. However MD5 and SHA-1 can still be use for authentication purpose with a very secure password combination. eg. (eQ@xC#Eif2dsa!e2cX2?"}23{D@.
NOTE**: NEVER DOUBLE HASH!
Double hashing is *worse* security than a regular hash. What you’re actually doing is taking some input $passwd, converting it to a string of exactly 32 characters containing only the characters [0-9][A-F], and then hashing *that*. You have just *greatly* increased the odds of a hash collision (ie. the odds that I can guess a phrase that will hash to the same value as your password).
sha1(md5($pass)) makes even less sense, since you’re feeding in 128-bits of information to generate a 256-bit hash, so 50% of the resulting data is redundant. You have not increased security at all.
Credit goes to Ghogilee
****updated on 8 Oct 09
On the note of Ghogilee, i found a few errors which i would like to point out. Double hashing here is referring to two different hash function. It does reduce the search space but doesn't *greatly* increased the odds of a hash collision. On the other hand, SHA-1 should be a 160-bit hash not 256-bit and not only does this doesn't increased the security but also weaken the hash function as the hacker will only required to crack the weaker hash function in this case md5.
If you wish to understand the risk and stuff you can do with hash function, please visit Enhance Security Hash Function For Web Development. Here i document the most detail hash function i could for your information.
Enhance Hashing With Salt
Once you have decide your secure password encryption algorithm, the last thing you might want is to have different user having the same cryptographic hash code in order to defend against rainbow attack. This can bring another problem of more than one account being compromised at the same time when there are multiple same hash and short password can easily be cracked with ease when your database and tables have been known. We can generate a salt in order to overcome this problem so that the string is longer and more random (providing that the salt + password are random enough).
define('SALT_LENGTH', 15); function HashMe($phrase, &$salt = null) { $key = '!@#$%^&*()_+=-{}][;";/?<>.,'; if ($salt == '') { $salt = substr(hash('sha512',uniqid(rand(), true).$key.microtime()), 0, SALT_LENGTH); } else { $salt = substr($salt, 0, SALT_LENGTH); } return hash('sha512',$salt . $key . $phrase); }
The above function contains two parameter. The first will take in a phrase and generate a SHA-2 salt only if the second parameter is placed with an empty variable. However, if both parameter contains values, it will be used when you wish to compare between two hashes. We can use the above method this way,
$username = cleanMe($_POST('username')); $password = cleanMe($_POST('password')); $salt = ''; $hashed_password = HashMe($password, $salt); $sqlquery = 'INSERT INTO `usertable` ("username", "password", "salt") VALUES ("'.$username.'", "'.$hashed_password .'", "'.$salt.'") WHERE 1'; ..
The above will insert the information into the table when user is being created. We will check the user with the following salt.
$username = cleanMe($_POST('username')); $password = cleanMe($_POST('password')); $salt = ''; $sqlquery = 'SELECT `salt`, `password` FROM `usertable` WHERE `username` = "'.$username.'" limit 1'; .. #we get the data here and placed into variable $row $salt = $row['salt']; $hashed_password = HashMe($password, $salt); if($hashed_password == $row['password']){ #verified } else{ #ACCESS DENIAL } ..
The objective of salt is to lengthen the password in the table and also creates totally random hash code for each password. Furthermore, a key is being placed in as hash value to protect the password as our SALT is placed in the table and if our table is compromised, the SALT will also be take into consideration in a rainbow table. Therefore, an additional key is required that is not placed within the table. This way, even if your table is being compromised, it will really takes a lot of time for them to crack those hashed password. As i mention earlier, database can be easily compromised due to employee or social engineering.
Summary
Many of us should start moving forward to new hash function rather than sticking on to MD5 and SHA-1. Although it is still secure for these two algorithm to be used given a strong password. Nonetheless, in the near future these two might not be that secure anymore. Furthermore, both algorithm had already been dropped by US and focus on SHA-2 instead. On the other hand, SALT can really help in many ways against social engineering and inside job attack. Its not all about Session attack, SQL Injection, XSS or XRSF nowadays.