1

I am using password_hash to store passwords in a MySQL database field of type VARCHAR(255). When I try to login the user and verify credentials, the password_verify function always returns false.

Here is the code excerpt that stores the password in the MySQL database:

$password_hash = password_hash($password, PASSWORD_DEFAULT);

// Generate API Key
$api_key = $this->generateApiKey();

// Insert Query
$stmt = $this->conn->prepare("INSERT INTO user(email, password, name, api_key, status) values(?, ?, ?, ?, 1)");
$stmt->bind_param("ssss", $email, $password_hash, $name, $api_key);
$result = $stmt->execute();
$stmt->close();

And the piece of code that checks the password:

// Query user by email
$stmt = $this->conn->prepare("SELECT password FROM user WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();

$stmt->bind_result($password_hash);
$stmt->store_result();

if ($stmt->num_rows > 0) {
    // Found user with that email address
    // Now verify the password

    $stmt->fetch();
    $stmt->close();

    if (password_verify($password, $password_hash)) {
        // User password is correct
        return TRUE;

Then I wrote this test code and grabbed the data straight from the MySQL field and it still fails. When I create the password_hash in the same file ($hash2 in the file below) - then the password verifies correctly.

$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';
$hash2 = password_hash($password, PASSWORD_DEFAULT);

echo $hash . " - " . strlen($hash);
echo "<br />";
echo $hash2 . " - " . strlen($hash2);
echo "<br />";

if (password_verify($password, $hash)) {
    echo "Password Valid!";
} else {
    echo "Password invalid!";
}

echo "<br /><br />";

if (password_verify($password, $hash2)) {
    echo "Password 2 Valid!";
} else {
    echo "Password 2 invalid!";
}
mattdonders
  • 1,328
  • 1
  • 19
  • 42
  • are you sure this is the right hash? – Leandro Papasidero Feb 23 '15 at 03:51
  • I grabbed the field straight from the database, although I did notice that every time I refresh my test page the $hash2 variable changes, but I am not 100% sure how crypt works to fully understand why. – mattdonders Feb 23 '15 at 03:53
  • Check your MySQL Character encoding; check your database encoding, check your table encoding and check your column encoding and collation. MySQL [should be using UTF8mb4_ character sets and collations](https://stackoverflow.com/questions/279170/utf-8-all-the-way-through). – Martin Mar 11 '20 at 14:32
  • Also; for note; cost = 10 is FAR TOO LOW. Your cost value should be as high as practically possible for your server; typically 14+ – Martin Mar 11 '20 at 14:33

4 Answers4

1

This proves that something is wrong with your hash

<?php
// See the password_hash() example to see where this came from.
$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';

$hash2 = '$2y$10$gMJKYZUc1FKSZBnsONxLOebOHj.uuEWSiCP0jo4Zv0iAHBz6iz.NG';

if (password_verify('pass1234567890', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

echo "<br>";

if (password_verify('pass1234567890', $hash2)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

Screenshotenter image description here

Leandro Papasidero
  • 3,728
  • 1
  • 18
  • 33
  • Understood, but `password_verify` should be able to verify any of the hashes made from that password correct? – mattdonders Feb 23 '15 at 04:00
  • @mattdonders I thing something is wrong with that hash. I created a new hash and my works perfectly. Try to update the record with my hash (if my example wors for you) and let me know if you get something else. – Leandro Papasidero Feb 23 '15 at 04:07
  • But what could be wrong? Hashes are the same length, I'm doing an INSERT into a VARCHAR(255) using `bind_param()` as well. The $hash in that test file is literally straight from thr database. – mattdonders Feb 23 '15 at 04:08
  • So you're saying, delete the user manually, recreate them and try this again? – mattdonders Feb 23 '15 at 04:09
  • it can be that it was and extra character when you set the password? space or can be many other things – Leandro Papasidero Feb 23 '15 at 04:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/71455/discussion-between-lea-tano-and-mattdonders). – Leandro Papasidero Feb 23 '15 at 04:10
0

In my case the probme was that I stored the database connection query in another file which included the same variable that I used for fetching current password, so what happened was that first I assigned a variable "password" to current password and then included my connection query file which had the same variable "password" therefore what happened was that, "password" variable of signup form was reassigned by "password" variable of connection query, and that's why it actually hashed another password. So by changing the variable name this problem was solved.

Here is my code for reference,

signup.php

    $email = $_POST["email"];
    $password = $_POST["password"];
    
    include 'partials/php/_dbconnect.php';
    $passwordHash = password_hash($passwd, PASSWORD_DEFAULT);

_dbconnect.php

<?php
$server = "localhost";
$username = "root";
$password = "";
$database = "demo";

$connectionquery = mysqli_connect($server, $username, $password, $database);
?>

which I changed to;

    $email = $_POST["email"];
    $passwd = $_POST["password"];
    
    include 'partials/php/_dbconnect.php';
    $passwordHash = password_hash($passwd, PASSWORD_DEFAULT);
0
password_verify($password,trim($password_hash)))

While I am unsure if it happened when the hash was stored or during retrieval, the password_hash had a space at the end. Trimming the hash before feeding it to password_verify fixed the issue for me.

Thennan
  • 788
  • 5
  • 13
-1

Just make a variable for if(password_verify($pass_input, $pass_db)) where $pass_input is the value given from the textified form and $pass_db is the value stored in mysql (hashed)

Like this:

$verif_pass = (password_verify($pass_input, $pass_db));
if($verif_pass){echo "TRUE"} else {echo "FALSE";}

and just modify TRUE/FALSE as you want.

  • Can you explain that further? Why should adding a new variable solve the problem? – Nico Haase Mar 11 '20 at 14:31
  • Not sure... maybe password_verify return a boolen value TRUE if match and FALSE if failed. But the script working properly. – Suhardi HP Mar 11 '20 at 14:44
  • Im just tried without make a variable for it and working, the script like this .. if(password_verify($pass_input, $pass_db) === TRUE ){echo "TRUE";} else {echo "FALSE";} – Suhardi HP Mar 11 '20 at 15:35
  • What **exactly** does that change, compared to the given code? Does it only print something else? Or do you think the additional check `=== TRUE` makes a difference? Please edit your answer to contain all such information - keep in mind that others should be able to learn from it – Nico Haase Mar 11 '20 at 15:37
  • **Please edit your answer to contain all information** - the given answer does not contain `password_hash` after all – Nico Haase Mar 11 '20 at 15:44