Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
75.00% |
15 / 20 |
|
83.33% |
5 / 6 |
CRAP | |
0.00% |
0 / 1 |
Argon2Password | |
75.00% |
15 / 20 |
|
83.33% |
5 / 6 |
11.56 | |
0.00% |
0 / 1 |
isSupported | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
prepareParams | |
54.55% |
6 / 11 |
|
0.00% |
0 / 1 |
7.35 | |||
crypt | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
verify | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
toString | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
needsUpdate | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | |
21 | declare( strict_types = 1 ); |
22 | |
23 | /** |
24 | * Implements Argon2, a modern key derivation algorithm designed to resist GPU cracking and |
25 | * side-channel attacks. |
26 | * |
27 | * @see https://en.wikipedia.org/wiki/Argon2 |
28 | */ |
29 | class Argon2Password extends Password { |
30 | /** |
31 | * @var null[] Array with known password_hash() option names as keys |
32 | */ |
33 | private const KNOWN_OPTIONS = [ |
34 | 'memory_cost' => null, |
35 | 'time_cost' => null, |
36 | 'threads' => null, |
37 | ]; |
38 | |
39 | /** |
40 | * @inheritDoc |
41 | */ |
42 | protected function isSupported(): bool { |
43 | return defined( 'PASSWORD_ARGON2ID' ); |
44 | } |
45 | |
46 | /** |
47 | * @return mixed[] Array of 2nd and third parameters to password_hash() |
48 | */ |
49 | private function prepareParams(): array { |
50 | switch ( $this->config['algo'] ) { |
51 | case 'argon2i': |
52 | $algo = PASSWORD_ARGON2I; |
53 | break; |
54 | case 'argon2id': |
55 | case 'auto': |
56 | $algo = PASSWORD_ARGON2ID; |
57 | break; |
58 | default: |
59 | throw new LogicException( "Unexpected algo: {$this->config['algo']}" ); |
60 | |
61 | } |
62 | |
63 | $params = array_intersect_key( $this->config, self::KNOWN_OPTIONS ); |
64 | |
65 | return [ $algo, $params ]; |
66 | } |
67 | |
68 | /** |
69 | * @inheritDoc |
70 | */ |
71 | public function crypt( string $password ): void { |
72 | [ $algo, $params ] = $this->prepareParams(); |
73 | $this->hash = password_hash( $password, $algo, $params ); |
74 | } |
75 | |
76 | /** |
77 | * @inheritDoc |
78 | */ |
79 | public function verify( string $password ): bool { |
80 | return password_verify( $password, $this->hash ); |
81 | } |
82 | |
83 | /** |
84 | * @inheritDoc |
85 | */ |
86 | public function toString(): string { |
87 | $res = ":argon2:{$this->hash}"; |
88 | $this->assertIsSafeSize( $res ); |
89 | return $res; |
90 | } |
91 | |
92 | /** |
93 | * @inheritDoc |
94 | */ |
95 | public function needsUpdate(): bool { |
96 | [ $algo, $params ] = $this->prepareParams(); |
97 | return password_needs_rehash( $this->hash, $algo, $params ); |
98 | } |
99 | } |