I am using php 5.4 with this backwards compatibility script: https://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 '<br/>';
echo $hardcode_hash;
echo '<br/>';
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
Found the problem. when I did this:
echo strlen($hash)
it printed 90, which is strange because there were definitely no spaces at the end when I printed out the success/failure message, and the field has a varchar length of 255
I added this line:
$hash = substr( $hash, 0, 60 );
And now it works fine.
Its strange that no one else seems to have run into this issue. There are similar posts about password_verify, but none of them required this type of conversion, or any conversion for that matter:
php password_verify not working
password_verify php not match
http://forums.phpfreaks.com/topic/283407-need-help-with-password-verify/
Using PHP 5.5's password_hash and password_verify function
One thing that bothers me is this prevents the code from being forward compatible. How will I know that the hash is 60 characters long when the default changes?
I was having the same issue with password_verify(). For me i had declared my username and password as VARCHAR(50). Therefore it was not inserting the hash value in my database which is obviously more than 50 characters. Therefore every time I used password_verify() I got a false. I changed my database values to varchar(255). Inserted data again, tested and it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With