Skip to content

Commit 18e0951

Browse files
committed
add $options param to Password methods
1 parent 01b7268 commit 18e0951

2 files changed

Lines changed: 32 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## v4.1.14-alpha
44
- Fix issue with scopes being applied twice in Unique::getPaginatedQuery (https://github.com/userfrosting/extend-user/issues/2)
55
- Update Bower dependencies in core Sprinkle
6+
- Refactor the `Password` class to use `hash_equals` for legacy passwords (prevent timing-based attacks) and factor out the default cost (#814)
67

78
## v4.1.13-alpha
89
- `ufTable`: Implement `rowTemplate` for customizing how rows are rendered (#787)

app/sprinkles/account/src/Util/Password.php

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,27 @@
1414
*/
1515
class Password
1616
{
17-
const DEFAULT_COST = 12;
17+
/**
18+
* Default crypt cost factor.
19+
*
20+
* @var int
21+
*/
22+
protected static $rounds = 12;
1823

1924
/**
2025
* Returns the hashing type for a specified password hash.
2126
*
2227
* Automatically detects the hash type: "sha1" (for UserCake legacy accounts), "legacy" (for 0.1.x accounts), and "modern" (used for new accounts).
2328
* @param string $password the hashed password.
29+
* @param array $options
2430
* @return string "sha1"|"legacy"|"modern".
2531
*/
26-
public static function getHashType($password)
32+
public static function getHashType($password, array $options = [])
2733
{
2834
// If the password in the db is 65 characters long, we have an sha1-hashed password.
2935
if (strlen($password) == 65) {
3036
return 'sha1';
31-
} elseif (substr($password, 0, 7) == '$2y$'.self::$_DEFAULT_COST.'$') {
37+
} elseif (substr($password, 0, 7) == '$2y$' . static::cost($options) . '$') {
3238
return 'legacy';
3339
}
3440

@@ -39,12 +45,15 @@ public static function getHashType($password)
3945
* Hashes a plaintext password using bcrypt.
4046
*
4147
* @param string $password the plaintext password.
48+
* @param array $options
4249
* @return string the hashed password.
4350
* @throws HashFailedException
4451
*/
45-
public static function hash($password)
52+
public static function hash($password, array $options = [])
4653
{
47-
$hash = password_hash($password, PASSWORD_BCRYPT);
54+
$hash = password_hash($password, PASSWORD_BCRYPT, [
55+
'cost' => static::cost($options),
56+
]);
4857

4958
if (!$hash) {
5059
throw new HashFailedException();
@@ -60,9 +69,11 @@ public static function hash($password)
6069
* @param string $hash The hash to compare against.
6170
* @return boolean True if the password matches, false otherwise.
6271
*/
63-
public static function verify($password, $hash)
72+
public static function verify($password, $hash, array $options = [])
6473
{
65-
if (static::getHashType($hash) == 'sha1') {
74+
$hashType = static::getHashType($hash, $options);
75+
76+
if ($hashType == 'sha1') {
6677
// Legacy UserCake passwords
6778
$salt = substr($hash, 0, 25); // Extract the salt from the hash
6879
$hashInput = $salt . sha1($salt . $password);
@@ -72,11 +83,11 @@ public static function verify($password, $hash)
7283

7384
return false;
7485

75-
} elseif (static::getHashType($hash) == 'legacy') {
86+
} elseif ($hashType == 'legacy') {
7687
// Homegrown implementation (assuming that current install has been using a cost parameter of 12)
7788
// Used for manual implementation of bcrypt.
7889
$extract = substr($hash, 0, 60);
79-
$compare = crypt($password, '$2y$' . self::$DEFAULT_COST . '$' . substr($hash, 60));
90+
$compare = crypt($password, '$2y$' . static::cost($options) . '$' . substr($hash, 60));
8091

8192
if (hash_equals($extract, $compare) === true) {
8293
return true;
@@ -88,4 +99,15 @@ public static function verify($password, $hash)
8899
// Modern implementation
89100
return password_verify($password, $hash);
90101
}
102+
103+
/**
104+
* Extract the cost value from the options array.
105+
*
106+
* @param array $options
107+
* @return int
108+
*/
109+
protected static function cost(array $options = [])
110+
{
111+
return isset($options['rounds']) ? $options['rounds'] : static::$rounds;
112+
}
91113
}

0 commit comments

Comments
 (0)