Completed
Push — b0.25.0 ( 535bde...57b0c8 )
by Sebastian
07:17
created

Password   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Test Coverage

Coverage 93.33%

Importance

Changes 0
Metric Value
wmc 6
eloc 17
dl 0
loc 131
ccs 14
cts 15
cp 0.9333
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getInfo() 0 3 1
A hash() 0 9 2
A __construct() 0 5 1
A verify() 0 3 1
A needsRehash() 0 3 1
1
<?php
2
3
/**
4
 * Linna Framework.
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2018, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types=1);
11
12
namespace Linna\Authentication;
13
14
use UnexpectedValueException;
15
16
/**
17
 * Provide methods for manage password, this class use PHP password hashing function,
18
 * see php documentation for more information.
19
 * <a href="http://php.net/manual/en/book.password.php">http://php.net/manual/en/book.password.php</a>
20
 */
21
class Password
22
{
23
    /**
24
     * @var array An associative array containing options
25
     *
26
     * http://php.net/manual/en/function.password-hash.php
27
     */
28
    protected $options = [
29
        1 => ['cost' => 11],
30
        2 => [
31
            'memory_cost' => 1024,
32
            'time_cost' => 2,
33
            'threads' => 2
34
        ]
35
    ];
36
37
    /**
38
     * @var int Password default algorithm
39
     */
40
    protected $algo = 1;
41
42
    /**
43
     * Class constructor.
44
     * <p>For password algorithm constants see <a href="http://php.net/manual/en/password.constants.php">Password Constants</a>.</p>
45
     * <pre><code class="php">//Options passed to class constructor as ['key' => 'value'] array.
46
     * $password = new Password(PASSWORD_DEFAULT, [
47
     *     'cost' => 11
48
     * ]);
49
     * </code></pre>
50
     *
51
     * @param int   $algo
52
     * @param array $options
53
     */
54 283
    public function __construct(int $algo = 1, array $options = [])
55
    {
56 283
        $this->algo = $algo;
57
58 283
        $this->options[$algo] = array_replace_recursive($this->options[$algo], $options);
59 283
    }
60
61
    /**
62
     * Verifies if a password matches an hash and return the result as boolean.
63
     * <pre><code class="php">$password = new Password();
64
     *
65
     * $storedHash = '$2y$11$cq3ZWO18l68X7pGs9Y1fveTGcNJ/iyehrDZ10BAvbY8LaBXNvnyk6';
66
     * $password = 'FooPassword';
67
     *
68
     * $verified = $password->verify($password, $storedHash);
69
     * </code></pre>
70
     *
71
     * @param string $password
72
     * @param string $hash
73
     *
74
     * @return bool True if password match, false if not.
75
     */
76 44
    public function verify(string $password, string $hash): bool
77
    {
78 44
        return password_verify($password, $hash);
79
    }
80
81
    /**
82
     * Create password hash from the given string and return it.
83
     * <pre><code class="php">$password = new Password();
84
     *
85
     * $hash = $password->hash('FooPassword');
86
     *
87
     * //var_dump result
88
     * //$2y$11$cq3ZWO18l68X7pGs9Y1fveTGcNJ/iyehrDZ10BAvbY8LaBXNvnyk6
89
     * var_dump($hash)
90
     * </code></pre>
91
     *
92
     * @param string $password
93
     *
94
     * @return string
95
     */
96 21
    public function hash(string $password): string
97
    {
98 21
        $hash = password_hash($password, $this->algo, $this->options[$this->algo]);
99
100 21
        if ($hash === false) {
101
            throw new UnexpectedValueException('Password hashing fails.');
102
        }
103
104 21
        return $hash;
105
    }
106
107
    /**
108
     * Checks if the given hash matches the algorithm and the options provided.
109
     * <pre><code class="php">$password = new Password();
110
     *
111
     * $hash = '$2y$11$cq3ZWO18l68X7pGs9Y1fveTGcNJ/iyehrDZ10BAvbY8LaBXNvnyk6';
112
     *
113
     * //true if rehash is needed, false if no
114
     * $rehashCheck = $password->needsRehash($hash);
115
     * </code></pre>
116
     *
117
     * @param string $hash
118
     *
119
     * @return bool
120
     */
121 2
    public function needsRehash(string $hash): bool
122
    {
123 2
        return password_needs_rehash($hash, $this->algo, $this->options[$this->algo]);
124
    }
125
126
    /**
127
     * Returns information about the given hash.
128
     * <pre><code class="php">$password = new Password();
129
     *
130
     * $hash = '$2y$11$cq3ZWO18l68X7pGs9Y1fveTGcNJ/iyehrDZ10BAvbY8LaBXNvnyk6';
131
     *
132
     * $info = $password->getInfo($hash);
133
     *
134
     * //var_dump result
135
     * //[
136
     * //    'algo' => 1,
137
     * //    'algoName' => 'bcrypt',
138
     * //    'options' => [
139
     * //        'cost' => int 11
140
     * //    ]
141
     * //]
142
     * var_dump($info);
143
     * </code></pre>
144
     *
145
     * @param string $hash
146
     *
147
     * @return array
148
     */
149 2
    public function getInfo(string $hash): array
150
    {
151 2
        return password_get_info($hash);
152
    }
153
}
154