Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.45% covered (success)
95.45%
21 / 22
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractPbkdf2Password
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
3 / 3
9
100.00% covered (success)
100.00%
1 / 1
 getDefaultParams
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getDelimiter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 crypt
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
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
23declare( strict_types = 1 );
24
25namespace 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 */
43abstract 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 */
110class_alias( AbstractPbkdf2Password::class, 'AbstractPbkdf2Password' );