How to Use Bcrypt For Hashing Passwords in PHP

How do you use bcrypt for hashing passwords in PHP?

bcrypt is a hashing algorithm which is scalable with hardware (via a configurable number of rounds). Its slowness and multiple rounds ensures that an attacker must deploy massive funds and hardware to be able to crack your passwords. Add to that per-password salts (bcrypt REQUIRES salts) and you can be sure that an attack is virtually unfeasible without either ludicrous amount of funds or hardware.

bcrypt uses the Eksblowfish algorithm to hash passwords. While the encryption phase of Eksblowfish and Blowfish are exactly the same, the key schedule phase of Eksblowfish ensures that any subsequent state depends on both salt and key (user password), and no state can be precomputed without the knowledge of both. Because of this key difference, bcrypt is a one-way hashing algorithm. You cannot retrieve the plain text password without already knowing the salt, rounds and key (password). [Source]

How to use bcrypt:

Using PHP >= 5.5-DEV

Password hashing functions have now been built directly into PHP >= 5.5. You may now use password_hash() to create a bcrypt hash of any password:

<?php
// Usage 1:
echo password_hash('rasmuslerdorf', PASSWORD_DEFAULT)."\n";
// $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// For example:
// $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

// Usage 2:
$options = [
'cost' => 11
];
echo password_hash('rasmuslerdorf', PASSWORD_BCRYPT, $options)."\n";
// $2y$11$6DP.V0nO7YI3iSki4qog6OQI5eiO6Jnjsqg7vdnb.JgGIsxniOn4C

To verify a user provided password against an existing hash, you may use the password_verify() as such:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}

Using PHP >= 5.3.7, < 5.5-DEV (also RedHat PHP >= 5.3.3)

There is a compatibility library on GitHub created based on the source code of the above functions originally written in C, which provides the same functionality. Once the compatibility library is installed, usage is the same as above (minus the shorthand array notation if you are still on the 5.3.x branch).

Using PHP < 5.3.7 (DEPRECATED)

You can use crypt() function to generate bcrypt hashes of input strings. This class can automatically generate salts and verify existing hashes against an input. If you are using a version of PHP higher or equal to 5.3.7, it is highly recommended you use the built-in function or the compat library. This alternative is provided only for historical purposes.

class Bcrypt{
private $rounds;

public function __construct($rounds = 12) {
if (CRYPT_BLOWFISH != 1) {
throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
}

$this->rounds = $rounds;
}

public function hash($input){
$hash = crypt($input, $this->getSalt());

if (strlen($hash) > 13)
return $hash;

return false;
}

public function verify($input, $existingHash){
$hash = crypt($input, $existingHash);

return $hash === $existingHash;
}

private function getSalt(){
$salt = sprintf('$2a$%02d$', $this->rounds);

$bytes = $this->getRandomBytes(16);

$salt .= $this->encodeBytes($bytes);

return $salt;
}

private $randomState;
private function getRandomBytes($count){
$bytes = '';

if (function_exists('openssl_random_pseudo_bytes') &&
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL is slow on Windows
$bytes = openssl_random_pseudo_bytes($count);
}

if ($bytes === '' && is_readable('/dev/urandom') &&
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
$bytes = fread($hRand, $count);
fclose($hRand);
}

if (strlen($bytes) < $count) {
$bytes = '';

if ($this->randomState === null) {
$this->randomState = microtime();
if (function_exists('getmypid')) {
$this->randomState .= getmypid();
}
}

for ($i = 0; $i < $count; $i += 16) {
$this->randomState = md5(microtime() . $this->randomState);

if (PHP_VERSION >= '5') {
$bytes .= md5($this->randomState, true);
} else {
$bytes .= pack('H*', md5($this->randomState));
}
}

$bytes = substr($bytes, 0, $count);
}

return $bytes;
}

private function encodeBytes($input){
// The following is code from the PHP Password Hashing Framework
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

$output = '';
$i = 0;
do {
$c1 = ord($input[$i++]);
$output .= $itoa64[$c1 >> 2];
$c1 = ($c1 & 0x03) << 4;
if ($i >= 16) {
$output .= $itoa64[$c1];
break;
}

$c2 = ord($input[$i++]);
$c1 |= $c2 >> 4;
$output .= $itoa64[$c1];
$c1 = ($c2 & 0x0f) << 2;

$c2 = ord($input[$i++]);
$c1 |= $c2 >> 6;
$output .= $itoa64[$c1];
$output .= $itoa64[$c2 & 0x3f];
} while (true);

return $output;
}
}

