Password_verify does not return the correct one

Asked

Viewed 2,065 times

2

I’m trying to use the remote password_verify but he is not returning me the correct for example:

$senha = "151201";

$hash = "dc123878c3ceb4b521c7531ecaa93b53";

if(password_verify($senha, $hash)){
    $teste = "Senha correta";
    echo $teste;
} else {
    $teste = "Senha incorreta";
    echo $teste;
}

The variable $hashwas assigned to String: dc123878c3ceb4b521c7531ecaa93b53 that was generated on the site: http://www.md5online.org/md5-encrypt.html despite the string 151201 was dc123878c3ceb4b521c7531ecaa93b53 the command keeps returning me FALSE

  • password_verify only works with password_hash http://php.net/manual/en/function.password-hash.php

2 answers

3

The hash used by the function password_verify not just the MD5 password. Actually, the function is compatible with the function crypt, i.e., the hash to be used should be this:

define("SALT", uniqid()); // Exemplo!

$senha = "151201";

$hash = crypt($senha, SALT);

if (password_verify($senha, $hash)) {
    $teste = "Senha correta";
    echo $teste;
} else {
    $teste = "Senha incorreta";
    echo $teste;
}

See working on Ideone.

Or you can use the function password_hash to generate the hash:

$senha = "151201";

$hash = password_hash($senha, PASSWORD_DEFAULT);

if (password_verify($senha, $hash)) {
    $teste = "Senha correta";
    echo $teste;
} else {
    $teste = "Senha incorreta";
    echo $teste;
}

See working on Ideone.

  • I think using crypt the result is a DES and not a Bcrypt. So much so that it is not adjusting the difficulty, and not resulting in $2$ which is the Bcrypt prefix.

2


The password_hash supports Bcrypt and Argon2i (in PHP 7.2). MD5 has never been assigned to passwords. Moreover since 1994 it could already be considered broken, nowadays it is not recommended for anything, but that is not the issue here.


So that you use the password_verify it is preferable to use a password compatible with Bcrypt (or Argon2i in the case of PHP 7.2), you can use:

  • To Bcrypt:

    password_hash($senha, PASSWORD_BCRYPT);
    
  • To Argon2i:

    password_hash($senha, PASSWORD_ARGON2I);
    

/!\ Care:

The password_hash does not remove the nulls and will stop at them, so this is broken:

// Não utilize o código abaixo em produção, existem erros intencionais:

$_POST['senha'] = "a\x00bc";
// Nota: Existe um nulo após o `a`, isso pode ser enviado usando `%00` pelo usuário!

$hash =  password_hash($_POST['senha'], PASSWORD_BCRYPT);

if(strlen($_POST['senha']) >= 3 && strlen($_POST['senha']) < 70){
    if( password_verify('a', $hash)){
        echo 'Igual';
    }
}

Test this.

Upshot: Igual, yes the a is equal to a\x00bc. >:D


If you don’t want to use Bcrypt/Agon2i all is not lost, you can use the PBKDF2, for example:

$senha = '12345678';
$salt = random_bytes(16);
$iteracoes = 150000;

$hash = hash_pbkdf2('sha3-512', $senha, $salt, $iteracoes);

To check just do hash_equals($senha, $hash). Never do $senha === $hash let alone do $senha == $hash, obviously. It is not considered better than Bcrypt and much less better than Argon2i, some say it is the "worst of the recommended methods", being used "when there is nothing better".

Browser other questions tagged

You are not signed in. Login or sign up in order to post.