SmfPassword   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 54
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 54
ccs 14
cts 14
cp 1
rs 10
c 0
b 0
f 0
wmc 5
lcom 0
cbo 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A hash() 0 6 1
A needsRehash() 0 3 1
A verify() 0 5 1
A splitHash() 0 7 2
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