<?php
/**
* This file implements the bcrypt Password Driver class.
*
* This file is part of the evoCore framework - {@link http://evocore.net/}
* See also {@link https://github.com/b2evolution/b2evolution}.
*
* @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
*
* @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
*
* @package evocore
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
load_class( 'users/model/passwords/_passworddriver.class.php', 'PasswordDriver' );
/**
* bcryptPasswordDriver Class
*
* @package evocore
*/
class bcryptPasswordDriver extends PasswordDriver
{
protected $code = 'bb$2a';
/**
* Length of salt
* @var integer
*/
protected $salt_length = 22;
/**
* Get prefix of the password driver
*
* @return string
*/
public function get_prefix()
{
return parent::get_prefix().'10$';
}
/**
* Hash password
*
* @param string Password
* @param string Salt
* @return string Hashed password
*/
public function hash( $password, $salt = '' )
{
// The 2x and 2y prefixes of bcrypt might not be supported
// Revert to 2a if this is the case
$code = ( ! $this->is_supported() ) ? 'bb$2a' : $this->get_code();
// Do not support 8-bit characters with $2a$ bcrypt
// Also see http://www.php.net/security/crypt_blowfish.php
if( $code === 'bb$2a' )
{
if( ord( $password[ strlen( $password ) - 1 ] ) & 128 )
{
return false;
}
}
if( empty( $salt ) )
{ // Generate new random if salt is not provided:
$salt = $this->get_random_salt();
}
$hash = crypt( $password, $this->get_prefix().$salt );
if( strlen( $hash ) < 60 )
{
return false;
}
return $this->clear_hash( $hash );
}
/**
* Get JavaScript code to hash password on browser/client side
*
* @param string Name of password variable in JS code
* @param string Name of salt variable in JS code
* @return string
*/
public function get_javascript_hash_code( $var_password_name, $var_salt_name )
{
$js_code = '
function bcrypt_clear_hash( hash )
{
return hash.substr( '.( strlen( $this->get_prefix() ) + $this->salt_length ).' );
}
function bcrypt_hash( password, salt )
{
var code = "'.( ! $this->is_supported() ? 'bb$2a' : $this->get_code() ).'";
if( code === "bb$2a" )
{
if( password[ password.length - 1 ].charCodeAt(0) & 128 )
{
return false;
}
}
var hash = TwinBcrypt.hashSync( password, "'.$this->get_prefix().'" + salt );
if( hash.length < 60 )
{
return false;
}
return bcrypt_clear_hash( hash );
}
bcrypt_hash( '.$var_password_name.', '.$var_salt_name.' );
';
return $js_code;
}
/**
* Get a random salt value with a length of 22 characters
*
* @return string Salt for password hashing
*/
protected function get_random_salt()
{
$salt = $this->hash_encode64( generate_random_key( $this->salt_length ), $this->salt_length );
// Save last generated salt to know what value write in DB on user password updating:
$this->last_generated_salt = $salt;
return $salt;
}
}
?>