Being that it is 2024 DSI uses technology other than basic HTML for its web presence.



Your browser is not enabling JavaScript

To truly use our website this will need to be corrected.
Or, use an alternative browser.

DSI Globe Logo

DSI

877-803-4374

Welcome!

DSI -> 4business -> University (Help you do it) -> Programming

Php Crypt Security Md5 To Bcrypt

Finalized by: Steve T on August 13, 2015

Security is extremely important more so as time goes by. The most common data attack is brute force and if Moore's Law is followed the small progression of time makes this type of attack increasingly easier to be successful.  

MD5 security is not encryption it is simply obfuscation uniqueness is not true. A password of "This is my password" will always have an MD5 value of "27406f62c3db0c5e010bb95b4aacbd85" within a predefined system. 

True encryption utilizes a key or 'salt' and with Blowfish (bcrypt) that salt is embedded within the encrypted data. Using the same password data from above strained through bcrypt now becomes "$2y$13$EiR2X7O4iKO6ZMgQybvDwu/YC./lakBafR/.orxp7hp.01AALCd1." but if you run it a second time it becomes "$2y$13$OPgnEBn0SfmCjNAUSYs6bO7n78gpz4g3yNmyFuMeovf3tG5oGfms6". Validating the data uses the embedded key (salt) to determine a match. At first you may think this would help the bad guys in deciphering your password or data, it does not.

This type of dynamic encryption makes it more difficult to use a brute force attack. It actually complicated the algorithm used to decrypt the data, but wait, there's more. With Blowfish you can add another factor called rounds or cost. This further enhances the security by asking Blowfish to iterate the algorithm x amount of times. Rather than taking milliseconds to run a single brute force attack it can now take several seconds if you choose. It may not sound like much, but a brute force attack expects thousands of results (pass or fail) per second. This is very substantial.

First off, check that you have Blowfish operational on your server. PHP 5.3 and higher should. Run the following.

<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
    echo "CRYPT_BLOWFISH is enabled!";
}
else {
    echo "CRYPT_BLOWFISH is not available";
}
?>

If it is not enabled consider upgrading your PHP to a more recent version. 

If it is enabled you can use this enhanced security method.

 

You want to start by randomizing the salt and determining the cost (rounds). Here is a simple function for doing that. 

// --- Bcrypt function
// --- DSI | www.itdsi.com

$rounds = 13; // --- Define cost.
function better_crypt($input, $rounds)
  {
    $salt = "";
    $salt_chars = array_merge(range('A','Z'), range('a','z'), range(0,9));
    for($i=0; $i < 22; $i++) {
      $salt .= $salt_chars[array_rand($salt_chars)];
    }
    return crypt($input, sprintf('$2y$%02d$', $rounds) . $salt);
  }

You could use a predefined salt value, but that sort of defeats the purpose. The $rounds value is the iterations you want Blowfish to run. The higher the number the more processing power is required to encrypt or decrypt the data. The default value is 7 but if you need a faster, less secure solution you can lower this to 4. This function could be added to an include such as a config file. 

 

After you set the salt and define the cost you can start to use the function. 

$password = "This is my password";

$hashed_pw = better_crypt($password, $rounds);
echo $password."<br>".$hashed_pw;

This shows the raw password and the encrypted version of the password.

 

We can then validate the encrypted data with this. 

// --- Check password
if(crypt($password, $hashed_pw) == $hashed_pw) {
    echo "Password is correct";
  }

PHP deduces the salt and the cost of the encrypted password from a database or other variable and compares the user entered password or variable in question. Pretty simple right?

 

So what do you do if you have a database of users that have stored passwords in MD5 or DES? You could setup something to have all the users change their passwords. A notification or a trigger upon next login. Wouldn't it be less stressful and simpler to automate the process and have this happen blindly?

Try this...

// --- Check if PW is Bcrypt, change if not Bcrypt
// --- DSI | www.itdsi.com

if (substr($pwInDatabase, 0, 1) == "$") {

    // Password already converted, continue login sequence

} else {
    
    // User still using the old MD5, update it!

    if (md5($password) == $pwInDatabase) {
        $db->storePw(better_crypt($password, $rounds));
    }
    
    // Continue login sequence
}

The end user will not be aware of the algorithm change. If you have users that don't login often and you are concerned with leaving an open door for the bad guys you could always push out a notification email to the users informing them of security changes and the importance of them logging into their account.