Skip to content

Commit 98ffb75

Browse files
[10.x] Verify hash config (#48814)
* Verify hash config * formatting --------- Co-authored-by: Taylor Otwell <taylor@laravel.com>
1 parent 38e7183 commit 98ffb75

File tree

5 files changed

+379
-34
lines changed

5 files changed

+379
-34
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use ReflectionClass;
4040
use ReflectionMethod;
4141
use ReflectionNamedType;
42+
use RuntimeException;
4243

4344
trait HasAttributes
4445
{
@@ -1316,7 +1317,19 @@ public static function encryptUsing($encrypter)
13161317
*/
13171318
protected function castAttributeAsHashedString($key, $value)
13181319
{
1319-
return $value !== null && ! Hash::isHashed($value) ? Hash::make($value) : $value;
1320+
if ($value === null) {
1321+
return null;
1322+
}
1323+
1324+
if (! Hash::isHashed($value)) {
1325+
return Hash::make($value);
1326+
}
1327+
1328+
if (! Hash::verifyConfiguration($value)) {
1329+
throw new RuntimeException("Could not verify the hashed value's configuration.");
1330+
}
1331+
1332+
return $value;
13201333
}
13211334

13221335
/**

src/Illuminate/Hashing/Argon2IdHasher.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Argon2IdHasher extends ArgonHasher
1818
*/
1919
public function check($value, $hashedValue, array $options = [])
2020
{
21-
if ($this->verifyAlgorithm && $this->info($hashedValue)['algoName'] !== 'argon2id') {
21+
if ($this->verifyAlgorithm && ! $this->isUsingCorrectAlgorithm($hashedValue)) {
2222
throw new RuntimeException('This password does not use the Argon2id algorithm.');
2323
}
2424

@@ -29,6 +29,17 @@ public function check($value, $hashedValue, array $options = [])
2929
return password_verify($value, $hashedValue);
3030
}
3131

32+
/**
33+
* Verify the hashed value's algorithm.
34+
*
35+
* @param string $hashedValue
36+
* @return bool
37+
*/
38+
protected function isUsingCorrectAlgorithm($hashedValue)
39+
{
40+
return $this->info($hashedValue)['algoName'] === 'argon2id';
41+
}
42+
3243
/**
3344
* Get the algorithm that should be used for hashing.
3445
*

src/Illuminate/Hashing/ArgonHasher.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ protected function algorithm()
9595
*/
9696
public function check($value, $hashedValue, array $options = [])
9797
{
98-
if ($this->verifyAlgorithm && $this->info($hashedValue)['algoName'] !== 'argon2i') {
98+
if ($this->verifyAlgorithm && ! $this->isUsingCorrectAlgorithm($hashedValue)) {
9999
throw new RuntimeException('This password does not use the Argon2i algorithm.');
100100
}
101101

@@ -118,6 +118,56 @@ public function needsRehash($hashedValue, array $options = [])
118118
]);
119119
}
120120

121+
/**
122+
* Verifies that the configuration is less than or equal to what is configured.
123+
*
124+
* @internal
125+
*/
126+
public function verifyConfiguration($value)
127+
{
128+
return $this->isUsingCorrectAlgorithm($value) && $this->isUsingValidOptions($value);
129+
}
130+
131+
/**
132+
* Verify the hashed value's algorithm.
133+
*
134+
* @param string $hashedValue
135+
* @return bool
136+
*/
137+
protected function isUsingCorrectAlgorithm($hashedValue)
138+
{
139+
return $this->info($hashedValue)['algoName'] === 'argon2i';
140+
}
141+
142+
/**
143+
* Verify the hashed value's options.
144+
*
145+
* @param string $hashedValue
146+
* @return bool
147+
*/
148+
protected function isUsingValidOptions($hashedValue)
149+
{
150+
['options' => $options] = $this->info($hashedValue);
151+
152+
if (
153+
! is_int($options['memory_cost'] ?? null) ||
154+
! is_int($options['time_cost'] ?? null) ||
155+
! is_int($options['threads'] ?? null)
156+
) {
157+
return false;
158+
}
159+
160+
if (
161+
$options['memory_cost'] > $this->memory ||
162+
$options['time_cost'] > $this->time ||
163+
$options['threads'] > $this->threads
164+
) {
165+
return false;
166+
}
167+
168+
return true;
169+
}
170+
121171
/**
122172
* Set the default password memory factor.
123173
*

src/Illuminate/Hashing/BcryptHasher.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function make($value, array $options = [])
6767
*/
6868
public function check($value, $hashedValue, array $options = [])
6969
{
70-
if ($this->verifyAlgorithm && $this->info($hashedValue)['algoName'] !== 'bcrypt') {
70+
if ($this->verifyAlgorithm && ! $this->isUsingCorrectAlgorithm($hashedValue)) {
7171
throw new RuntimeException('This password does not use the Bcrypt algorithm.');
7272
}
7373

@@ -88,6 +88,48 @@ public function needsRehash($hashedValue, array $options = [])
8888
]);
8989
}
9090

91+
/**
92+
* Verifies that the configuration is less than or equal to what is configured.
93+
*
94+
* @internal
95+
*/
96+
public function verifyConfiguration($value)
97+
{
98+
return $this->isUsingCorrectAlgorithm($value) && $this->isUsingValidOptions($value);
99+
}
100+
101+
/**
102+
* Verify the hashed value's algorithm.
103+
*
104+
* @param string $hashedValue
105+
* @return bool
106+
*/
107+
protected function isUsingCorrectAlgorithm($hashedValue)
108+
{
109+
return $this->info($hashedValue)['algoName'] === 'bcrypt';
110+
}
111+
112+
/**
113+
* Verify the hashed value's options.
114+
*
115+
* @param string $hashedValue
116+
* @return bool
117+
*/
118+
protected function isUsingValidOptions($hashedValue)
119+
{
120+
['options' => $options] = $this->info($hashedValue);
121+
122+
if (! is_int($options['cost'] ?? null)) {
123+
return false;
124+
}
125+
126+
if ($options['cost'] > $this->rounds) {
127+
return false;
128+
}
129+
130+
return true;
131+
}
132+
91133
/**
92134
* Set the default password work factor.
93135
*

0 commit comments

Comments
 (0)