-->

PHP password_verify not working against database

2020-03-31 06:59发布

问题:

I'm trying to me a page more secure and I started with the password encrypting part of it. I'm trying to implement password_hash + password verify, but so far I've been unsuccessful to make the whole thing work. So, here it is in my login area:

$username = mysqli_real_escape_string($connection, $_POST['username']);

$password = mysqli_real_escape_string($connection, $_POST['password']);

$query = "SELECT username, password FROM `users` WHERE username='$username' and user_enabled='1'";
$result = mysqli_query($connection, $query) or die(mysqli_error($connection));
if($row = mysqli_fetch_assoc($result)) { $dbpassword = $row['password']; }

if(password_verify($password, $dbpassword)) {
    echo "Successful login";
}else{
    echo "Invalid Login Credentials.";
}

I always get Invalid Login Credentials.

When I modify the new password for the user, I am doing the following:

$pass = mysqli_real_escape_string($connection, $_POST['password']);
$options = [ 'cost' => 10,
             'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
           ];
$password = password_hash($pass,  PASSWORD_BCRYPT, $options)."\n";

$query = "UPDATE users 
          SET `password` = '".$password."'
          WHERE id = ".$_POST['user_id']."
          ";

$result = mysqli_query($connection, $query) or die(mysqli_error($connection));

password in database is VARCHAR(255), and it is storing something like:

$2y$10$Y5HIyAsLMfkXIFSJONPsfO3Gxx3b46H.8/WFdLVH3Fqk2XNfy2Uaq

What am I doing wrong here?

回答1:

The \n in the following line, is embedding a linebreak, (Edit: one that cannot be included in the user inputted password).

$password = password_hash($pass,  PASSWORD_BCRYPT, $options)."\n";

and you need to delete it and start over with a new hash.

Jay Blanchard, a member here on Stack submitted a note about it not too long also in the password_hash() manual, which is something that he and I actually talked about.

Be care when using the example from the documentation which concatenates a newline character \n to the end of the hash, i.e.:

echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";

People are storing the hash with the concatenated newline and consequently password_verify() will fail.

Another option would be to use trim(); that also works (at the moment of hashing).

$password = password_hash($pass,  PASSWORD_BCRYPT, $options)."\n";
$password = trim($password);
// Store in db after

Yet you still need to start over by clearing the old hash(es) and creating new ones.

Do keep in mind though, that you shouldn't escape passwords.

One such as 123'\abc (being perfectly valid) will be modified to 123\'\abc by real_escape_string(); it's not needed. password_verify() takes care of that, security-wise.