Rev 65 | Rev 67 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 65 | Rev 66 | ||
---|---|---|---|
Line 142... | Line 142... | ||
142 | function vts_crypt_hash($algo, $str_password, $str_salt, $ver='1', $mode='ps', $iterations=0/*default*/) { |
142 | function vts_crypt_hash($algo, $str_password, $str_salt, $ver='1', $mode='ps', $iterations=0/*default*/) { |
143 | if ($ver == '1') { |
143 | if ($ver == '1') { |
144 | if ($mode == 'sp') { |
144 | if ($mode == 'sp') { |
145 | $payload = $str_salt.$str_password; |
145 | $payload = $str_salt.$str_password; |
146 | $algo_supported_natively = in_array($algo, hash_algos()); |
146 | $algo_supported_natively = in_array($algo, hash_algos()); |
147 | if (!$algo_supported_natively && ($algo === 'sha3-512') && function_exists('sha3_512')) { |
147 | if (!$algo_supported_natively && str_starts_with($algo, 'sha3-') && method_exists('\bb\Sha3\Sha3', 'hash')) { |
- | 148 | $bits = explode('-',$algo)[1]; |
|
148 | $bin_hash = sha3_512($payload, true); |
149 | $bin_hash = \bb\Sha3\Sha3::hash($payload, $bits, true); |
149 | } else { |
150 | } else { |
150 | $bin_hash = hash($algo, $payload, true); |
151 | $bin_hash = hash($algo, $payload, true); |
151 | } |
152 | } |
152 | } else if ($mode == 'ps') { |
153 | } else if ($mode == 'ps') { |
153 | $payload = $str_password.$str_salt; |
154 | $payload = $str_password.$str_salt; |
154 | $algo_supported_natively = in_array($algo, hash_algos()); |
155 | $algo_supported_natively = in_array($algo, hash_algos()); |
155 | if (!$algo_supported_natively && ($algo === 'sha3-512') && function_exists('sha3_512')) { |
156 | if (!$algo_supported_natively && str_starts_with($algo, 'sha3-') && method_exists('\bb\Sha3\Sha3', 'hash')) { |
- | 157 | $bits = explode('-',$algo)[1]; |
|
156 | $bin_hash = sha3_512($payload, true); |
158 | $bin_hash = \bb\Sha3\Sha3::hash($payload, $bits, true); |
157 | } else { |
159 | } else { |
158 | $bin_hash = hash($algo, $payload, true); |
160 | $bin_hash = hash($algo, $payload, true); |
159 | } |
161 | } |
160 | } else if ($mode == 'sps') { |
162 | } else if ($mode == 'sps') { |
161 | $payload = $str_salt.$str_password.$str_salt; |
163 | $payload = $str_salt.$str_password.$str_salt; |
162 | $algo_supported_natively = in_array($algo, hash_algos()); |
164 | $algo_supported_natively = in_array($algo, hash_algos()); |
163 | if (!$algo_supported_natively && ($algo === 'sha3-512') && function_exists('sha3_512')) { |
165 | if (!$algo_supported_natively && str_starts_with($algo, 'sha3-') && method_exists('\bb\Sha3\Sha3', 'hash')) { |
- | 166 | $bits = explode('-',$algo)[1]; |
|
164 | $bin_hash = sha3_512($payload, true); |
167 | $bin_hash = \bb\Sha3\Sha3::hash($payload, $bits, true); |
165 | } else { |
168 | } else { |
166 | $bin_hash = hash($algo, $payload, true); |
169 | $bin_hash = hash($algo, $payload, true); |
167 | } |
170 | } |
168 | } else if ($mode == 'hmac') { |
171 | } else if ($mode == 'hmac') { |
169 | if (version_compare(PHP_VERSION, '7.2.0') >= 0) { |
172 | if (version_compare(PHP_VERSION, '7.2.0') >= 0) { |
170 | $algo_supported_natively = in_array($algo, hash_hmac_algos()); |
173 | $algo_supported_natively = in_array($algo, hash_hmac_algos()); |
171 | } else { |
174 | } else { |
172 | $algo_supported_natively = in_array($algo, hash_algos()); |
175 | $algo_supported_natively = in_array($algo, hash_algos()); |
173 | } |
176 | } |
174 | if (!$algo_supported_natively && ($algo === 'sha3-512') && function_exists('sha3_512_hmac')) { |
177 | if (!$algo_supported_natively && str_starts_with($algo, 'sha3-') && method_exists('\bb\Sha3\Sha3', 'hash_hmac')) { |
- | 178 | $bits = explode('-',$algo)[1]; |
|
175 | $bin_hash = sha3_512_hmac($str_password, $str_salt, true); |
179 | $bin_hash = \bb\Sha3\Sha3::hash_hmac($str_password, $str_salt, $bits, true); |
176 | } else { |
180 | } else { |
177 | $bin_hash = hash_hmac($algo, $str_password, $str_salt, true); |
181 | $bin_hash = hash_hmac($algo, $str_password, $str_salt, true); |
178 | } |
182 | } |
179 | } else if ($mode == 'pbkdf2') { |
183 | } else if ($mode == 'pbkdf2') { |
- | 184 | $algo_supported_natively = in_array($algo, hash_algos()); |
|
- | 185 | if (!$algo_supported_natively && str_starts_with($algo, 'sha3-') && method_exists('\bb\Sha3\Sha3', 'hash_pbkdf2')) { |
|
180 | if ($iterations == 0) { |
186 | if ($iterations == 0) { |
181 | // TODO: Find good value for iterations, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2 |
187 | $iterations = 2000; // because userland implementations are much slower, we must choose a small value... |
182 | $iterations = 500000; |
- | |
183 | } |
188 | } |
184 | $algo_supported_natively = in_array($algo, hash_algos()); |
189 | $bits = explode('-',$algo)[1]; |
185 | if (!$algo_supported_natively && ($algo === 'sha3-512') && function_exists('sha3_512_pbkdf2')) { |
- | |
186 | $bin_hash = sha3_512_pbkdf2($str_password, $str_salt, $iterations, 0, true); |
190 | $bin_hash = \bb\Sha3\Sha3::hash_pbkdf2($str_password, $str_salt, $iterations, $bits, 0, true); |
187 | } else { |
191 | } else { |
- | 192 | if ($iterations == 0) { |
|
- | 193 | // Recommendations taken from https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2 |
|
- | 194 | // I am not sure if these recommendations are correct. They write PBKDF2-HMAC-SHA1... |
|
- | 195 | // Does this count for us, or does hash_pbkdf2() implement PBKDF2-SHA1 rather than PBKDF2-HMAC-SHA1? |
|
- | 196 | if ($algo == 'sha3-512') $iterations = 100000; |
|
- | 197 | else if ($algo == 'sha3-384') $iterations = 100000; |
|
- | 198 | else if ($algo == 'sha3-256') $iterations = 100000; |
|
- | 199 | else if ($algo == 'sha3-224') $iterations = 100000; |
|
- | 200 | else if ($algo == 'sha512') $iterations = 210000; // value by owasp.org cheatcheat (28.02.2023) |
|
- | 201 | else if ($algo == 'sha512/256') $iterations = 210000; // value by owasp.org cheatcheat (28.02.2023) |
|
- | 202 | else if ($algo == 'sha512/224') $iterations = 210000; // value by owasp.org cheatcheat (28.02.2023) |
|
- | 203 | else if ($algo == 'sha384') $iterations = 600000; |
|
- | 204 | else if ($algo == 'sha256') $iterations = 600000; // value by owasp.org cheatcheat (28.02.2023) |
|
- | 205 | else if ($algo == 'sha224') $iterations = 600000; |
|
- | 206 | else if ($algo == 'sha1') $iterations = 1300000; // value by owasp.org cheatcheat (28.02.2023) |
|
- | 207 | else if ($algo == 'md5') $iterations = 5000000; |
|
- | 208 | else $iterations = 5000; |
|
- | 209 | } |
|
188 | $bin_hash = hash_pbkdf2($algo, $str_password, $str_salt, $iterations, 0, true); |
210 | $bin_hash = hash_pbkdf2($algo, $str_password, $str_salt, $iterations, 0, true); |
189 | } |
211 | } |
190 | } else { |
212 | } else { |
191 | throw new Exception("Invalid VTS crypt version 1 mode. Expect sp, ps, sps, hmac, or pbkdf2."); |
213 | throw new Exception("Invalid VTS crypt version 1 mode. Expect sp, ps, sps, hmac, or pbkdf2."); |
192 | } |
214 | } |
Line 216... | Line 238... | ||
216 | $algo = $params['a']; |
238 | $algo = $params['a']; |
217 | 239 | ||
218 | if (!isset($params['m'])) throw new Exception('Param "m" (mode) missing'); |
240 | if (!isset($params['m'])) throw new Exception('Param "m" (mode) missing'); |
219 | $mode = $params['m']; |
241 | $mode = $params['m']; |
220 | 242 | ||
- | 243 | if ($mode == 'pbkdf2') { |
|
221 | if (($mode == 'pbkdf2') && !isset($params['i'])) throw new Exception('Param "i" (iterations) missing'); |
244 | if (!isset($params['i'])) throw new Exception('Param "i" (iterations) missing'); |
222 | $iterations = $params['i']; |
245 | $iterations = $params['i']; |
- | 246 | } else { |
|
- | 247 | $iterations = 0; |
|
- | 248 | } |
|
223 | 249 | ||
224 | // Create a VTS MCF 1.0 hash based on the parameters of $hash and the password $password |
250 | // Create a VTS MCF 1.0 hash based on the parameters of $hash and the password $password |
225 | $calc_authkey_1 = vts_crypt_hash($algo, $password, $bin_salt, $ver, $mode, $iterations); |
251 | $calc_authkey_1 = vts_crypt_hash($algo, $password, $bin_salt, $ver, $mode, $iterations); |
226 | 252 | ||
227 | // We rewrite the MCF to make sure that they match (if params have the wrong order) |
253 | // We rewrite the MCF to make sure that they match (if params have the wrong order) |