You can use this code like this:

$bcrypt = new Bcrypt(15);

$hash = $bcrypt->hash('password');
$isGood = $bcrypt->verify('password', $hash);

Alternatively, you may also use the Portable PHP Hashing Framework.

How to use BCRYPT with password_hash() in PHP

The whole idea behind password_hash() is to always use an up-to-date hashing algorithm. Currently, the default algo. used is exactly BCRYPT. It even allows you to pass more options in order to make your password even more secure(for example your own salt or work factor).
And what's even better, is that php also offers the password_needs_rehash() function that allows you to check later if a given hash was created using the current algo,and if not, you can just rehash the password.
Check out the official php documentation page for pasword_hash(): http://php.net/manual/en/function.password-hash.php

Hash passwords with bcrypt in the database or in php code?

I would go for the second option and calculate the BCrypt hash in the PHP code.

If you place the password inside the SQL statement, there are additional possibilities it can leak. First the connection to the database must be made secure and then it could end up in log files.

If you place the hash in the SQL statement, you only have to care about a secure transfer to your application, the rest will be safe because only the hash can leak. As a bonus you do not have to care about SQL-injection and encoding/escaping issues. Another advantage is, that you are independend of the database system, you can also support databases without a BCrypt implementation (most databases do not offer a BCrypt function, or only by installing an extension).

Class to hash password using bcrypt

To call it as an object:

class PasswordHash {
public function generate_bcrypt($user_password) {
return password_hash($user_password, PASSWORD_DEFAULT);
}
}

$password = 'password';
$passwordhash = new PasswordHash();
echo $passwordhash->generate_bcrypt($password);

To call it using the static method

class PasswordHash {
public static function generate_bcrypt($user_password) {
return password_hash($user_password, PASSWORD_DEFAULT);
}
}

$password = 'password';
echo PasswordHash::generate_bcrypt($password);

You'll need to adapt this to fit the separation of your class files, but you can get the general idea from the examples.

how to use correctly bcrypt php class

Thank you @Magnus Eriksson, i did it and it works.

 <?php
function logUser() {

require( './connexion.php' );

$sql_user = 'SELECT * FROM tgn_users WHERE login="' . $_POST[ 'login' ] . '"';

$req = mysqli_query( $connexion, $sql_user )or die( mysqli_error( $connexion ) );

if ( mysqli_num_rows( $req ) > 0 ) {

$row = mysqli_fetch_assoc( $req );

if ( Bcrypt::checkPassword( $_POST[ 'mdp_user' ], $row[ 'mdp_user' ] ) ) {

if($row['login']='admin'){

header( 'Location: ../../admin/' );

}else{

$_SESSION[ 'nom_user' ] = $row[ 'nom_user' ];
$_SESSION[ 'prenom_user' ] = $row[ 'prenom_user' ];
$_SESSION[ 'id_user' ] = $row[ 'id_user' ];
//$lifetime = 60*60*24*30;
//setcookie(session_name($_SESSION['nom_user']), session_id($_SESSION['id_user']),time()+$lifetime,'/');
header( 'Location: ../../profile.php' );
}

}else {
$_SESSION[ 'message' ] = "Erreur de log et/ou de pwd";
header( "Location: " . $_SERVER[ 'HTTP_REFERER' ] );

}
}

}?>

But i have a problem in my condition. Whatever login is put i'am redirected to the admin page :(. AM I missing something in my if condition ?

How to use bcrypt with php for password authentication?

You must store the password AND the salt used when you BCrypt, or you'll never get the same string.
This class seems pretty broken to me, don't use it. See this example and the documentation to directly use PHP's crypt function.

Edit : You probably should use PHPPass, seems like a well tested and referenced library.



Related Topics



Leave a reply



Submit