1 | <?php |
||
13 | class DjangoPassword implements IPassword { |
||
14 | /** |
||
15 | * @var string The hash method to use when hashing passwords. |
||
16 | */ |
||
17 | public $hashMethod; |
||
18 | |||
19 | /** |
||
20 | * Initiailize an instance of the {@link DjangoPassword} class. |
||
21 | * |
||
22 | * @param string $hashMethod The hasm method used to hash the passwords. |
||
23 | */ |
||
24 | 5 | public function __construct($hashMethod = 'crypt') { |
|
27 | |||
28 | /** |
||
29 | * Generate a random salt that is compatible with {@link crypt()}. |
||
30 | * |
||
31 | * @return string|null Returns the salt as a string or **null** if the crypt algorithm isn't known. |
||
32 | */ |
||
33 | 4 | protected function generateCryptSalt() { |
|
34 | 4 | if (CRYPT_BLOWFISH === 1) { |
|
35 | 4 | $salt = str_replace('+', '/', base64_encode(openssl_random_pseudo_bytes(12))); |
|
36 | 4 | } elseif (CRYPT_EXT_DES) { |
|
37 | $count_log2 = 24; //min($this->iteration_count_log2 + 8, 24); |
||
38 | # This should be odd to not reveal weak DES keys, and the |
||
39 | # maximum valid value is (2**24 - 1) which is odd anyway. |
||
40 | $count = (1 << $count_log2) - 1; |
||
41 | |||
42 | $salt = '_'; |
||
43 | $salt .= $this->itoa64[$count & 0x3f]; |
||
|
|||
44 | $salt .= $this->itoa64[($count >> 6) & 0x3f]; |
||
45 | $salt .= $this->itoa64[($count >> 12) & 0x3f]; |
||
46 | $salt .= $this->itoa64[($count >> 18) & 0x3f]; |
||
47 | |||
48 | $salt .= substr(base64_encode(openssl_random_pseudo_bytes(3), 0, 3)); |
||
49 | } else { |
||
50 | $salt = null; |
||
51 | } |
||
52 | 4 | return $salt; |
|
53 | } |
||
54 | |||
55 | /** |
||
56 | * Hashes a plaintext password. |
||
57 | * |
||
58 | * @param string $password The password to hash. |
||
59 | * @return string Returns the hashed password. |
||
60 | * @throws \Exception Throws an exception when the hash method is invalid. |
||
61 | */ |
||
62 | 8 | public function hash($password) { |
|
63 | 8 | if ($this->hashMethod === 'crypt') { |
|
64 | 4 | $salt = $this->generateCryptSalt(); |
|
65 | try { |
||
66 | 4 | $hash = crypt($password, $salt); |
|
67 | 4 | } catch (\Exception $ex) { |
|
68 | throw new \Exception("$salt is an invalid salt.", $ex); |
||
69 | } |
||
70 | 8 | } elseif (in_array($this->hashMethod, hash_algos())) { |
|
71 | 4 | $salt = base64_encode(openssl_random_pseudo_bytes(12)); |
|
72 | 4 | $hash = hash($this->hashMethod, $salt.$password); |
|
73 | 4 | } else { |
|
74 | 1 | throw new \Exception("The {$this->hashMethod} hash method is invalid.", 500); |
|
75 | } |
||
76 | |||
77 | 8 | $result = $this->hashMethod.'$'.$salt.'$'.$hash; |
|
78 | 8 | return $result; |
|
79 | } |
||
80 | |||
81 | /** |
||
82 | * {@inheritdoc} |
||
83 | */ |
||
84 | 6 | public function needsRehash($hash) { |
|
85 | 6 | if (strpos($hash, '$') === false) { |
|
86 | 1 | return true; |
|
87 | } else { |
||
88 | 6 | list($method,,) = explode('$', $hash, 3); |
|
89 | 6 | switch (strtolower($method)) { |
|
90 | 6 | case 'crypt': |
|
91 | 6 | case 'sha256': |
|
92 | 3 | return false; |
|
93 | 3 | default: |
|
94 | 3 | return true; |
|
95 | 3 | } |
|
96 | } |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Check to make sure a password matches its stored hash. |
||
101 | * |
||
102 | * @param string $password The password to verify. |
||
103 | * @param string $hash The stored password hash. |
||
104 | * @return bool Returns `true` if the password matches the stored hash. |
||
105 | */ |
||
106 | 8 | public function verify($password, $hash) { |
|
121 | } |
||
122 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: