SmfPassword::needsRehash()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Todd Burry <[email protected]>
4
 * @copyright 2009-2014 Vanilla Forums Inc.
5
 * @license MIT
6
 */
7
8
namespace Garden\Password;
9
10
/**
11
 * Implements the password hash from Simple Machines Forums (SMF).
12
 *
13
 * Note that smf salts passwords with usernames. In order to use a smf password with this class you must concatenate
14
 * the username to the end of the password hash in the following way:
15
 *
16
 * ```php
17
 * // Password hash in php.
18
 * $passwordHash = $sha1PasswordHash.'$'.$username;
19
 * ```
20
 *
21
 * ```sql
22
 * -- Password hash in mysql.
23
 * select concat(memberName, '$', password) as passwordHash
24
 * from smf_members
25
 * ```
26
 *
27
 * The smf password hash is not a good choice for a default password hashing algorithm for several reasons.
28
 *
29
 * 1. It uses the username as a salt which could change thus invalidating the hash.
30
 * 2. The username is not a secure field and is thus a bad choice for a password salt.
31
 * 3. It relies on sha1 which is susceptible to a rainbow table attack.
32
 */
33
class SmfPassword implements IPassword {
34
35
    /**
36
     * Hashes a plaintext password.
37
     *
38
     * Although smf uses the username as salt, this hashing algorithm generates a random salt.
39
     *
40
     * @param string $password The password to hash.
41
     * @return string Returns the hashed password.
42
     */
43 3
    public function hash($password) {
44 3
        $salt = base64_encode(openssl_random_pseudo_bytes(12));
45 3
        $hash = sha1(strtolower($salt).$password);
46
47 3
        return $hash.'$'.$salt;
48
    }
49
50
    /**
51
     * Checks if a given password hash needs to be re-hashed to to a stronger algorithm.
52
     *
53
     * @param string $hash The hash to check.
54
     * @return bool Returns `true`
55
     */
56 1
    public function needsRehash($hash) {
57 1
        return false;
58
    }
59
60
    /**
61
     * Check to make sure a password matches its stored hash.
62
     *
63
     * @param string $password The password to verify.
64
     * @param string $hash The stored password hash.
65
     * @return bool Returns `true` if the password matches the stored hash.
66
     */
67 3
    public function verify($password, $hash) {
68 3
        list($storedHash, $username) = $this->splitHash($hash);
69 3
        $result = (sha1(strtolower($username).$password) == $storedHash);
70 3
        return $result;
71
    }
72
73
    /**
74
     * Split a password hash and salt into its separate components.
75
     *
76
     * @param string $hash The full password hash.
77
     * @return array An array in the form of [$hash, $username].
78
     */
79 3
    protected function splitHash($hash) {
80 3
        if (strpos($hash, '$') === false) {
81 1
            return [false, false];
82
        } else {
83 2
            return explode('$', $hash, 2);
84
        }
85
    }
86
}
87