Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
18 | class PhpbbPassword implements IPassword { |
||
19 | const ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; |
||
20 | |||
21 | /** |
||
22 | * Check for a correct password. |
||
23 | * |
||
24 | * @param string $password The password in plain text. |
||
25 | * @param string $hash The stored password hash. |
||
26 | * @return bool Returns true if the password is correct, false if not. |
||
27 | */ |
||
28 | 3 | public function verify($password, $hash) { |
|
35 | |||
36 | /** |
||
37 | * The crypt function/replacement. |
||
38 | * |
||
39 | * @param string $password The password to encrypt. |
||
40 | * @param string $setting The hash prefix setting. It should start with $H$. |
||
41 | * @return string The encypted password. |
||
42 | */ |
||
43 | 3 | private function cryptPrivate($password, $setting) { |
|
44 | 3 | $itoa64 = PhpbbPassword::ITOA64; |
|
45 | 3 | $output = '*'; |
|
46 | |||
47 | // Check for correct hash |
||
48 | 3 | if (substr($setting, 0, 3) != '$H$') { |
|
49 | return $output; |
||
50 | } |
||
51 | |||
52 | 3 | $count_log2 = strpos($itoa64, $setting[3]); |
|
53 | |||
54 | 3 | if ($count_log2 < 7 || $count_log2 > 30) { |
|
55 | return $output; |
||
56 | } |
||
57 | |||
58 | 3 | $count = 1 << $count_log2; |
|
59 | 3 | $salt = substr($setting, 4, 8); |
|
60 | |||
61 | 3 | if (strlen($salt) != 8) { |
|
62 | return $output; |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * We're kind of forced to use MD5 here since it's the only |
||
67 | * cryptographic primitive available in all versions of PHP |
||
68 | * currently in use. To implement our own low-level crypto |
||
69 | * in PHP would result in much worse performance and |
||
70 | * consequently in lower iteration counts and hashes that are |
||
71 | * quicker to crack (by non-PHP code). |
||
72 | */ |
||
73 | 3 | View Code Duplication | if (PHP_VERSION >= 5) { |
1 ignored issue
–
show
|
|||
74 | 3 | $hash = md5($salt.$password, true); |
|
75 | do { |
||
76 | 3 | $hash = md5($hash.$password, true); |
|
77 | 3 | } while (--$count); |
|
78 | } else { |
||
79 | $hash = pack('H*', md5($salt.$password)); |
||
80 | do { |
||
81 | $hash = pack('H*', md5($hash.$password)); |
||
82 | } while (--$count); |
||
83 | } |
||
84 | |||
85 | 3 | $output = substr($setting, 0, 12); |
|
86 | 3 | $output .= $this->encode64($hash, 16); |
|
87 | |||
88 | 3 | return $output; |
|
89 | } |
||
90 | |||
91 | /** |
||
92 | * Encode hash. |
||
93 | * |
||
94 | * @param string $input The input to encode. |
||
95 | * @param int $count The number of characters to encode. |
||
96 | * @return string The encoded string. |
||
97 | */ |
||
98 | 3 | protected function encode64($input, $count) { |
|
99 | 3 | $itoa64 = PhpbbPassword::ITOA64; |
|
100 | 3 | $output = ''; |
|
101 | 3 | $i = 0; |
|
102 | |||
103 | do { |
||
104 | 3 | $value = ord($input[$i++]); |
|
105 | 3 | $output .= $itoa64[$value & 0x3f]; |
|
106 | |||
107 | 3 | if ($i < $count) { |
|
108 | 3 | $value |= ord($input[$i]) << 8; |
|
109 | } |
||
110 | |||
111 | 3 | $output .= $itoa64[($value >> 6) & 0x3f]; |
|
112 | |||
113 | 3 | if ($i++ >= $count) { |
|
114 | 3 | break; |
|
115 | } |
||
116 | |||
117 | 3 | if ($i < $count) { |
|
118 | 3 | $value |= ord($input[$i]) << 16; |
|
119 | } |
||
120 | |||
121 | 3 | $output .= $itoa64[($value >> 12) & 0x3f]; |
|
122 | |||
123 | 3 | if ($i++ >= $count) { |
|
124 | break; |
||
125 | } |
||
126 | |||
127 | 3 | $output .= $itoa64[($value >> 18) & 0x3f]; |
|
128 | 3 | } while ($i < $count); |
|
129 | |||
130 | 3 | return $output; |
|
131 | } |
||
132 | |||
133 | /** |
||
134 | * Hashes a plaintext password. |
||
135 | * |
||
136 | * @param string $password The password to hash. |
||
137 | * @return string Returns the hashed password. |
||
138 | */ |
||
139 | 3 | public function hash($password) { |
|
149 | |||
150 | /** |
||
151 | * Generate a password salt based on the given input string. |
||
152 | * |
||
153 | * @param string $input The input string to generate the salt from. |
||
154 | * @return string Returns the password salt prefixed with `$P$`. |
||
155 | */ |
||
156 | 3 | private function gensaltPrivate($input) { |
|
165 | |||
166 | /** |
||
167 | * Checks if a given password hash needs to be re-hashed to to a stronger algorithm. |
||
168 | * |
||
169 | * @param string $hash The hash to check. |
||
170 | * @return bool Returns `true` |
||
171 | */ |
||
172 | 1 | public function needsRehash($hash) { |
|
175 | } |
||
176 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.