Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.45% |
21 / 22 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
AbstractPbkdf2Password | |
100.00% |
21 / 21 |
|
100.00% |
3 / 3 |
9 | |
100.00% |
1 / 1 |
getDefaultParams | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getDelimiter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
crypt | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
7 | |||
getDigestAlgo | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
pbkdf2 | n/a |
0 / 0 |
n/a |
0 / 0 |
0 |
1 | <?php |
2 | /** |
3 | * Implements the AbstractPbkdf2Password class for the MediaWiki software. |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | */ |
22 | |
23 | declare( strict_types = 1 ); |
24 | |
25 | namespace MediaWiki\Password; |
26 | |
27 | /** |
28 | * A PBKDF2-hashed password |
29 | * |
30 | * This is a computationally complex password hash for use in modern applications. |
31 | * The number of rounds can be configured by $wgPasswordConfig['pbkdf2']['cost']. |
32 | * |
33 | * To support different native implementations of PBKDF2 and the underlying |
34 | * hash algorithms, the following subclasses are available: |
35 | * |
36 | * - Pbkdf2PasswordUsingOpenSSL is the preferred, more efficient option |
37 | * and is used by default. |
38 | * - Pbkdf2PasswordUsingHashExtension provides compatibility with PBKDF2 |
39 | * password hashes computed using legacy algorithms. |
40 | * |
41 | * @since 1.40 |
42 | */ |
43 | abstract class AbstractPbkdf2Password extends ParameterizedPassword { |
44 | protected function getDefaultParams(): array { |
45 | return [ |
46 | 'algo' => $this->config['algo'], |
47 | 'rounds' => $this->config['cost'], |
48 | 'length' => $this->config['length'] |
49 | ]; |
50 | } |
51 | |
52 | protected function getDelimiter(): string { |
53 | return ':'; |
54 | } |
55 | |
56 | public function crypt( string $password ): void { |
57 | if ( count( $this->args ) == 0 ) { |
58 | $this->args[] = base64_encode( random_bytes( 16 ) ); |
59 | } |
60 | |
61 | $algo = $this->params['algo']; |
62 | $salt = base64_decode( $this->args[0] ); |
63 | $rounds = (int)$this->params['rounds']; |
64 | $length = (int)$this->params['length']; |
65 | |
66 | $digestAlgo = $this->getDigestAlgo( $algo ); |
67 | if ( $digestAlgo === null ) { |
68 | throw new PasswordError( "Unknown or unsupported algo: $algo" ); |
69 | } |
70 | if ( $rounds <= 0 || $rounds >= 0x7fffffff ) { |
71 | throw new PasswordError( 'Invalid number of rounds.' ); |
72 | } |
73 | if ( $length <= 0 || $length >= 0x7fffffff ) { |
74 | throw new PasswordError( 'Invalid length.' ); |
75 | } |
76 | |
77 | $hash = $this->pbkdf2( $digestAlgo, $password, $salt, $rounds, $length ); |
78 | $this->hash = base64_encode( $hash ); |
79 | } |
80 | |
81 | /** |
82 | * Get the implementation specific name for a hash algorithm. |
83 | * |
84 | * @param string $algo Algorithm specified in the password hash string |
85 | * @return string|null $algo Implementation specific name, or null if unsupported |
86 | */ |
87 | abstract protected function getDigestAlgo( string $algo ): ?string; |
88 | |
89 | /** |
90 | * Call the PBKDF2 implementation, which hashes the password. |
91 | * |
92 | * @param string $digestAlgo Implementation specific hash algorithm name |
93 | * @param string $password Password to hash |
94 | * @param string $salt Salt as a binary string |
95 | * @param int $rounds Number of iterations |
96 | * @param int $length Length of the hash value in bytes |
97 | * @return string Hash value as a binary string |
98 | * @throws PasswordError If an internal error occurs in hashing |
99 | */ |
100 | abstract protected function pbkdf2( |
101 | string $digestAlgo, |
102 | string $password, |
103 | string $salt, |
104 | int $rounds, |
105 | int $length |
106 | ): string; |
107 | } |
108 | |
109 | /** @deprecated since 1.43 use MediaWiki\\Password\\AbstractPbkdf2Password */ |
110 | class_alias( AbstractPbkdf2Password::class, 'AbstractPbkdf2Password' ); |