Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions src/Illuminate/Hashing/ArgonHasher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Hashing;

use Error;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use RuntimeException;

Expand Down Expand Up @@ -60,13 +61,13 @@ public function __construct(array $options = [])
*/
public function make(#[\SensitiveParameter] $value, array $options = [])
{
$hash = @password_hash($value, $this->algorithm(), [
'memory_cost' => $this->memory($options),
'time_cost' => $this->time($options),
'threads' => $this->threads($options),
]);

if (! is_string($hash)) {
try {
$hash = password_hash($value, $this->algorithm(), [
'memory_cost' => $this->memory($options),
'time_cost' => $this->time($options),
'threads' => $this->threads($options),
]);
} catch (Error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might it be helpful to add this caught Error as the previous parameter of the RuntimeException?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yah, I was considering that. is there any security implication though, because it could expose info like which algo is being used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it already showing the hashing algo in the exception message?

In theory, these exceptions should not be passed along to the end-user when the app is set to production mode.

(I don't have a strong opinion on it either way, just a thought as I have fallen into the practice of forwarding exceptions when throwing a new one)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also catches a generic Error object, which could be caused by any number of things. At least this way you can see what specifically happened.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could also expose other info, like cost factor, etc.

you're right, it should never show to users in production.

I'd say give a PR a shot, and see what other people think.

throw new RuntimeException('Argon2 hashing not supported.');
}

Expand Down
11 changes: 6 additions & 5 deletions src/Illuminate/Hashing/BcryptHasher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Hashing;

use Error;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use RuntimeException;

Expand Down Expand Up @@ -44,11 +45,11 @@ public function __construct(array $options = [])
*/
public function make(#[\SensitiveParameter] $value, array $options = [])
{
$hash = password_hash($value, PASSWORD_BCRYPT, [
'cost' => $this->cost($options),
]);

if ($hash === false) {
try {
$hash = password_hash($value, PASSWORD_BCRYPT, [
'cost' => $this->cost($options),
]);
} catch (Error) {
throw new RuntimeException('Bcrypt hashing not supported.');
}

Expand Down
21 changes: 21 additions & 0 deletions tests/Hashing/HasherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,25 @@ public function testIsHashedWithNonHashedValue()
{
$this->assertFalse($this->hashManager->isHashed('foo'));
}

public function testBasicBcryptNotSupported()
{
$this->expectException(RuntimeException::class);

(new BcryptHasher(['rounds' => 0]))->make('password');
}

public function testBasicArgon2iNotSupported()
{
$this->expectException(RuntimeException::class);

(new ArgonHasher(['time' => 0]))->make('password');
}

public function testBasicArgon2idNotSupported()
{
$this->expectException(RuntimeException::class);

(new Argon2IdHasher(['time' => 0]))->make('password');
}
}