Update password hashing algorithm

This commit is contained in:
Amit sharma
2026-04-28 11:03:49 +05:30
parent 622e8d9c26
commit 9ff2bac9ed
15 changed files with 157 additions and 160 deletions

View File

@@ -1181,8 +1181,8 @@ abstract class AdminTabCore
}
/* Automatically hash password */
if ($key == 'passwd' && !empty($value)) {
$crypto = new Hashing();
$value = $crypto->hash($value);
$objHash = new PasswordHashing();
$value = $objHash->passwordHash($value);
}
$object->{$key} = $value;
}

View File

@@ -390,8 +390,8 @@ class CustomerCore extends ObjectModel
return false;
}
if (isset($passwd)) {
$crypto = new Hashing();
if (!$crypto->checkHash($passwd, $result['passwd'])) {
$objHash = new PasswordHashing();
if (!$objHash->validateHash($passwd, $result['passwd'])) {
return false;
}
}
@@ -401,8 +401,8 @@ class CustomerCore extends ObjectModel
$this->{$key} = $value;
}
}
if (isset($passwd) && !$crypto->isFirstHash($passwd, $result['passwd'])) {
$this->passwd = $crypto->hash($passwd);
if (isset($passwd) && !$objHash->isPrimaryHash($passwd, $result['passwd'])) {
$this->passwd = $objHash->passwordHash($passwd);
$this->update();
}
return $this;
@@ -861,8 +861,8 @@ class CustomerCore extends ObjectModel
}
$this->is_guest = 0;
$crypto = new Hashing();
$this->passwd = $crypto->hash($password);
$objHash = new PasswordHashing();
$this->passwd = $objHash->passwordHash($password);
$this->cleanGroups();
$this->addGroups(array(Configuration::get('PS_CUSTOMER_GROUP'))); // add default customer group
$this->id_default_group = (int) Configuration::get('PS_CUSTOMER_GROUP');
@@ -897,8 +897,8 @@ class CustomerCore extends ObjectModel
public function setWsPasswd($passwd)
{
if ($this->id == 0 || $this->passwd != $passwd) {
$crypto = new Hashing();
$this->passwd = $crypto->hash($passwd);
$objHash = new PasswordHashing();
$this->passwd = $objHash->passwordHash($passwd);
}
return true;
}

View File

