From 1897404ab2ac625855ac90037d06d75cdc292595 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 12 May 2021 12:25:42 +0200 Subject: [PATCH] Allow adjusting the '$cost' parameter for BCrypt hashes --- .../password/algorithm/Bcrypt.class.php | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/wcfsetup/install/files/lib/system/user/authentication/password/algorithm/Bcrypt.class.php b/wcfsetup/install/files/lib/system/user/authentication/password/algorithm/Bcrypt.class.php index 403a49f05a..0fa4a86db1 100644 --- a/wcfsetup/install/files/lib/system/user/authentication/password/algorithm/Bcrypt.class.php +++ b/wcfsetup/install/files/lib/system/user/authentication/password/algorithm/Bcrypt.class.php @@ -15,9 +15,31 @@ use wcf\system\user\authentication\password\IPasswordAlgorithm; */ final class Bcrypt implements IPasswordAlgorithm { - private const OPTIONS = [ - 'cost' => 12, - ]; + /** + * @var int + */ + private $cost; + + /** + * @param int $cost The BCrypt 'cost' option for newly created hashes. It is recommended not to change this option. + */ + public function __construct(int $cost = 12) + { + if ($cost < 9) { + throw new \InvalidArgumentException(\sprintf( + "Refusing to accept BCrypt costs lower than '9', '%d' given.", + $cost + )); + } + if ($cost > 14) { + throw new \InvalidArgumentException(\sprintf( + "Refusing to accept BCrypt costs higher than '14', '%d' given.", + $cost + )); + } + + $this->cost = $cost; + } /** * @inheritDoc @@ -32,7 +54,7 @@ final class Bcrypt implements IPasswordAlgorithm */ public function hash(string $password): string { - return \password_hash($password, \PASSWORD_BCRYPT, self::OPTIONS); + return \password_hash($password, \PASSWORD_BCRYPT, $this->getOptions()); } /** @@ -40,6 +62,16 @@ final class Bcrypt implements IPasswordAlgorithm */ public function needsRehash(string $hash): bool { - return \password_needs_rehash($hash, \PASSWORD_BCRYPT, self::OPTIONS); + return \password_needs_rehash($hash, \PASSWORD_BCRYPT, $this->getOptions()); + } + + /** + * Returns the value to be used for password_*'s `$options` parameter. + */ + private function getOptions() + { + return [ + 'cost' => $this->cost, + ]; } } -- 2.20.1