I am using php 5.4 with this backwards compatibility script: //github.com/ircmaxell/password_compat/blob/master/lib/password.php
that shouldn't matter though, because I can get the hashing and verification process working in my registration function:
$hash = password_hash[$pass, PASSWORD_DEFAULT];
echo $pass;
echo $hash;
if[ password_verify[$pass,$hash] ]
echo 'success';
else echo 'failure';
//success is always shown
//EXAMPLE INPUT
$pass = 'password';
//EXAMPLE OUTPUT
password$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYSsuccess
but whenever I try to store the hash in a MySQL database and then retrieve it for the verify function, it always fails. Here is my login function:
function user_login[ $mysqli, $email, $pass ]{
$err_msg = 'login: '.$mysqli->error.' | '.$email;
if[ $stmt = $mysqli->prepare['SELECT password FROM users WHERE email=?'] ] :
if[ !$stmt->bind_param['s', $email] ] log_sql_error[ $err_msg ];
if[ !$stmt->execute[] ] log_sql_error[ $err_msg ];
if[ !$stmt->bind_result[ $hash ] ] log_sql_error[ $err_msg ];
if[ $stmt->fetch[] === FALSE ] log_sql_error[ $err_msg ];
if[ !$stmt->close[] ] log_sql_error[ $err_msg ];
//I can see that these values are identical to the ones
//echoed out in the registration function
echo $pass;
echo $hash;
if[ password_verify[$pass,$hash] ]
echo 'success';
else echo 'failure';
else : log_sql_error[ $err_msg ];
endif;
}
//failure is always shown
//EXAMPLE INPUT
$pass = 'password';
//EXAMPLE OUTPUT
password$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYSfailure
My 'password' column has this datatype: VARCHAR[255] NOT NULL
No php errors show up so the only thing I can think of is that the hash value is not formatted in the same way when it comes out of the database as when it went in, but when I echo out the values, they appear to be identical.
How else can I debug this / what is wrong with my code?
Thanks
UPDATE:
This definitely has something to do with encoding:
$hardcode_hash = '$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYS';
echo $hash;
echo '
';
echo $hardcode_hash;
echo '
';
if[ $hash == $hardcode_hash ]
echo 'success';
else echo 'failure';
//OUTPUT
$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYS
$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYS
failure
how do I reformat the SQL value to match the output of password_hash? Here's what I've tried:
[string]$hash
utf8_encode[$hash]
if I do:
$hash = settype[$hash,"string"];
if[$hash == $hardcode_hash]
returns true, but password_verify[$pass, $hash]
still returns false
[PHP 5 >= 5.5.0, PHP 7, PHP 8]
password_verify — Verifies that a password matches a hash
Description
password_verify[string $password
, string $hash
]: bool
Note that password_hash[] returns the algorithm, cost and salt as part of the returned hash. Therefore, all information that's needed to verify the hash is included in it. This allows the verify function to verify the hash without needing separate storage for the salt or algorithm information.
This function is safe against timing attacks.
Parameters
password
The user's password.
hash
A hash created by password_hash[].
Return Values
Returns true
if the password and hash match, or false
otherwise.
Examples
Example #1 password_verify[] example
The above example will output:
See Also
- password_hash[] - Creates a password hash
- » userland implementation
- sodium_crypto_pwhash_str_verify[] - Verifies that a password matches a hash