Why Does Password_Verify Return False

Why does password_verify return false?

There are a variety of reasons why password_verify could be returning false, it can range from the setup of your table to the actual comparing of the password, below are the common causes of it failing.

Column Setup

  • The length of the password column in your table is too short:

    • If you are using PASSWORD_DEFAULT then it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice).
    • If you are using PASSWORD_BCRYPT then it is recommended to store the result in a database column that is 60 characters because PASSWORD_BCRYPT will always result in a 60 character string or FALSE on failure.

Password Sanitization

Another common cause is when developers try to "clean" the user's password to prevent it from being malicious, as a result, this causes the input to be different to what is being stored in the table. It is not even necessary to escape the input, you should use prepared statements instead. You shouldn't even trim the passwords as that could change that which was originally provided.

Password Verification

When using password_verify you need to compare the plaintext password with the hash from the database/file/some-other-storage-method, not compare hashes (the implication here being that you need to have stored the hashed password of the user when they register):

<?php

$hashed = password_hash('test', PASSWORD_DEFAULT);
$password = 'test';

if (password_verify($password, $hashed)) {
echo 'success';
} else {
echo 'fail';
}

?>

Ensure that you are actually passing a hash to password_verify and not something else by dumping it.

Repl

Hardcoded Passwords

In the instance that you are using a hardcoded hash and you are facing issues, ensure that you are using single quotes instead of double quotes when storing the value in the variable as the $ will be interpreted in when using double quotes:

<?php
// Undefined variable: QHpfI0MfQWjvsVQWRdFHSOX6WqG8LSf0iFGiKs0Fz0RvqhpFOpAKu :1
$incorrect = "$2y$10$QHpfI0MfQWjvsVQWRdFHSOX6WqG8LSf0iFGiKs0Fz0RvqhpFOpAKu";

$correct = '$2y$10$QHpfI0MfQWjvsVQWRdFHSOX6WqG8LSf0iFGiKs0Fz0RvqhpFOpAKu';
?>

Repl - Comment out respectively.

Troubleshooting

var_dump() the hashed password on registration right before you insert it into your database, and var_dump() it again after you fetch it from your database when you are about to password_verify() it. Ensure both hashes are identical. If they are, and the plaintext passwords are identical too, there's no reason for password_verify to fail. It only fails if the hash gets modified in some way on its roundtrip through the database, or if the plaintext passwords aren't identical.

Ensure that you are passing a correct algorithm to password_hash has the second parameter.

Addendum

As per the documentation:

Caution It is strongly recommended that you do not generate your own salt for this function. It will create a secure salt automatically for you if you do not specify one.

As noted above, providing the salt option in PHP 7.0 will generate a deprecation warning. Support for providing a salt manually may be removed in a future PHP release.

PHP password_verify always returning false even when hardcoded

I could not find any problem in your code here but since hashing and verifying is a process which depends on a lot of factors to be successful i would like to give you some tips so that you can check it yourself for any potential problems.

  1. make sure you are not escaping/sanityzing the password before
    hashing it. This way you're altering the stored password. Let

    $password = $_POST['password'];

