Managing passwords the correct way in PHP
Because of security matters!
Whenever we develop a user based web application system, we have a common problem of storing the password in the database with correct security standards. In this blog, we will see the
I still remember days when we used MD5 or SHA1 hashing to store passwords. Many folks are still using them. One can easily crack the hash generated from MD5 and SHA1 functions using Rainbow Algorithm.
<?php // below example is for just for understanding how md5 is used. $password = '[email protected]'; // output of below function will be 32 digit hexadecimal string 0f359740bd1cda994f8b55330c86d845 echo md5($password); ?>
there are certain sites that have stored hashes of MD5 functions e.g https://crackstation.net. On this site when you enter MD5 hash it will give you original input from stored mapping. Hence, to overcome this situation we add extra salt with the password, generating a more complex hash.
<?php $password = '[email protected]'; // generate some radom value $salt = md5(microtime()); // output of below function will be 32 digit hexadecimal string. md5($password . $salt); ?>
using salt mechanism we need to store the salt and hash in the database for authentication to succeed.
Although we can avoid it; thanks to the PHP community, after version 5.5, they have introduced several PHP hash functions to specifically generate and store password.
The new password hashing API introduces four simple functions:
password_hash()
– hashes the password.password_verify()
– verifies a password against its hash.password_needs_rehash()
– used for password rehashingpassword_get_info()
– returns the name of the hashing algorithm and various options used while hashing.
Let me jump more in detail.
1. password_hash()
Creates a new password hash using a strong one-way hashing algorithm.
string password_hash ( string $password , int $algo [, array $options ] )
Here the function has three parameters:
PASSWORD_DEFAULT
– Use the default bcrypt algorithm.
PASSWORD_BCRYPT
– Use the algorithmCRYPT_BLOWFISH
to create the hash. This will produce a standard crypt() compatible hash using the “$2y$” identifier. The result will always be a 60 character string or onFALSE
on failure.

Here, cost and salt are the supported $options. here salt is random text and cost is used for adding complexity in the algorithm if we don’t provide both options than compiler will randomly select salt and cost would be default 10
warning: The salt option has been deprecated as of PHP 7.0.0. Now the preferred way is to simply use the salt that is generated by default.:
PASSWORD_ARGON2I
– Use the Argon2 hashing algorithm to create the hash. This option is only available for PHP version 7.2. According to cryptographic expert, Argon is one of the best cryptographic functions. This algorithm had won the Password Hashing Competition in July 2015.
supported $options for PASSWORD_ARGON2I is
- memory_cost (integer) – Maximum memory (in kibibytes) that may be used to compute the Argon2 hash. Defaults to
PASSWORD_ARGON2_DEFAULT_MEMORY_COST
.
- time_cost (integer) – Maximum amount of time it may take to compute the Argon2 hash. Defaults to
PASSWORD_ARGON2_DEFAULT_TIME_COST
.
- threads (integer) – Number of threads to use for computing the Argon2 hash. Defaults to
PASSWORD_ARGON2_DEFAULT_THREADS
.
2. password_verify()
password_verify()
a
bool password_verify ( string $password , string $hash )
Thepassword_verify()
function takes a plain password and the hashed string as its second argument. It returns true if the hash matches the specified password.
<?php if (password_verify($password, $hash)) { // Success! if given password and hash match other wise it will return false. } else { // Invalid credentials }
This function is safe enough for a timing attack.
3. password_needs_rehash()
This function checks to see if the supplied hash implements the algorithm and options provided. If not, it is assumed that the hash needs to be rehashed
bool password_needs_rehash ( string $hash , int $algo [, array $options ] )
- $hash is a hash which password_hash() function had generated in the first place.
- $algo is denoting the algorithm used in password_hash(). e.g (
PASSWORD_BCRYPT or PASSWORD_ARGON2I)
- Supported options according to the requirement of $algo go in $options.
We use this function when we change application-wise $algo or its relevant $options.
<?php
$new = [
'options' => ['cost' => 11],
'algo' => PASSWORD_DEFAULT,
'hash' => null
];
$password = 'rasmuslerdorf';
//generated hash of password
$oldHash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
//first we verify stored hash against plain-text password
if (password_verify($password, $oldHash)) {
// verify legacy password to new password_hash options
if (password_needs_rehash($oldHash, $new['algo'], $new['options'])) {
// rehash/store plain-text password using new hash
$newHash = password_hash($password, $new['algo'], $new['options']);
echo $newHash;
}
}
?>
The above example will output something similar to:
$2y$11$Wu5rN3u38.g/XWdUeA6Wj.PD.F0fLXXmZrMNFyzzg2UxkVmxlk41W
4. password_get_info()
The above function will give us information about the given hash.
// here $hash should be valid hash generated using password_hash function array password_get_info ( string $hash )
Project | Password hashing |
---|---|
CMS Airship | Argon2i |
Drupal | SHA512Crypt with multiple rounds |
Joomla | bcrypt |
Laravel | bcrypt with other options |
Symfony | bcrypt with other options |
WordPress | salted MD5 |
Categories
- Charts (1)
- Deployment Tools (1)
- IDE (1)
- JavaScript (3)
- Operating System (1)
- Other (30)
- PHP (1)
- Programming (6)