I think i have hashed password using function PASSWORD
directly from mysql database(am i doing wrong here?). And i am trying to verify that password with this c
You must use password_hash to encode passwords verified with password_verify.
The MySQL function PASSWORD is something entirely different. It is used for encoding passwords specific to MySQL authentication. (MySQL specifically recommends against using PASSWORD
for anything other than MySQL authentication.)
The two use different hashing algorithms, present their output in different formats, and are generally not compatible with each other.
password_hash
and password_verify
is:
$hash = password_hash($password, PASSWORD_DEFAULT);
//Store $hash in your database as the user's password
//To verify:
//Retrieve $hash from the database, given a username
$valid = password_validate($password, $hash);
The problem in your code is that you're doing this:
$password=password_verify($password,$hash); $sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
password_verify
returns a boolean (whether the password and hash matched). Instead, you need to retrieve the hash from the database and match the entered password with that hash.
This is too long for a comment.
Seeing that this question has yet to contain a green tick next to any of the answers, am submitting the following in order to point out probable issues.
I noticed that you are trying to move over from MD5 to password_hash()
- password_verify()
.
What you need to know is that MD5 produces a 32 character length string, as opposed to password_hash()
being a 60 length.
varchar(255)
.If you kept your password column's length to 32, then you will need to clear out your existing hashes from that column, then ALTER your column to be 60, or 255 as the manual suggests you do.
You will need to clear out all your existing passwords, ALTER your column, create a new hash, then try your login code again.
I see this in your code:
"*85955899FF0A8CDC2CC36745267ABA38EAD1D28"; //this is the hashed password i got by using function PASSWORD in database
This string *85955899FF0A8CDC2CC36745267ABA38EAD1D28
is 40 long, which is too short and has been cut off.
This tells me that your column's length is 40, instead of 60, or again as the manual suggests, 255.
MD5 reference:
Returns the hash as a 32-character hexadecimal number.
Reference for password_hash()
:
The result will always be a 60 character string, or FALSE on failure.
To ALTER your column, here is a reference link:
Also make sure that your form contains a POST method and that the inputs bear the matching name attributes and that no whitespace gets introduced.
You can use trim()
to get rid of those.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Then the rest of your code
Sidenote: Displaying errors should only be done in staging, and never production.
as well as or die(mysqli_error($db))
to mysqli_query()
.
Edit:
What you need to do is fetch an array and get the match on that.
$sql = "select * from admin where username = '".$first."' and password = '".$password."' ";
$result = $db->query($sql);
if ($result->num_rows === 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (password_verify($password, $row['password'])) {
//Password matches, so create the session
// $_SESSION['user']['user_id'] = $row['user_id'];
// header("Location:/members");
echo "Match";
}else{
echo "The username or password do not match";
}
}
Another possible solution:
$query = "SELECT * from admin WHERE username='$first'";
$result = $db->query($query);
if($result->num_rows ===1){
$row = $result->fetch_array(MYSQLI_ASSOC);
if (password_verify($password, $row['password'])){
echo "match";
} else {
$error = "email or Password is invalid";
echo $error;
}
}
mysqli_close($db); // Closing Connection
password_verify
is a boolean function which return either true
or false
. In your code, after getting value of password from Post param, you doing this operation
$password=password_verify($password,$hash);
which changes the $password
value to true
or false
and that boolean value stored in $password
you are using in mysql select statement
$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
Another thing is it might be possible that the hashed/salted password you are using is not the correct hashed value of the password you are using.
Update: Try this
$cost = [
'cost' => 15,
];
$hash_password = password_hash('ChRisJoRdAn123', PASSWORD_BCRYPT, $cost);
before any db operation, change your password
field varchar
length to >=64
$sql = "INSERT INTO admin (username,password)values('ChrisJordan','".$hash_password."')";
After insert operation, execute the select statement with the user
$sql = "select * from admin where username = 'ChrisJordan'";
after this fetching hased password
and password
from the post parameter, you will need to verify both passwords using password_verify
if (password_verify(validate($_POST['password']), $hash_password_from_db)) {
echo "Valid Password";
}else{
echo "Invalid Password";
}
One cannot search for a salted password hash in a database. To calculate the hash you need the password_hash() function as you already did correctly in your insert statement.
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
To check a password, you first need to search by username only (used a prepared query to avoid sql injection):
$sql = 'select * from admin where username = ?';
$db->prepare($sql);
$db->bind_param('s', $first);
When you finally got the stored hash from the database, it can be checked like this:
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);