both when you create the account and
when you check if the password match at login.


  1. make sure you are enclosing the hash variable in single quotes (') and not double quotes (").using double quotes makes PHP read each paired character with "$" as indivisual variables which will probably cause your code to break, USE SINGLE QUOTES INSTEAD.

  2. Ensure the Password field in the database (that stores the hashed
    password) is able to store up to 255 characters. From the documentation
    it is recommended to store the result in a database column that can
    expand beyond 60 characters (255 characters would be a good choice). If the field is narrower the hash will be truncated and you'll never
    have a match.

  3. As you get the user by username at login ensure that username is unique
    as long as it is your primary key (in the table
    definition). Good idea to check this also upon user registration and login (at php level).

  4. echo both hash and entered
    values and make sure they match the ones that were inserted and
    generated during password_hash() if the database value was different
    (the hash), make sure the type of its column is varchar(256), the
    hash is usually 60 characters long but the hashing function is
    frequently improved so that length may expand in the future.

  5. if the entered value was different (the user password), make sure the
    filtering isn't corrupting the password value.

  6. also check if another variable has the same name as the one you're storing the password in.

  7. If password_verify($password, password_hash($password, PASSWORD_DEFAULT))
    "works", then the problem is that $row['Password'] does not contain what is expected - including not being generated correctly.

  8. If it "doesn't work" then
    another line is causing the observed behavior. Both of these
    outcomes allow focusing on a refined problem set.

  9. try changing the password from the another column that matched and copy it to your password column and enter that password to check.if it worked then there is problem with your stored password

  10. try copying this hash to your password column

    $2y$10$uDnEpQpkh9RO5tWwOrHtneLAuYMRDstRaKGZFyHubObDR0789OMO6

this is the hashed password for 123456 using bycrypt. select this password and try to verify it with password_verify(123456,$yourhashedfromdatabase) after selecting this from sql if it works then there is probably some manipulation after your data is entered and goes to the database. it it does not then check if the password that reaches the database is exactly as your typed by echoing it.

UPDATE: after you updated your code i see that while entering the password you use "Pass" column but while extracting you use "Password" column. this could be the issue

password_verify not returning true/false

After testing your entire code, I have come to the following conclusion.

The problem here is that you are escaping the password while inserting it into your database, which is something I did raise in comments from the beginning.

"side note: you shouldn't escape a password/hash function, passwords such as 123'\abc< are perfectly valid and will be modified on insertion."

$password = mysqli_real_escape_string($conn, $username);

Side note for ^ - Consult Edit #2 below, near "However...":

Simply don't use it, just keep/use the assignment normally.

Both password_hash() and password_verify() do their job, so there's no need to escape passwords.

You will need to remove it from the code that you used to insert it into the database with, and start over again with a new set of hashes.

That escaping function is most likely adding a character during insertion.

Side note: Just for the record, my password column is VARCHAR, yet that shoulnd't be a difference from your CHAR (Edit: consult footnote). If it is then ALTER your column to be VARCHAR.

The manual on password_hash() though, suggests using 255 for a length, being a good bet.

  • http://php.net/manual/en/function.password-hash.php

Edit footnote:

As per a comment I posted beneath my answer.

It looks to have a difference. This Q&A What's the difference between VARCHAR and CHAR? shows it, as per the accepted answer

VARCHAR is variable-length.

CHAR is fixed length.

  • https://stackoverflow.com/a/1885635/1415724

Edit #2:

After further testing to see if it made a difference by ALTER'ing the password column from VARCHAR(255) to CHAR(60) made a difference; it did not.

Tests performed:

  • Inserted a new hash without the escaping function and verifying: TRUE.
  • Inserted a new hash with the escaping function and verifying: FALSE.

Therefore and as I stated originally; the fault lies with the use of mysqli_real_escape_string().

However and going over your code again, this line:

$password = mysqli_real_escape_string($conn, $username);

You were using the $username variable here which also accounts for the wrong value being inserted in the database. All of these put together were the problems from the get go.

Why is password_verify returning false?

Probably the problem is with your column length, from the manual:
it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice). link

PHP password_verify returning false

You overwrite your $password when you include your dbconnection.

include('connection.php');

has:

$password="mypassword";

Previously you set:

$password=validateFormData($_POST['password']);

so your hashed password is not the user's password, but your DB password.

I would prefix all DB credentials variables with db_. So your database password variable would then be $db_password. This will allow you to have distinct variables throughout your project (I'd think).

Additionally you should be using $formPass, not $newpass. The $newpass is going to be double hashed at the verify function.

$formEmail=validateFormData($_POST['loginEmail']);
$formPass=validateFormData($_POST['loginPassword']);
$newPass=password_hash($formPass,PASSWORD_DEFAULT);

so change:

if(password_verify($newPass,$LogPass))

to:

if(password_verify($formPass, $LogPass))

password_verify() returning false when passwords match

password_verify() works with the function password_hash();

change:

$hash = hash('sha512', $password);

to:

$hash = password_hash($password, PASSWORD_DEFAULT);


Related Topics



Leave a reply



Submit