PHP Cryptographic Functions For Passwords

27th March 2009 - 6 minutes read time

There are three available cryptographic functions in PHP, these are md5(), sha1() and crc32(). All of the functions take a string and output a value that is encrypted and can't be reversed to the original string. In fact the only way to get the original string back is to run a brute force algorithm which tries to guess what the original string was.

To test these functions I will use the following string.

$string = 'wibble';

md5()

This function returns the hash as a 32-character hexadecimal number. The md5() function is used quite a bit and most PHP programmers will have come across it at some point.

md5($string);
//returns 50eccc6e2b0d307d5e8a40fb296f6171

The md5() and sh1() functions have a second parameter which makes the function return binary data if set to true (the default is false). This returns binary data, which can be turned back into a hexadecimal number by using the bin2hex() function.

bin2hex(md5($string, true));

This function returns the same as in the previous example.

sha1()

sha1() returns the sha1 hash as a string 40 characters long. This function is more secure than the md5() function as there is a lesser chance of guessing what the original string was.

sha1($string);
//returns 02e0182ae38f90d11be647e337665e67f9243817

The sha1() function can also be made to return binary data if the second optional parameter is set to true.

crc32()

This isn't really a cryptographic function, but it can be used in a similar way as a string will always come out with the same result. This function returns the crc32 polynomial of a string as an integer.

crc32($string);
//returns 489363548

Because of the way that PHP stores integers (as signed), quite a few of the results of this function will be negative. For example, the string "wibble" will return a positive integer, but the string "wobble" will return a negative number, which must be compensated for. This can be fixed by using the "%u" formatter of the sprintf() function, which will return a string containing the correct integer value.

This hashing function is intended to be used as part of a hash table and not as a mechanism of security. This is because it is very easy to generate a "hash collision" where two separate strings have the same hash value. I include this here to give you that warning.

sprintf("%u", crc32($string));
// returns 489363548

crypt()

The crypt() function will take a string as input and produce a variety of different outputs depending on the current system and environment. The salt is the second parameter and if you don't include this the function will generate a salt for you, which causes the outcome of the hash to be different every time. An important thing to note is that the value of the salt value effects what hashing algorithm is used. There are a set of constants that can be used if you want to detect if an encryption algorithm is available.

if ( CRYPT_STD_DES == 1 ) {
 crypt($string, 'st');
}
// returns something like "stNPuLMaoIxdU"

If you want to compare a password then you must pass the entire result of crypt() as the salt for a crypt of the password. For example, the following is incorrect.

$one = crypt('one');
$two = crypt('one');
var_dump($one == $two); // returns false

Adding a salt to the second crypt() call gives us the correct answer.

$one = crypt('one');
$two = crypt('one', $one);
var_dump($one == $two); // returns true

As with all hashing functions there is no decrypt function as this is a one way process.

hash()

The hash() function is a multi use function that takes two parameters as a default. The first is the hashing algorithm that will be used and the second is the string to be hashed. To encode the string using the whirlpool algorithm use the following code.

hash("whirlpool", $string);
// returns 91cefc6cc8eecf3a0ef18889bc3b06e7217ce7d41e1d0d5e37709415c3a98e450c53e62ae57680a011a08ef65429e6ba76701c703fcfc4c63938a4aa61737c38

To find out what hashing algorithms your system supports you can use the hash_algos() function. This returns an array of the available algorithms.

print_r(hash_algos());

If you have haval256,5 available in this list then I suggest you use it as it produces the safest hash value. More information about the hash functions can be found in the hash section of the PHP documentation.

Breaking The Code

It isn't possible to break a md5 of sha1 encoded string, but this can only be done by trying to guess the original value. The site md5.rednoize.com/ can break a string that you enter, but only because it contains 47 million hashes and can therefore reverse engineer the value of the hash.

To stop this happening to your passwords you can use what is called a salt value. Rather than directly encode the value of the password you store the password along with a salt, which is kept secret. An attacker needs to know the value of the salt value before they can correctly guess a users password.

Add new comment

The content of this field is kept private and will not be shown publicly.