@@ -287,8 +287,8 @@ class EmployeeCore extends ObjectModel
}
if ($passwd !== null) {
$crypto = new Hashing();
if (!$crypto->checkHash($passwd, $result['passwd'])) {
$objHash = new PasswordHashing();
if (!$objHash->validateHash($passwd, $result['passwd'])) {
return false;
}
}
@@ -300,8 +300,8 @@ class EmployeeCore extends ObjectModel
}
}
if ($passwd !== null && !$crypto->isFirstHash($passwd, $result['passwd'])) {
$this->passwd = $crypto->hash($passwd);
if ($passwd !== null && !$objHash->isPrimaryHash($passwd, $result['passwd'])) {
$this->passwd = $objHash->passwordHash($passwd);
$this->update();
}
return $this;
@@ -375,20 +375,20 @@ class EmployeeCore extends ObjectModel
// validate and set password for the employee
public function setWsPasswd($passwd)
{
$crypto = new Hashing();
$objHash = new PasswordHashing();
if ($this->id != 0) {
if ($this->passwd != $passwd) {
if (!Validate::isHashedPassword($passwd, Validate::ADMIN_PASSWORD_LENGTH)) {
WebserviceRequest::getInstance()->setError(400, 'The password must be at least '.Validate::ADMIN_PASSWORD_LENGTH.' characters long.', 134);
} else {
$this->passwd = $crypto->hash($passwd);
$this->passwd = $objHash->passwordHash($passwd);
}
}
} else {
if (!Validate::isHashedPassword($passwd, Validate::ADMIN_PASSWORD_LENGTH)) {
WebserviceRequest::getInstance()->setError(400, 'The password must be at least '.Validate::ADMIN_PASSWORD_LENGTH.' characters long.', 134);
} else {
$this->passwd = $crypto->hash($passwd);
$this->passwd = $objHash->passwordHash($passwd);
}
}

View File

@@ -1,125 +0,0 @@
<?php
/**
* 2007-2017 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2017 PrestaShop SA
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
class HashingCore
{
/** @var array should contain hashing methods */
private $hashMethods = array();
/**
* Check if it's the first function of the array that was used for hashing
*
* @param string $passwd The password you want to check
* @param string $hash The hash you want to check
* @param string $staticSalt A static salt
*
* @return bool Result of the verify function
*/
public function isFirstHash($passwd, $hash, $staticSalt = _COOKIE_KEY_)
{
if (!count($this->hashMethods)) {
$this->initHashMethods();
}
$closure = reset($this->hashMethods);
return $closure['verify']($passwd, $hash, $staticSalt);
}
/**
* Iterate on hash_methods array and return true if it matches
*
* @param string $passwd The password you want to check
* @param string $hash The hash you want to check
* @param string $staticSalt A static salt
*
* @return bool `true` is returned if the function find a match else false
*/
public function checkHash($passwd, $hash, $staticSalt = _COOKIE_KEY_)
{
if (!count($this->hashMethods)) {
$this->initHashMethods();
}
foreach ($this->hashMethods as $closure) {
if ($closure['verify']($passwd, $hash, $staticSalt)) {
return true;
}
}
return false;
}
/**
* Hash the `$plaintextPassword` string and return the result of the 1st hashing method
* contained in Hashing::hashMethods
*
* @param string $plaintextPassword The password you want to hash
* @param string $staticSalt The static salt
*
* @return string
*/
public function hash($plaintextPassword, $staticSalt = _COOKIE_KEY_)
{
if (!count($this->hashMethods)) {
$this->initHashMethods();
}
$closure = reset($this->hashMethods);
return $closure['hash']($plaintextPassword, $staticSalt, $closure['option']);
}
/**
* Init hash methods
*
* @return void
*/
private function initHashMethods()
{
$this->hashMethods = array(
'bcrypt' => array(
'option' => array(),
'hash' => function ($passwd, $staticSalt, $option) {
return password_hash($passwd, PASSWORD_BCRYPT);
},
'verify' => function ($passwd, $hash, $staticSalt) {
return password_verify($passwd, $hash);
},
),
'md5' => array(
'option' => array(),
'hash' => function ($passwd, $staticSalt, $option) {
return md5($staticSalt.$passwd);
},
'verify' => function ($passwd, $hash, $staticSalt) {
return md5($staticSalt.$passwd) === $hash;
},
),
);
}
}

View File

@@ -1188,8 +1188,8 @@ abstract class ObjectModelCore implements Core_Foundation_Database_EntityInterfa
}
if ($field == 'passwd') {
if ($value = Tools::getValue($field)) {
$crypto = new Hashing();
$this->{$field} = $crypto->hash($value);
$objHash = new PasswordHashing();
$this->{$field} = $objHash->passwordHash($value);
}
} else {
$this->{$field} = $value;

122
classes/PasswordHashing.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
/**
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License version 3.0
* that is bundled with this package in the file LICENSE.md
* It is also available through the world-wide-web at this URL:
* https://opensource.org/license/osl-3-0-php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to support@qloapps.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this module to a newer
* versions in the future. If you wish to customize this module for your needs
* please refer to https://store.webkul.com/customisation-guidelines for more information.
*
* @author Webkul IN
* @copyright Since 2010 Webkul
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
*/
class PasswordHashingCore
{
/** @var array Available password hashing methods. */
private $passwordHashMethods = array();
/**
* Check whether the stored hash matches the primary hashing method.
*
* @param string $passwd Plain-text password to validate.
* @param string $hash Stored password hash.
* @param string $staticSalt Static salt used by legacy hash methods.
*
* @return bool
*/
public function isPrimaryHash($passwd, $hash, $staticSalt = _COOKIE_KEY_)
{
if (!count($this->passwordHashMethods)) {
$this->initPasswordHashMethods();
}
$closure = reset($this->passwordHashMethods);
return $closure['verify']($passwd, $hash, $staticSalt);
}
/**
* Validate a password against all supported hashing methods.
*
* @param string $passwd Plain-text password to validate.
* @param string $hash Stored password hash.
* @param string $staticSalt Static salt used by legacy hash methods.
*
* @return bool
*/
public function validateHash($passwd, $hash, $staticSalt = _COOKIE_KEY_)
{
if (!count($this->passwordHashMethods)) {
$this->initPasswordHashMethods();
}
foreach ($this->passwordHashMethods as $closure) {
if ($closure['verify']($passwd, $hash, $staticSalt)) {
return true;
}
}
return false;
}
/**
* Hash a plain-text password with the primary hashing method.
*
* @param string $plaintextPassword Password to hash.
* @param string $staticSalt Static salt reserved for legacy hash methods.
*
* @return string
*/
public function passwordHash($plaintextPassword, $staticSalt = _COOKIE_KEY_)
{
if (!count($this->passwordHashMethods)) {
$this->initPasswordHashMethods();
}
$closure = reset($this->passwordHashMethods);
return $closure['hash']($plaintextPassword, $staticSalt, $closure['option']);
}
/**
* Initialize the supported password hashing methods.
*
* @return void
*/
private function initPasswordHashMethods()
{
$this->passwordHashMethods = array(
'bcrypt' => array(
'option' => array(),
'hash' => function ($passwd, $staticSalt, $option) {
return password_hash($passwd, PASSWORD_BCRYPT);
},
'verify' => function ($passwd, $hash, $staticSalt) {
return password_verify($passwd, $hash);
},
),
'md5' => array(
'option' => array(),
'hash' => function ($passwd, $staticSalt, $option) {
return md5($staticSalt.$passwd);
},
'verify' => function ($passwd, $hash, $staticSalt) {
return md5($staticSalt.$passwd) === $hash;
},
),
);
}
}

View File

@@ -91,7 +91,7 @@ class ValidateCore
/**
* Check for password hash validity (legacy MD5 or bcrypt), or plaintext password.
*
* @param string $hash
* @param string $hashedPasswd
* @return bool Validity is ok or not
*/
public static function isHashedPassword($hashedPasswd)

View File

@@ -3840,8 +3840,8 @@ class AdminControllerCore extends Controller
}
/* Automatically hash password */
if ($key == 'passwd' && !empty($value)) {
$crypto = new Hashing();
$value = $crypto->hash($value);
$objHash = new PasswordHashing();
$value = $objHash->passwordHash($value);
}
$object->{$key} = $value;
}

