PasswordHasher   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 5
eloc 15
c 5
b 0
f 0
dl 0
loc 83
ccs 11
cts 11
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A hash() 0 3 1
A validate() 0 7 2
A __construct() 0 8 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Security;
6
7
/**
8
 * PasswordHasher allows generating password hash and verifying passwords against a hash.
9
 */
10
final class PasswordHasher
11
{
12
    private ?string $algorithm;
13
    private array $parameters;
14
15
    private const SAFE_PARAMETERS = [
16
        PASSWORD_BCRYPT => [
17
            'cost' => 13,
18
        ],
19
    ];
20
21
    /**
22
     * @param string|null $algorithm Algorithm to use. If not specified, PHP chooses safest algorithm available in the
23
     * current version of PHP.
24
     * @param array|null $parameters Algorithm parameters. If not specified, safe defaults are used.
25
     *
26
     * @see https://www.php.net/manual/en/function.password-hash.php
27
     */
28 5
    public function __construct(?string $algorithm = PASSWORD_DEFAULT, array $parameters = null)
29
    {
30 5
        $this->algorithm = $algorithm;
31
32 5
        if ($parameters === null) {
33 4
            $this->parameters = self::SAFE_PARAMETERS[$algorithm] ?? [];
34
        } else {
35 1
            $this->parameters = $parameters;
36
        }
37
    }
38
39
    /**
40
     * Generates a secure hash from a password and a random salt.
41
     *
42
     * The generated hash can be stored in database.
43
     * Later when a password needs to be validated, the hash can be fetched and passed
44
     * to {@see validate()}. For example,
45
     *
46
     * ```php
47
     * // generates the hash (usually done during user registration or when the password is changed)
48
     * $hash = (new PasswordHasher())->hash($password);
49
     * // ...save $hash in database...
50
     *
51
     * // during login, validate if the password entered is correct using $hash fetched from database
52
     * if ((new PasswordHasher())->validate($password, $hash)) {
53
     *     // password is good
54
     * } else {
55
     *     // password is bad
56
     * }
57
     * ```
58
     *
59
     * @param string $password The password to be hashed.
60
     *
61
     * @return string The password hash string. The output length might increase
62
     * in future versions of PHP (http://php.net/manual/en/function.password-hash.php)
63
     *
64
     * @see validate()
65
     * @psalm-suppress InvalidNullableReturnType
66
     * @psalm-suppress NullableReturnStatement
67
     */
68 3
    public function hash(string $password): string
69
    {
70 3
        return password_hash($password, $this->algorithm, $this->parameters);
0 ignored issues
show
Bug Best Practice introduced by
The expression return password_hash($pa...thm, $this->parameters) could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
71
    }
72
73
    /**
74
     * Verifies a password against a hash.
75
     *
76
     * @param string $password The password to verify.
77
     * @param string $hash The hash to verify the password against.
78
     *
79
     * @throws \InvalidArgumentException on bad password/hash parameters or if crypt() with Blowfish hash is not
80
     * available.
81
     *
82
     * @return bool whether the password is correct.
83
     *
84
     * @see hash()
85
     */
86 3
    public function validate(string $password, string $hash): bool
87
    {
88 3
        if ($password === '') {
89 1
            throw new \InvalidArgumentException('Password must be a string and cannot be empty.');
90
        }
91
92 2
        return password_verify($password, $hash);
93
    }
94
}
95