Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strcmp vs. == vs. === in PHP for checking hash equality

I'm using crypt() to hash passwords in PHP, and am trying to work out the safest way of testing equality of the resulting hash when performing password checks.

There are three options that I can see:

Option 1 - Double Equals

function checkPassword($hash, $password)
{
    return crypt($password, $hash) == $hash;
}

Option 2 - Triple Equals

function checkPassword($hash, $password)
{
    return crypt($password, $hash) === $hash;
}

Option 3 - strcmp()

function checkPassword($hash, $password)
{
    return strcmp(crypt($password, $hash), $hash) === 0;
}

My intuition tells me that option 1 is a bad idea, due to the lack of type checking, and that options 2 or 3 are likely to be better. However, I can't work out if there's a specific case that === or strcmp would fail under. Which is safest for this purpose?

like image 496
Polynomial Avatar asked Feb 05 '13 15:02

Polynomial


People also ask

How do I check if two variables are equal in PHP?

Equal Operator == The comparison operator called Equal Operator is the double equal sign “==”. This operator accepts two inputs to compare and returns true value if both of the values are same (It compares only value of variable, not data types) and return a false value if both of the values are not same.

Is there any reason to use strcmp () for strings comparison?

You can use strcmp() if you wish to order/compare strings lexicographically. If you just wish to check for equality then == is just fine. Like in usort. In fact, it's pretty much made for sorting.

How do I check if two strings are not equal in PHP?

PHP strcmp() Function: The strcmp() is an inbuilt function in PHP that is used to compare two strings.

What does === mean in PHP?

=== Operator: This operator is used to check the given values and its data type are equal or not. If yes, then it returns true, otherwise it returns false.


1 Answers

When it comes to security I prefer to use the === operator. === ensures the two operands are exactly the same, without trying to accomodate some casting in order to "help" the comparison to reach a successful match - as it may help while developing thanks to a loose-typed language, like PHP.

Of course, one of the operand is to be trusted. A hash from the database is trustable, while the user input is not.

One can always dither for a while, coming to the conclusion there is no risk using == in a specific case. Maybe. But for instance

  "0afd9f7b678fdefca" == 0 is true
  "aafd9f7b678fdefca" == 0 is also true

as PHP tries to convert the "hash" into a number (probably using atoi) which gives 0. While it is unlikely crypt returns 0, I'd prefer to maximize the cases where the passwords don't match (and answer a support call) by using ===, than allowing a rare case that I didn't think about by using ==.

As for strcmp, the function returns <0 or >0 if different, and 0 if equal. But

  strcmp("3", 0003) returns 0
  strcmp("0003", 0003) returns -3

which are not surprising after all. A literal 0003 is actually an integer, 3 and since strcmp expects a string, the 3 will be converted to "3". But that shows there is some conversion that may happen in this case, since strcmp is a function, while === is part of the language.

So my preference in that case goes to === (which is faster than == anyway).

like image 166
Déjà vu Avatar answered Sep 23 '22 16:09

Déjà vu