PHP: Hash Functions md5(), sha1(), crypt(), hash()
In this tutorial, we will explore the various hash functions available in PHP.
md5()
The MD5 Message-Digest Algorithm was designed by Professor Ronald Rivest of MIT in 1991. It produces a 128-bit hash value.
PHP has the md5() function which calculates the MD5 hash algorithm of a string and returns a 32-character hexadecimal character by default. The syntax for this method is:
md5(string, raw);
string
raw
The below line of code prints the MD5 hash (or "message digests") of the string "scriptverse":
<?php
$str = 'scriptverse';
echo md5($str);
?>
The above script will output something like:
81ce3538a7d141a49e3052840469b2ce
md5($str)
is equivalent to md5($str, FALSE)
. When the second argument is set to TRUE,
<?php
$str = 'scriptverse';
echo md5($str, TRUE);
?>
it returns a raw 16-character binary format.
��58��A��0R�i��
sha1()
SHA-1 stands for Secure Hash Algorithm 1. The cryptographic function was originally developed as part of the United States government's project known as Capstone, a policy to develop cryptography standards for public and government use.
The sha1()
function in PHP calculates the sha1 hash of a string and returns a 40-character hexadecimal value by default. It has the following syntax:
sha1(string, raw);
string
raw
<?php
$str = 'scriptverse';
echo sha1($str);
?>
The above script will output:
e7eaf1e1341219d99a40b27b89d8785d6e68ba55
When we set the second argument to TRUE
,
<?php
$str = 'scriptverse';
echo sha1($str, TRUE);
?>
it returns a raw 20-character binary format.
����4ٚ@�{��x]nh�U
Owing to their speed and efficiency, usage of both md5()
and sha1()
to hash secure passwords is not recommended anymore. Both the algorithms have been found to be prone to length extension attacks.
crypt()
The crypt()
function returns a one-way hashed string based on DES, MD5, Blowfish or SHA algorithms.
crypt(string, salt);
string
salt
crypt()
produces a weak password without salt.
As crypt()
supports multiple hash algorithms, following are the algorithmic constants which are set either to 1 or 0, depending on the system's support for them:
- CRYPT_STD_DES
- CRYPT_EXT_DES
- CRYPT_MD5
- CRYPT_BLOWFISH
- CRYPT_SHA_256
- CRYPT_SHA_512
You can quick check any with the echo()
construct just to test the system's support for it.
<?php
echo CRYPT_STD_DES;
?>
It will output either 1 or 0, depending on the system's support for it.
As we can see, there is no algorithm
parameter for the crypt()
function. So how do we decide which algorithm to use in crypt()
? By their salts! As you will see, the salt for each algorithm has a different length and/or different set of characters.
We decide which algorithm to use in crypt()
by providing the salt, as the salt for each of them has a different length and/or different character set.
CRYPT_STD_DES
This is a standard DES-based hash with 2-character salt from the character range /0-9A-Za-z
.
<?php
if(CRYPT_STD_DES == 1) {
echo 'Standard DES: '.crypt('scriptverse', 'SL').PHP_EOL;
}
else {
echo 'Standard DES not supported.'.PHP_EOL;
}
?>
Output of the above script is:
SLL9BdKgKI9Vc
CRYPT_EXT_DES
The CRYPT_EXT_DES
is a 9-character salt, consisting of an underscore followed by 4 bytes of iteration count in the Extended DES number system and 4 bytes of salt. Here, w8..
equals 800 in Extended DES count.
<?php
if (CRYPT_EXT_DES == 1) {
echo 'Extended DES: '.crypt('scriptverse', '_w8..salt').PHP_EOL;
}
else {
echo 'Extended DES not supported.'.PHP_EOL;
}
?>
The above script outputs the following:
_w8..salt6wMKpeebhmQ
CRYPT_MD5
This is MD5 hashing with a 12-character salt, starting with $1$.
<?php
if(CRYPT_MD5 == 1) {
echo 'MD5: '.crypt('scriptverse', '$1$salt4md5$'). PHP_EOL;
}
else {
echo 'MD5 not supported.' . PHP_EOL;
}
?>
The script outputs the following:
$1$salt4md5$59qRDO2PX2oFaPs/AmNAh0
CRYPT_BLOWFISH
This hashing is based on the Blowfish algorithm, designed by Bruce Schneier in 1993. The salt consists of: (i) "$2a$" or "$2x$" or "$2y$", (ii) a two digit cost parameter in the range 04-31
, (iii) "$", and (iv) 22 characters from the character range ./0-9A-Za-z
where the last character is $. If characters from outside the given range is included in the salt, crypt()
will return an empty string. Versions prior to PHP 5.3.7 only support "$2a$" as the salt prefix. But from PHP 5.3.7+, developers have recommended to use $2y$ when hashing newly set passwords.
<?php
if(CRYPT_BLOWFISH == 1) {
echo 'Blowfish: '.crypt('scriptverse',
'$2y$18$justsomesalt4blowfish$'). PHP_EOL;
}
else {
echo 'Blowfish not supported.' . PHP_EOL;
}
?>
The above script outputs:
$2y$18$justsomesalt4blowfish.ugIcGyBMVINUiXjuGEl52Ta01E8NtI
CRYPT_SHA256
This is SHA256 hashing with a 16-character salt, starting with $5$
. If after the prefix $5$
, the salt starts with 'rounds=<N>$'
, then N
is an indication of the number of times the hashing loop would be executed. The default round is 5000, while the minimum cannot go below 1000 and the maximum above 999,999,999. Any value of N
outside this range is truncated to the nearest limit.
<?php
if(CRYPT_SHA256 == 1) {
echo 'CRYPT_SHA256: '.crypt('scriptverse',
'$5$rounds=7000$somesalt4sha-256897$'). PHP_EOL;
}
else {
echo 'CRYPT_SHA256 not supported.' . PHP_EOL;
}
?>
The script outputs the following:
$5$rounds=7000$somesalt4sha-256$TKuDHNWyLL/7CSxmCOtGXLUZB.lc7tawZgRKdJWwbx8
CRYPT_SHA512
SHA512 hashing is similar to CRYPT_SHA256
above. It hashes with a 16-character salt prefixed with $6$
. If the salt string starts with 'rounds=<N>$'
, then N
indicates the number of times the hashing loop would be executed. The minimum and maximum allowed rounds are 1000 and 999,999,999 respectively; the default round is 5000. Any value of N
outside this range is truncated to the nearest limit.
<?php
if(CRYPT_SHA512 == 1) {
echo 'CRYPT_SHA512: '.crypt('scriptverse',
'$6$rounds=8000$somesalt4sha-521$'). PHP_EOL;
}
else {
echo 'CRYPT_SHA512 not supported.' . PHP_EOL;
}
?>
The script outputs the following:
$6$rounds=8000$somesalt4sha-521$MxGTPJgAfxpOgPRIuj0ryPzmL8V9QnCcjzC6/CLVHQSJuZXe2tRz4FHoQKu2nOz51cRK7f3t2EFCuVmg0.KrH.
hash()
The PHP hash()
function generates a hash value based on the hashing algorithm passed as its first parameter.
hash(algorithm, string, raw);
algorithm
ripemd128
, md5
, sha384
, tiger192,3
, etc.
string
raw
You can get the list of registered hashing algorithms in PHP using the hash_algos() function. The below script returns 52 of them (currently).
<?php
print_r(hash_algos());
?>
Here is the hash output for the ripemd128
algorithm:
<?php
echo hash('ripemd128', 'scriptverse', false);
?>
This script outputs:
9d289fa1ef815052a96240f1009a1110
If the last parameter is set to true
<?php
echo hash('ripemd128', 'scriptverse', true);
?>
it returns raw binary data
�(���PR�b@��
Notes
-
crypt()
uses a one-way algorithm and there is NOdecrypt()
function.