What is the best way to compare hashed strings? (PHP)
Should I use if(strc开发者_如何学JAVAmp(md5($string),$hash)==0)
or if(md5($string)==$hash)
You should be very careful when comparing hashes directly for things like authentification as you could be opening a window to a timing attack.
Although it sounds very counterintuitive, you should to a full comparison of the string, avoiding any optimizations (i.e. exiting early if a character is different).
Here are some links about the problem:
- https://wiki.php.net/rfc/timing_attack
- http://codahale.com/a-lesson-in-timing-attacks/
- http://carlos.bueno.org/2011/10/timing.html
And here are some ideas in order to fix it:
- The fastest and easiest: just use
hash_equals()
if available (PHP 5.6 and greater). - https://github.com/symfony/polyfill-php56/blob/master/Php56.php (
hash_equals()
polyfill) - https://github.com/zendframework/zend-crypt/blob/master/src/Utils.php (
compareStrings()
)
If you compare strings, use strcmp
or ===
. People prefer ===
because strcmp
can be confusing (it returns 0
on success, wat).
You must use ===
, not ==
. ==
will convert both operands to integers if they can be interpreted as such, and because an MD5 hash doesn’t fit in an integer, they will be truncated around the half. Therefore, only the first halves of the hashes have to be equal. See http://phpsadness.com/sad/47.
If you are hashing passwords, consider using a slow and strong hashing algorithm such as PBKDF2, rather than MD5.
If you're using anything newer than PHP 5.6 (and including) you should use timing attack safe string comparison function.
if (hash_equals($expected, $correct)) {
}
(If you're on PHP 5.5 or earlier, see here for equivalents.)
Actually you should use password_verify
for this and also use all other password_*
functions.
They are available in PHP >= 5.5.0.
As a fallback you can use this polyfill. It currently works with PHP >= 5.3.7.
And if you really cannot/want to use this there is still hash_equals
(and polyfills for that) as @MM. already said.
I think if(md5($string) == $hash)
is better, because you have only one comparison instead of 2 (stcmp & ==).
md5 generates only ascii-chars which don't need a binary safe comparsion.
精彩评论