Tormy Van Cool
Tormy Van Cool

Reputation: 801

password_verify() against MySQL doesn't work

I store the password, get through a form, into MySQL database via PDO, after having hashed it with password_hash() (VARCHAR(512) field)

$options = array(
    'cost' => 12
);
$password = password_hash($password, PASSWORD_BCRYPT, $options);

Suppose that

$pass = "123Azerty";
//and the hash is
$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";

When I get the password from the database and I verify it with password_verify() it returns always false

...
...
$returnedPWD = $row['password'];
if (password_verify($pass,$returnedPWD)){
    echo "TRUE";
} else {
    echo "FALSE";
}
...
...

At this point, I tried to do it "manually" in this way

$pass = "123Azerty";
$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";
if (password_verify($pass,$hash )){
    echo "TRUE";
} else {
    echo "FALSE";
}

And it always returned FALSE

BUT

when I changed

$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";
// into
$hash = '$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe';

it worked. Because the hash enclosed in single quotes, is not parsable. On my understanding, it means that the hash taken from database, it is interpreted as parsable (double totes) than it doesn't work at all

then I tried to enclose the string out the db int strval():

...
...
$returnedPWD = strval($row['password']);
if (password_verify($pass,$returnedPWD)){
    echo "TRUE";
} else {
    echo "FALSE";
}
...
...

But it returns always FALSE reading all the posts related the not functioning of password_verify(), I didn't come up to any valid solution, for me.

Please is there a way to make it work?

Thanks in advance

EDIT 1

I did try with other settings as PASSWORD_DEFAULT but no changes. I also tried to base64 encode it upfront database storage, then decode it. But nothing changed

EDIT 2

I store the data using PDO with parameters

 $query = "INSERT INTO `users` (username, password) VALUES (:username, :password)";

 $params = array(
            ':username' => "$username",
            ':password' => "$password" // hashed one
        );

EDIT 3

Table Structure

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(512) NOT NULL,
  `enabled` int(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=13 ;


$username = trim($_POST["username"];
$password = trim($_POST["password"];

// Query to insert data
 $query = "INSERT INTO `users` (username, password, enabled) VALUES (:username, :password, 1)";

// The very original setup I did use and didn't work out
$param_password = password_hash($password, PASSWORD_DEFAULT); 

// Bind parameters
$params = array(
     ':username' => "$username",
     ':password' => "$param_password"
);
...
...
// insert into db
$sth = $sql->prepare($query);

// Call MySQL
try {
    $sth->execute($params); // Execute the Query
} catch (PDOException $e) {
    $mysql_error = 'MySQL connection failed: ' . "<br>" . $e->getMessage();
}
...
...

and here the fundamental lines on how I read from database

...
...
$username_login = trim($_POST["username"]);
$password_login = trim($_POST["password"]);
...
...   
$query = "SELECT * FROM `users` WHERE username = :username";
$params = array(
    ':username' => $username_login
);   

$sth = $sql->prepare($query);

try{
    $sth->execute($params);
} catch (PDOException $e)  {
    $mysql_error = 'MySQL connection failed: ' . "<br>" . $e->getMessage();
}

while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
    foreach ($row as $key => $value) {
        global $$key;
        $$key = $value;
    }
}
...
...

if (password_verify($password_login, $password) and $enabled == 1){
    // Password is correct, so start a new session
    session_start();

    // Store data in session variables
    $_SESSION["logged"] = true;
    $_SESSION["id"] = $id;
    $_SESSION["uname"] = $username_login_;                            

    // Redirect user to welcome page
    header("location: index.php");

} else {
    // Display an error message if password is not valid
    $password_login__err = "The password you entered was not valid. Or you are not enabled";
}
...
...

Upvotes: 0

Views: 351

Answers (1)

Justinas
Justinas

Reputation: 43481

Your code does not work because of "$password " - it has space at the end. It should be:

$query = "INSERT INTO `users` (username, password) VALUES (:username, :password)";

$params = array(
        ':username' => $username,
        ':password' => $password, // hashed one
    );

Your manual test does not work because

$hash = "$2y$12$TzpGzy1cKM81pkEr/Mn0SOVA4wn0lr.7PnKFg4SU9Hto0EUiGGRMe";

has double quotes and it interpolates $2y, $12 and $Tz... as variables that leads to empty string. That's why single quotes works.


From your provided information I constructed sample code that does work: Check here

Upvotes: 3

Related Questions