So you have to update all the passwords of your users in database? If you twit your login script you will have to do nothing at all. Have a look at this:
Updating Md5 password hash to BCRYPT hash::
$passwordFromDatabase = "0d107d09f5bbe40cade3de5c71e9e9b7"; // md5 hash of "letmein"
$passwordFromForm = $_POST['password']; // $_POST['password'] == "letmein"
if(password_needs_rehash($passwordFromDatabase, PASSWORD_BCRYPT, ["cost" => 12]) && md5($passwordFromForm) === $passwordFromDatabase){
// generate new password
$newPasswordHash = password_hash($passwordFromForm, PASSWORD_BCRYPT, ["cost" => 12]);
// update hash from database - replace old hash $passwordFromDatabase with new hash $newPasswordHash
// after update login user
if(password_veryfi($passwordFromForm, $newPasswordHash)){
// user has logged in successfully and hash was updated
// redirect to user area
}else{
// ups something went wrong Exception
}
}else{
if($password_veryfi($passwordFromForm, $passwordFromDatabase)){
// user password hash from database is already BCRYPTed no need to rehash
// user has logged in successfully
// redirect to user area
}else{
// wrong password
// no access granted - stay where you are
}
}
The example above is universal. Instead of
... && md5($passwordFromForm) === ...){
you can use whatever nested hashing combination you have done to stored passwords. On the end it will end up as a BCRYP hash anyway.
Below read more about encryption and security, and how to define the right value of cost parameter to hash user password.
SLOW ALGOTITHM
The current standard is to use a slow hashing algorithm. PBKDF2, bcrypt or scrypt all take both a password and a salt as input and a configurable work factor - set this work factor as high as your users just accept on login time with your server's hardware. Reference
- PBKDF2 is simply an iterated fast hash (i.e. still efficiently
parallelizable). (It is a scheme which can be used with different
base algorithms. Use whatever algorithm you are using anyways in your
system.)
- Bcrypt needs some (4KB) working memory, and thus is less efficiently
implementable on a GPU with less than 4KB of per-processor cache.
- Scrypt uses a (configurable) large amount of memory additionally to
processing time, which makes it extremely costly to parallelize on
GPUs or custom hardware, while "normal" computers usually have enough
RAM available.
GOOD PASSWORD
The length of your password should not be less then 8 characters and it should use at least one:
- upper case
- one number and
- one special character
Setting up password 8 char long with lower and upper case and special char is capable of creating: 6 634 204 312 890 625 combinations. However if your password will be week let say 6 char small letters only you will only get:
308,915,776 combination. To make your account secure it is recommended to use more then 12 char for password length. CLICK for Password Combination Count Simulator
CRACKING SPEED (Changes every year giving crackers more process power of their GPUs or more powerful cloud computing)
When you design your password think about future processing power increase and tools that hackers will get.
This program IGHASHGPU v0.90 asserts to be able to do about 1300 millions of SHA-1 hashes (i.e. more than 2^30) in each second on a single ATI HD5870 GPU.
Assume a password of 40 bits of entropy, this needs 2^10 seconds, which is about 17 minutes.
A password of 44 bits of entropy (like the one in the famous XKCD comic) takes 68 minutes (worst case, average case is half of this).
Running on multiple GPUs in parallel speeds this up proportionally.
So, brute-forcing with fast hashes is a real danger, not a theoretical one. And many passwords have a much lower entropy, making brute-forcing even faster. Reference
SOLUTION
You can customise the speed of your algorithm by manipulating it cost. The higher the cost the longer will take to code and encode your password. The best would be probably aim for about 500 mls, wich make it really hard for attackers to brute force our password.
Password with 12 char and longer + slower algorithm will guarantee the decent amount of combination to be brute forced before the password will be cracked. Once we have decent password we can make life much harder to someone wanting to get in to our system by slowing the process of password verification to something that will make it really difficult and time/resource consuming. Set cost to a number that will affect in around 0.5s time taken to verify user password.
CUSTOMISE COST VALUE
How do you know how high should you set your cost since the script execution will be different for each server based on processing power and trafic ?
Well you should to measure the time it takes for verification process and customise the cost as it is appropriate for you.
<?php
/**
* This code will benchmark your server to determine how high of a cost you can
* afford. You want to set the highest cost that you can without slowing down
* you server too much. 8-10 is a good baseline, and more is good if your servers
* are fast enough. The code below aims for ≤ 50 milliseconds stretching time,
* which is a good baseline for systems handling interactive logins.
*/
$timeTarget = 0.50; // 500 milliseconds
$cost = 8; //start to measure from cost = 8
do {
$cost++;
$start = microtime(true);
password_hash("Ajd_hsk-K87&", PASSWORD_BCRYPT, ["cost" => $cost]);
$end = microtime(true);
} while (($end - $start) < $timeTarget);
echo "Appropriate Cost Found: " . $cost . "\n";
?>
Reference
The above function will return X number of cost that we need to use to meet our safety requirements.
Appropriate Cost Found: 13 //this result will be different based on your server machine.
This script is taken from php manual and enhanced to process 10x times longer. This would be generally secure way in most cases, but for admin and super admin login I would consider to make it even more time consuming (something about 1s), as those places are of more interest for real hackers.