View File

@@ -1378,8 +1378,8 @@ class WebserviceSpecificManagementBookingsCore Extends ObjectModel implements We
$objCustomer->firstname = $customerDetails['firstname'];
$objCustomer->lastname = $customerDetails['lastname'];
$objCustomer->email = $customerDetails['email'];
$crypto = new Hashing();
$objCustomer->passwd = $crypto->hash(Tools::passwdGen(32, 'RANDOM'));
$objHash = new PasswordHashing();
$objCustomer->passwd = $objHash->passwordHash(Tools::passwdGen(32, 'RANDOM'));
$objCustomer->phone = (isset($customerDetails['phone']) ? $customerDetails['phone'] : '');
$objCustomer->cleanGroups();
$objCustomer->add();

View File

@@ -2835,8 +2835,8 @@ class AdminImportControllerCore extends AdminController
AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $customer);
if ($customer->passwd) {
$crypto = new Hashing();
$customer->passwd = $crypto->hash($customer->passwd);
$objHash = new PasswordHashing();
$customer->passwd = $objHash->passwordHash($customer->passwd);
}
$customers_shop = array();

View File

@@ -263,8 +263,8 @@ class AdminLoginControllerCore extends AdminController
if (!count($this->errors)) {
$pwd = Tools::passwdGen(10, 'RANDOM');
$crypto = new Hashing();
$employee->passwd = $crypto->hash($pwd);
$objHash = new PasswordHashing();
$employee->passwd = $objHash->passwordHash($pwd);
$employee->last_passwd_gen = date('Y-m-d H:i:s', time());
$params = array(

View File

@@ -71,7 +71,7 @@ class IdentityControllerCore extends FrontController
$this->errors[] = Tools::displayError('This email address is not valid');
} elseif ($this->customer->email != $email && Customer::customerExists($email, true)) {
$this->errors[] = Tools::displayError('An account using this email address has already been registered.');
} elseif (!Tools::getIsset('old_passwd') || !(new Hashing())->checkHash($old_passwd, $this->context->cookie->passwd)) {
} elseif (!Tools::getIsset('old_passwd') || !(new PasswordHashing())->validateHash($old_passwd, $this->context->cookie->passwd)) {
$this->errors[] = Tools::displayError('The password you entered is incorrect.');
} elseif (Tools::getValue('passwd') != Tools::getValue('confirmation')) {
$this->errors[] = Tools::displayError('The password and confirmation do not match.');

View File

@@ -73,8 +73,8 @@ class PasswordControllerCore extends FrontController
} elseif ((strtotime($customer->last_passwd_gen.'+'.(int)Configuration::get('PS_PASSWD_TIME_FRONT').' minutes') - time()) > 0) {
Tools::redirect('index.php?controller=authentication&error_regen_pwd');
} else {
$crypto = new Hashing();
$customer->passwd = $crypto->hash($password = Tools::passwdGen(MIN_PASSWD_LENGTH, 'RANDOM'));
$objHash = new PasswordHashing();
$customer->passwd = $objHash->passwordHash($password = Tools::passwdGen(MIN_PASSWD_LENGTH, 'RANDOM'));
$customer->last_passwd_gen = date('Y-m-d H:i:s', time());
if ($customer->update()) {
Hook::exec('actionPasswordRenew', array('customer' => $customer, 'password' => $password));

View File

@@ -35,8 +35,8 @@ class InstallFixturesFashion extends InstallXmlLoader
public function createEntityCustomer($identifier, array $data, array $data_lang)
{
if ($identifier == 'John') {
$crypto = new Hashing();
$data['passwd'] = $crypto->hash('123456789');
$objHash = new PasswordHashing();
$data['passwd'] = $objHash->passwordHash('123456789');
$data['last_passwd_gen'] = date('Y-m-d H:i:s');
$data['birthday'] = date('Y-m-d', strtotime('-30 years'));
$data['newsletter_date_add'] = date('Y-m-d H:i:s');

View File

@@ -566,8 +566,8 @@ class InstallModelInstall extends InstallAbstractModel
$employee->firstname = Tools::ucfirst($data['admin_firstname']);
$employee->lastname = Tools::ucfirst($data['admin_lastname']);
$employee->email = $data['admin_email'];
$crypto = new Hashing();
$employee->passwd = $crypto->hash($data['admin_password']);
$objHash = new PasswordHashing();
$employee->passwd = $objHash->passwordHash($data['admin_password']);
$employee->last_passwd_gen = date('Y-m-d h:i:s', strtotime('-360 minutes'));
$employee->bo_theme = 'default';
$employee->default_tab = 1;