Will Sayin Will Sayin - 14 days ago 5
MySQL Question

php password_hash and password_verify looked all over still doesn't work

UPDATE
So this is an embarrassingly stupid admission, but the issue was that the hash I had stored in the database was a hash of 'password' including the quotes, there was no issue with the queries I wrote, the issue was between the chair and the keyboard.

So this is an often asked question, and I've looked all over stackoverflow and google trying to find out the answer, and have so fare been unsuccessful.

I have a table of "agents" with logins and password assigned to each agent. The password field is a varchar with a length of 255.

Here is my php code:

$conn = new mysqli( "localhost", "VABEN", "**********", "VABen" );
if( $conn->connect_error )
{
die( "Connection failed!" . $conn->connect_error );
}
$username = $_POST["username"];
$password = $_POST["password"];

$s = $conn->prepare( "SELECT `agent_password` FROM `VABen`.`agents` WHERE `agent_login`=?" );
$s->bind_param( "s", $username );
$s->execute();

$hash = $s->get_result();
$hash = $hash->fetch_array( MYSQLI_ASSOC );

$testpw = password_hash( 'password', PASSWORD_DEFAULT );
echo "Comparing submitted password to locally created hash $testpw which has a length of " . strlen($testpw) . "<br>";
if( password_verify( $password, $testpw ) )
{
echo "Password '$password' matches with hash $testpw<br>";
}
else
{
echo "Password '$password' does not match with hash $testpw<br>";
}
echo "<br>";

echo "Supplied Password: '$password'<br>";
echo "Queried Hash: " . $hash['agent_password'] . " which has a length of " . strlen( $hash['agent_password'] ) . "<br>";
echo "Result of password_verify: ";
if( password_verify( $password, $hash['agent_password'] ) )
echo "true<br>";
else
echo "false<br>";


I am at a loss. It only seems to work when I supply a locally created copy of password_hash, and if I then use that locally created copy in the MySQL database, it fails.

Any ideas?

Answer

Store the hash

Have you checked that agent_password is storing a hash generated by:

password_hash( $password, PASSWORD_DEFAULT );

Check PDO standards

Probably has no effect, but it is worth following standards for the differnt implementations of bindParam. If you're using the ? method, then:

 $s->bind_param( 1, $username );

There are several odd implementations of PDO in your script, try adjusting:

 $s->execute();

 //$hash = $s->get_result();
 //$hash = $hash->fetch_array( MYSQLI_ASSOC );
 $hash = $s->fetchColumn();

Change subsequent calls of $hash['agent_password'] to just $hash instead.

Test Basic Operation

Test the folowing:

// $password = $_POST["password"];
$password = "password";

Then, also try storing that hash, and retrieving it again, from mysql, prior to the final verify step.

Finally

I deeply suspect that what is stored in agent_password is not in fact a password hashed with password_hash.