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.

ronald l rivest Ronald Rivest. Photo by Ronald L. Rivest. CC BY-SA 4.0

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
Required. The string to be hashed.
raw
Optional. A boolean value, set to FALSE by default, returning a 32-character hexadecimal number. If set to TRUE, it returns a raw 16-character binary format.

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
Required. The string to be hashed.
raw
Optional. A boolean value, set to FALSE by default, returning a 40-character hexadecimal number. If set to TRUE, it returns a raw 20-character binary format.
					
					<?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
Required. The string to be hashed.
salt
Optional. A string parameter to base the hashing on, which is optional. However, 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

bruce schneier Bruce Schneier. Photo by Rama, Wikimedia Commons. CC BY-SA 2.0 (fr)

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
Required. The selected hash algorithm, like ripemd128, md5, sha384, tiger192,3, etc.
string
Required. The string to be hashed.
raw
Optional. A boolean value, set to FALSE by default, returning lowercased hexits. If set to TRUE, it returns a raw binary data.

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());
					?>
					
				

php hash algorithm

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 NO decrypt() function.