Subversion Repositories php_utils

Rev

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)