1

I have created a password using password_hash like so:

$password = password_hash('password123', PASSWORD_DEFAULT);

This is stored in a MySQL database in a column with varchar(60).

In my login form, I use:

if(password_verify($password, $foundUser->Password){ /*login*/ }

where $password is the plaintext input from the login form and $foundUser->Password is the hash that is stored in the database, but the password_verify() function is always returning false.

I have checked my inputs using the following code:

echo "Password: {$password} <br>"; echo "Found password: ".$foundUser->Password."<br>";

which outputs:

Password: password123 Found password: $2y$10$8.ICQHCyCPzS.xygPO4cfuHsHZb6Kuxynn8/uUHOU1.7gY.UhSIXa

so I am reasonably confident I'm typing the right password in and getting the right hash from my database.

I have looked at the links in this question for answers but haven't made it work yet. Does anyone have any ideas why password_verify() is returning false?

Narf
  • 14,600
  • 3
  • 37
  • 66
monkeyman
  • 135
  • 1
  • 4
  • 14
  • 1
    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)." – Álvaro González Feb 01 '17 at 11:41
  • 1
    **Note that `PASSWORD_DEFAULT` is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice).** – Just for starters… Have you checked that the value you get from your database is exactly the same as the one produced by `password_hash`…? – deceze Feb 01 '17 at 11:43
  • ... currently though `PASSWORD_DEFAULT` uses BCrypt though doesn't it, so it *should* always be a 60 character string. – CD001 Feb 01 '17 at 11:54
  • @Alvaro Gonzalez and @deceze I just tested this by generating a new hash using `password_hash()` and copy pasted it straight into the database as plaintext. When I echo it out it prints exactly the same code that the `password_hash()` generated. – monkeyman Feb 01 '17 at 11:56
  • Tested it on my server with your input `password_verify('password123', '$2y$10$8.ICQHCyCPzS.xygPO4cfuHsHZb6Kuxynn8/uUHOU1.7gY.UhSIXa')` => it returned true. So your code seems to be ok. What PHP version do you use to verify the password? – martinstoeckli Feb 01 '17 at 11:58
  • @martinstoeckli I'm using Version 5.6.28 – monkeyman Feb 01 '17 at 11:59
  • Strange way to test hash length... What does `var_dump($password)` print? Have you configured MySQL to reject data truncation? – Álvaro González Feb 01 '17 at 12:01
  • How do you check the return value, do you have a debugger? Is it possible that the problem lies inside the if statement, maybe you are redirecting without an exit? – martinstoeckli Feb 01 '17 at 12:03
  • @ÁlvaroGonzález `var_dump($password)` outputs `string(11) "password123"` – monkeyman Feb 01 '17 at 12:03
  • 2
    The little code you've shown has a syntax error, so surely you've stripped a lot of it down ... I'm guessing the problem is in the pieces you haven't shown. – Narf Feb 01 '17 at 12:06
  • What? `$password = password_hash('password123', PASSWORD_DEFAULT);` produces an 11 char unhashed string? – Álvaro González Feb 01 '17 at 12:11

4 Answers4

1

set database column value more than 60 because encrypted password characters may be more than 100. And $password = password_hash('password123', PASSWORD_DEFAULT); this function return encrypted password that may change every time.

1

I face the same problem like yours and I finally found that trim() will do the magic.

$userpasswd = trim($_POST['user_input_pw']);

Fetch from table:

$savedhash = trim($row['row_header']);

Password verify BCRYPT PHP:

if(password_verify($userpasswd, $savedhash)){

  /* Do something */

} else {

  /* Do nothing */

}

Hope it helps.

Alpha
  • 1,413
  • 3
  • 9
  • 23
0

There is a Caution in php manual for password_hash() function :Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being truncated to a maximum length of 72 characters. please read this http://php.net/manual/en/function.password-hash.php

maybe you need to change that mysql column from varchar(60) to varchar(73) or bigger. you can use type text also.

M. K Hossain
  • 807
  • 1
  • 12
  • 28
  • 1
    The password_hash() function will truncate the password on 72 characters, but will work without problems. The hash will still be 60 characters for a BCrypt hash (`'$2y$10$...`). – martinstoeckli Feb 01 '17 at 12:07
0

Solved my own problem guys. As per @martinstoeckli and @Narf suggestions I changed the way I was debugging it and found that the problem wasn't with password_verify() but with the way I was handling the output. Sorry for the run around and thanks for all your help.

monkeyman
  • 135
  • 1
  • 4
  • 14