What is the best way to compare hashed strings? (PHP)
Solution 1
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()
)
Solution 2
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.
Solution 3
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.)
webnat0
Updated on July 09, 2022Comments
-
webnat0 almost 2 years
Should I use
if(strcmp(md5($string),$hash)==0)
orif(md5($string)==$hash)
-
Felix Kling about 13 yearsUse
strcmp
in custom sort functions. For "normal" use, comparing the strings directly is easier and easier to read. -
ereOn over 11 yearsFor anyone reading this thread, you probably shouldn't do that at all.
-
caw almost 10 years
-
rugk over 7 yearsNo MD5, no MD5, no MD5!
-
-
BoltClock over 11 yearsWow... that's truly sad indeed.
-
Claudiu over 8 yearsLook @MM answer. Second of all md5 is obsolete (proven that it can be hacked). Use sha (a better, not the best).
-
lszrh over 8 yearsOf course, you should use sha over md5. But the questioner asked which he should use. If someone asks you: "Do you want a strawberry ice cream or a chocolate ice cream?", you cannot answer "I take vanilla ice cream". Furthermore the question is not about using a hash algorithm, but about comparing values.
-
rugk over 7 yearsWe do not talk about icecream here, but about security. So the answer is indeed "Do not use anything of what you proposed here!". And BTW: Also SHA-1 must not be used for passwords.
-
David almost 7 yearsWho says this is about security? Maybe he just wants to hash contents of a file to see if its equal to another one.
-
Fabiano Araujo about 6 yearsI know this is an old answer but it's important to notice that this "sadness" was posted to PHP 5.4.4. 3v4l.org/EDcdY shows us that from versions 5.4.4 to 5.6.30 and 7+, the statement above is not true, though inferior versions will indeed result in a true statement comparing only half of the string.