PHP password_verify returning false
You overwrite your $password
when you include your dbconnection.
include('connection.php');
has:
$password="mypassword";
Previously you set:
$password=validateFormData($_POST['password']);
so your hashed password is not the user's password, but your DB password.
I would prefix all DB credentials variables with db_
. So your database password variable would then be $db_password
. This will allow you to have distinct variables throughout your project (I'd think).
Additionally you should be using $formPass
, not $newpass
. The $newpass
is going to be double hashed at the verify
function.
$formEmail=validateFormData($_POST['loginEmail']);
$formPass=validateFormData($_POST['loginPassword']);
$newPass=password_hash($formPass,PASSWORD_DEFAULT);
so change:
if(password_verify($newPass,$LogPass))
to:
if(password_verify($formPass, $LogPass))
Why does password_verify return false?
There are a variety of reasons why password_verify
could be returning false, it can range from the setup of your table to the actual comparing of the password, below are the common causes of it failing.
Column Setup
The length of the password column in your table is too short:
- If you are using
PASSWORD_DEFAULT
then it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice). - If you are using
PASSWORD_BCRYPT
then it is recommended to store the result in a database column that is 60 characters becausePASSWORD_BCRYPT
will always result in a 60 character string or FALSE on failure.
- If you are using
Password Sanitization
Another common cause is when developers try to "clean" the user's password to prevent it from being malicious, as a result, this causes the input to be different to what is being stored in the table. It is not even necessary to escape the input, you should use prepared statements instead. You shouldn't even trim
the passwords as that could change that which was originally provided.
Password Verification
When using password_verify
you need to compare the plaintext password with the hash from the database/file/some-other-storage-method, not compare hashes (the implication here being that you need to have stored the hashed password of the user when they register):
<?php
$hashed = password_hash('test', PASSWORD_DEFAULT);
$password = 'test';
if (password_verify($password, $hashed)) {
echo 'success';
} else {
echo 'fail';
}
?>
Ensure that you are actually passing a hash to password_verify
and not something else by dumping it.
Repl
Hardcoded Passwords
In the instance that you are using a hardcoded hash and you are facing issues, ensure that you are using single quotes instead of double quotes when storing the value in the variable as the $
will be interpreted in when using double quotes:
<?php
// Undefined variable: QHpfI0MfQWjvsVQWRdFHSOX6WqG8LSf0iFGiKs0Fz0RvqhpFOpAKu :1
$incorrect = "$2y$10$QHpfI0MfQWjvsVQWRdFHSOX6WqG8LSf0iFGiKs0Fz0RvqhpFOpAKu";
$correct = '$2y$10$QHpfI0MfQWjvsVQWRdFHSOX6WqG8LSf0iFGiKs0Fz0RvqhpFOpAKu';
?>
Repl - Comment out respectively.
Troubleshooting
var_dump()
the hashed password on registration right before you insert it into your database, and var_dump()
it again after you fetch it from your database when you are about to password_verify()
it. Ensure both hashes are identical. If they are, and the plaintext passwords are identical too, there's no reason for password_verify
to fail. It only fails if the hash gets modified in some way on its roundtrip through the database, or if the plaintext passwords aren't identical.
Ensure that you are passing a correct algorithm to password_hash
has the second parameter.
Addendum
As per the documentation:
Caution It is strongly recommended that you do not generate your own salt for this function. It will create a secure salt automatically for you if you do not specify one.
As noted above, providing the salt option in PHP 7.0 will generate a deprecation warning. Support for providing a salt manually may be removed in a future PHP release.
PHP password_verify always returning false even when hardcoded
I could not find any problem in your code here but since hashing and verifying is a process which depends on a lot of factors to be successful i would like to give you some tips so that you can check it yourself for any potential problems.
make sure you are not escaping/sanityzing the password before
hashing it. This way you're altering the stored password. Let$password = $_POST['password'];
both when you create the account and
when you check if the password match at login.
make sure you are enclosing the hash variable in single quotes (') and not double quotes (").using double quotes makes PHP read each paired character with "$" as indivisual variables which will probably cause your code to break, USE SINGLE QUOTES INSTEAD.
Ensure the Password field in the database (that stores the hashed
password) is able to store up to 255 characters. From the documentation
it is recommended to store the result in a database column that can
expand beyond 60 characters (255 characters would be a good choice). If the field is narrower the hash will be truncated and you'll never
have a match.As you get the user by username at login ensure that username is unique
as long as it is your primary key (in the table
definition). Good idea to check this also upon user registration and login (at php level).echo both hash and entered
values and make sure they match the ones that were inserted and
generated during password_hash() if the database value was different
(the hash), make sure the type of its column is varchar(256), the
hash is usually 60 characters long but the hashing function is
frequently improved so that length may expand in the future.if the entered value was different (the user password), make sure the
filtering isn't corrupting the password value.also check if another variable has the same name as the one you're storing the password in.
If
password_verify($password, password_hash($password, PASSWORD_DEFAULT))
"works", then the problem is that $row['Password'] does not contain what is expected - including not being generated correctly.If it "doesn't work" then
another line is causing the observed behavior. Both of these
outcomes allow focusing on a refined problem set.try changing the password from the another column that matched and copy it to your password column and enter that password to check.if it worked then there is problem with your stored password
try copying this hash to your password column
$2y$10$uDnEpQpkh9RO5tWwOrHtneLAuYMRDstRaKGZFyHubObDR0789OMO6
this is the hashed password for 123456 using bycrypt. select this password and try to verify it with password_verify(123456,$yourhashedfromdatabase) after selecting this from sql if it works then there is probably some manipulation after your data is entered and goes to the database. it it does not then check if the password that reaches the database is exactly as your typed by echoing it.
UPDATE: after you updated your code i see that while entering the password you use "Pass" column but while extracting you use "Password" column. this could be the issue
password_verify() returning false when passwords match
password_verify() works with the function password_hash();
change:
$hash = hash('sha512', $password);
to:
$hash = password_hash($password, PASSWORD_DEFAULT);
Why my password hash is returning false when i provide the correct password?
Messing with input is dangerous, you may be effecting the content of
userid
by using strip_tags and its unnecessary anyway if you use prepared queries.using
var_dump()
in this lineif(var_dump(password_verify($password, $hash_password))){
will cause a false all the time asvar_dump()
returns NULL.It is also a good idea to add some error checking to the
sqlsrv_
calls.
So suggested code amendments
if(isset($_POST['login'])) {
//$username = strip_tags(trim($_POST["username"]));
//$password = $_POST["password"];
$query = "SELECT * FROM USERNAME WHERE user_id= ?";
$params = array($_POST["username"]);
$stmt = sqlsrv_prepare($conn, $query, $params);
if( !$stmt ) {
print_r( sqlsrv_errors(), true);
exit;
}
if( sqlsrv_execute( $stmt ) === false ) {
print_r( sqlsrv_errors(), true);
exit;
}
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
//$hash_password = $row['password'];
//$new = password_verify($password, $hash_password);
//if(password_verify($password, $hash_password)){
if(password_verify($_POST["username"], $row['password']))){
$msg = "Login Success";
}else{
$msg = "Login failure";
}
echo $msg;
}
Of course the other thing to check is that the hashing of the password worked correctly, ass if that failed you will never get the verify to work.
password_verify Always Returns False, even with proper variables used
You are escaping your password, as a result this changes the password from what it was. Instead of relying on escaping as a security measure (which in itself is a misconception), use prepared statements.
As per the comment below, a clarification is required it seems: You are escaping the password then hashing it, as a result what is stored in the db is not what the user passes therefore it will never find what the user passes, hence, false is always returned.
Related: Should I mysql_real_escape_string the password entered in the registration form?
Update #1
As spotted by @mario, you seem to have spaces in your query when you are passing the values to it as such, it is searching your table for incorrect values.
Reading Material
Prepared Statements
Related Topics
PHP Glob - Scan in Subfolders For a File
How to Get JavaScript Function Data into a PHP Variable
A Problem Occurred Somewhere in the Ssl/Tls Handshake
PHP Header Redirect Not Working
Import CSV File Directly into MySQL
PHP Is Confused When Adding and Concatenating
How to Access Dynamic Variable Names in Twig
Initializing PHP Class Property Declarations With Simple Expressions Yields Syntax Error
Access Controller Method from Another Controller in Laravel 5
PHP Curl Not Working - Wamp on Windows 7 64 Bit
How to Read Last Lines (I.E. "Tail") from a File Using PHP
Read Each Line of Txt File to New Array Element
Checking If a Variable Is an Integer in PHP
PHP Array Merge Two Arrays on Same Key