Skip to content

Hash::check not applying options before verifying Algorithm #55759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
GeNyaa opened this issue May 16, 2025 · 4 comments
Open

Hash::check not applying options before verifying Algorithm #55759

GeNyaa opened this issue May 16, 2025 · 4 comments

Comments

@GeNyaa
Copy link

GeNyaa commented May 16, 2025

Laravel Version

12.x, 11.x

PHP Version

8.2, 8.1

Database Driver & Version

No response

Description

When using;

Hash::check(
    'password',
    'hash',
    [
        'verify' => false,
    ]
);

it'll still verify the algorithm before running the rest of the function and will throw a bcrypt error, if the incorrect value is used.

Steps To Reproduce

make sure bcrypt verify is set to true in config.

Hash::check(
    'password',
    '$2a$12$JU/xbox8TdX8Yp7deAOAnu9KWeGtreepOspbfa4t9x7yaxICVfzuq',
    [
        'verify' => false,
    ]
);

results in an error thrown instead of a true or false.

@GeNyaa GeNyaa changed the title BcryptHasher::check not applying options before verifying Algorithm Hash::check not applying options before verifying Algorithm May 16, 2025
@ghabriel25
Copy link
Contributor

ghabriel25 commented May 17, 2025

@GeNyaa If you set it to true in config, that value will be used in constructor

Image

As you can see above, first check is passed, second check is the hashed password itself. It uses password_get_info to get the algorithm.

If this the result is not bcrypt it will throw a RuntimeException. I have tried your hashed password and it gives output unknown algorithm.

But I found out that if you pass option when using Hash::check, that options never used.

public function check(#[\SensitiveParameter] $value, $hashedValue, array $options = [])

I think it should be like this

public function check(#[\SensitiveParameter] $value, $hashedValue, array $options = [])
{
    if (is_null($hashedValue) || strlen($hashedValue) === 0) {
        return false;
    }

    if (! empty($options)) {
        $this->verifyAlgorithm = $options['verify'] ?? $this->verifyAlgorithm;
    }

    if ($this->verifyAlgorithm && ! $this->isUsingCorrectAlgorithm($hashedValue)) {
        throw new RuntimeException('This password does not use the Bcrypt algorithm.');
    }

    return parent::check($value, $hashedValue, $options);
}

@GeNyaa
Copy link
Author

GeNyaa commented May 18, 2025

The hash above is a different bcrypt version 2a instead of 2y, the hash itself should be the same though.

@crynobone
Copy link
Member

Is the step to reproduce used in any of Laravel documentation? If not, feel free to submit a PR to suggest the new usage.

@GeNyaa
Copy link
Author

GeNyaa commented May 19, 2025

I used verify false as an option to ignore the amount of rounds when checking the password. So it would allow me to check 8, 10 and 12 rounds without turning verify off inside the config/env vars. This doesn't seem documented in the documentation, but is working as expected. However when using 2a version hashes it errors out, which is why I thought this was a bug as it's suppose to just check the hash without verifying version or rounds.

I'll create a pr to address this later, when I have more time on my hands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants