Search code examples
phpencryptionpasswordspassword-hashphp-password-hash

PHP password_hash Check Two Hashes


If I have a two password hashes created using password_hash function, how can I tell if they came from the same base password? I know it uses a different salt each time. I do not have the plain text.

For instance: $2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re and $2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO both came from hashing test. How can I write a function that will return true if given these two hashes as parameters?

Is this possible?

So:

<?php
function check_hashes($hash1, $hash2) {
(some code)
}
echo strval(check_hashes('$2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re', '$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO'));
echo strval(check_hashes('$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO', '$2y$10$LoUOu3kt7zm1YZI1PtAsD.yzWF0b9jqOaAH64lK51VtgqRJZBgtO6'));
?>

Would output:

TRUE
FALSE

Solution

  • No, you can not check if the two hashes belong to the same password, unless you already know the password. If you could, this basically fails the purpose of using the password_hash function.

    If you know the password, you can simply, use the method: password_verify to verify your passwords:

    $res1 = "$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO";
    $res2 = "$2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re";
    var_dump(password_verify("test", $res1)); // returns true
    var_dump(password_verify("test", $res2)); // returns true
    

    So, as you can see, both the hashes will give you true with password_verify() method, and therefore, you do not need to check if the two hashes belong to the same password or not. And, if you do, the above logic can be used to construct a function like this:

    function belongs_to_password() {
      $args = func_get_args();
      $str  = array_shift($args);
      foreach ($args as $hash) {
        if (!password_verify($str, $hash)) return false;
      }
      return true;
    }
    

    The above function can be used to check whether the hashes passed to this function are all for the same password or not. And, can be used like this:

    $res1 = "$2y$10$ZSlQNIbsLWfj7JLCSkvFLeS/adH.KnGZTgA1BcvyPXl7BEn7GhREO";
    $res2 = "$2y$10$M6CnjqaxuUKNhg84T8NpLeylkUrvP1pzoZNhBWfpSzP2zJneuS1re";
    var_dump(belong_to_password("test", $res1, $res2)); // returns true