Password is not verified using function password_verify - php

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 code:
if($submit)
{
$first=$_POST['first'];
$password=$_POST['password'];
$hash="*85955899FF0A8CDC2CC36745267ABA38EAD1D28"; //this is the hashed password i got by using function PASSWORD in database
$password=password_verify($password,$hash);
$db = new mysqli("localhost", "root","","learndb");
$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
$result = $db->query($sql);
$result=mysqli_num_rows($result);
if($result>0)
{
session_start();
$_SESSION['logged_in'] = true;
session_regenerate_id(true);
header("Location:loginhome.php");
}
}
But the password is not matching. What am i missing here?
UPDATE:
After all the suggestions i have used password_hash from php code to store into database.
$db = new mysqli("localhost", "root","","learndb");
$password=password_hash('ChRisJoRdAn123',PASSWORD_DEFAULT);
$sql="INSERT INTO admin (username,password)values('ChrisJordan','$password')";
$db->query($sql);
still the password is not matching.

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);

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";
}

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.
The typical way to use 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().
Your other question Switching from md5 to password_hash
What you need to know is that MD5 produces a 32 character length string, as opposed to password_hash() being a 60 length.
Use 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:
http://php.net/manual/en/function.md5.php
Returns the hash as a 32-character hexadecimal number.
Reference for password_hash():
http://php.net/manual/en/function.password-hash.php
The result will always be a 60 character string, or FALSE on failure.
To ALTER your column, here is a reference link:
http://dev.mysql.com/doc/refman/5.7/en/alter-table.html
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

Related

decrypt password using salt

Code Here is encrypting password but How I decrypt it or Compare it to login in laravel
Code where used
getsql(md5($_POST['regpassword'] . SALT), "default"),
md5 is hashing and it's not reversible you can't decrypt it you can only hash the password using the same algorithm and salt then compare the results to make sure that it's the correct password
When you're validating the password, you can do:
$hashed = md5($_POST['password'] . SALT);
$sql = "SELECT * FROM users WHERE username = '{$_POST['username']}' AND password = '$hashed'";
I've simplified this to show the important part of how to check the password, in reality you should use a prepared statement to prevent SQL injection.
Another way is to fetch the hashed password from the database, then compare it with the hashed+salted password that was given:
$hashed = md5($_POST['password'] . SALT);
$sql = "SELECT password FROM users WHERE username = '{$_POST['username']}'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
if ($row && $hashed == $row['password']) {
// user is validated
}
If you fix your method of storing passwords to use a more reasonable method than a static SALT, this second method can easily be updated. Instead of $hashed == $row['password'] you would use password_verify($_POST['password'], $row['password']).

About hashing passwords with argon2i

I set up a dev server and I installed nginx with php-fpm and 7.2 php (I installed all the necessary php packages).
The time has come to upgrade the security of all logins, using the argon2i algo.
So, I tried this (test code in dev enviroment. The security in the code, will come later):
require('connector.php');
$usr_u = $_POST['username'];
$psw_u = $_POST['password'];
$usr = mysqli_real_escape_string($conn, $usr_u);
$psw = mysqli_real_escape_string($conn, $psw_u);
$f_pass = password_hash($psw, PASSWORD_ARGON2I);
$result = "SELECT `username` FROM `users` WHERE username = '$usr'";
$tbl = mysqli_query($conn, $result);
$table = $tbl->fetch_assoc();
$m_user = $table['username'];
if ($m_user == $usr)
{
//correct username
echo 'Correct username!<br>';
$result = "SELECT `password` FROM `users` WHERE username = '$m_user'";
$tbl = mysqli_query($conn, $result);
$table = $tbl->fetch_assoc();
$m_pass = $table['password'];
if (password_verify($m_pass,$f_pass)) //always returns false
{
echo 'Password correct!<br>';
}
else
{
echo 'Wrong password!<br>';
}
}
else
{
echo 'Wrong username!<br>';
}
//close connection
mysqli_close($conn);
I always get "Correct username!" and "Wrong password!". I used echo on hashed password from the DB and from the input and I see that every time the hashed password is different. I assume that the hashing process, include using random salt and there is my issue.
As far as I understand, the random salt is necessary in order to retain the security of the hashing.
Can you please point me to the right direction, on how to solve this? I have the hashed password in my DB and I can't figure out a way to check the input password against the one in my DB (using password_verify and hash_equals).
Thank everyone in advance for the help.
Look at the documentation for password_verify:
bool password_verify ( string $password , string $hash )
The first argument is the password but you are passing it the hash you want to compare it to.
The second argument is the hash you want to compare it to but you are passing it a new hash created from user input.
password_verify($_POST['password'], $m_pass)

Why is my password hashing function leading to data not being saved in the session? (PHP)

I am using the following two functions to hash passwords on a registration form:
function password_encrypt($password){
$hash_format = "$2y$10$"; //2y means use blowfish. 10 is cost parameter - number of times to run the blowfish hash.
//Blowfish wants salts of 22 characters or more.
$salt_length = 22;
$salt = generate_salt($salt_length);
$format_and_salt = $hash_format . $salt;
$hash = crypt($password, $format_and_salt); ///If this was echoed, salt would appear at beginning as part of result.
//Means hash can be passed in again as a salt. Then the has contains the salt making it easy to compare.
return $hash;
}
function generate_salt($length){
//MD5 returns 32 characters
$unique_random_string = md5(uniqid(mt_rand(), true));
//Valid characters for a salt are [a-zA-Z0-9./]
$base64_string = base64_encode($unique_random_string);
//But not '+' which is valid in base 64 encoding (base 64 encode returns '+' when it should be '.')
$modified_base64_string = str_replace('+','.', $base64_string);
//Truncate string to the correct length
$salt = substr($modified_base64_string, 0, $length);
return $salt;
}
When I run a check of the password with the following, data isn't being saved in the session:
if(!empty($User)&& !empty($Pass)){
$Pass = password_encrypt($Pass);
$query = "SELECT * FROM users WHERE '$User' = login AND '$Pass' = password";
$result = mysqli_query($connection, $query)
or die ('Error: '.mysql_error());
//If query produces nothing
if(!$query){
$Message = "Incorrect username and/or password.";
}else{
while($row = mysqli_fetch_assoc($result)){
///TODO Store user id in session as well
$_SESSION['first_name'] = $row["first_name"];
$_SESSION['group_id'] = $row["group_id"];
$_SESSION['user_id'] = $row["user_id"];
}
redirect_to('dashboard.php');
}
}
When I use plain text passwords instead of hashing the data is saved into the session correctly, however, when I use the hashing functions, accessing the session data I intended to save produces an error which says that, for example, the $_SESSION['user_id'] is an undefined index. Is there something wrong with the hashing methods?
The code is buggy and insecure and isn't going to work - the thread will never get to the point of trying to populate the session. But your question implies that you think it is getting there and there's something wrong with the session. There isn't.
The most elementary part of fault finding is isolating the problem - there are lots of ways of doing this, but instrumenting your code is a very simple way to do so. If you had you would know that your problem has nothing to do with the session.
You've not understood how salted hashes and initialization vectors work - you need to retrieved the hash from the password based on the suplied username then run it through crypt again in PHP land. There are lots of examples on the internet on how to do this.
Your problem is that you are not escaping characters in your encrypt password function:
$2aVOhEz8P7i6 will look for the variable '2aVOhEz8P7i6' which isn't set.
EDIT:
echo password_encrypt('hello');
= $2aVOhEz8P7i6
EDIT2:
also:
"SELECT * FROM users WHERE '$User' = login AND '$Pass' = password"
should be
"SELECT * FROM users WHERE login = '$User' AND password = '$Pass'"
for readability.

Hashing passwords with exact same inputs doesn't output the same value

I'm trying to hash the password if you sign up on my website, but it doesn't work.
This is my code to hash the password upon signing up:
$escapedName = mysql_real_escape_string($_POST['user']);
$escapedPW = mysql_real_escape_string($_POST['password']);
$salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
$hashedPW = hash('sha256', $escapedPW . $salt);
Then I just insert it in a database (the hashed password and the salt).
For example, when I hash Sas, with the following salt:
abac7ad23185ad19967f0d13e962197962782f0b7ec32d9889c27a93a9e800fa
This is the hashed password:
8ca5c5f31fafbf382533dbcbfc22b3635d776ec7770c7eac58d8ef9f1fa3613c
But when I try to hash the password on log in, with the exact same password and salt, this becomes the hashed pass:
6eb4b16444f18cee19db32bd29a39970e3019c5b1972a982ae4cb9a59642dffc
This is the code I use to login:
$escapedName = mysql_real_escape_string($_POST['user']);
$escapedPW = mysql_real_escape_string($_POST['password']);
$saltQuery = mysql_query("SELECT salt FROM members WHERE user='{$escapedName}'");
while($result = mysql_fetch_assoc($saltQuery)) {
$salt = $result['salt'];
}
$hashedPW = hash('sha256', $escapedPW . $salt);
$sql = mysql_query("SELECT * FROM members WHERE user='$escapedName' AND pass='$hashedPW'; ");
while ($res = mysql_fetch_assoc($query2)) {
$username = $res['user'];
$PW = $res['pass'];
}
I hope it's not too much code and I also hope you will understand my question.
Sorry I can't comment but something tells me that there is a length restriction on the salt column in your database.
Example: The salt field might only allow a 64 characters while the generated salt might be longer therefore when you save the salt it gets trimmed which ultimately changes the hashed password.
If that's the case, you might want to trim the salt before saving it.
I'd advise using PDO to make queries against your database.
Your inputs to the hash function must be different for some reason or other.
Add log output messages that print your inputs before you hash for both use cases (create user and login). Also be sure to put quotes around the inputs in your logging to show whitespace issues.
Compare the raw inputs as well as the output of the hash function in both cases, and there will be a difference somewhere. If there is no difference, and the output of the hash is the same, then there is a problem in your query that is looking up the user in the login case.
Whatever you're doing, it's insecure if you WANT the hashes to be the same! See http://php.net/crypt for proper password hashing.
All you need:
function check_password($password) {
...//get db password to compare
if (crypt($post_password, $db_results[0]['password']) == $db_results[0]['password']) {
return true;
} else { return false; }
}

Authentication failed, even password is correct, using bcrypt hash method

I am having problem with bcrypt hash method and mysql. I'm using the Bcrypt class from this answer.
I am creating login script and checking, if password is
correct. I am comparing password from input and hashed
password from DB.
$username= $_POST['username']; //username from input
$pass= $_POST['pass']; //username from input
$query= mysql_query("SELECT pass FROM users WHERE username='$username'");
$row= mysql_fetch_row($query);
$row[0];// hashed password, I echo $row[0] and it shows correct hashed password
$bcrypt = new Bcrypt(15);
$isGood = $bcrypt->verify($pass, $row[0]);
if ($isGood){
echo "Authentication succeeded";
}
else {
echo"Authentication failed";
}
Even $pass is correct, I always get 'Authentication failed'.
Any ideas, what can be wrong?
Thank you in advance.
The pass column in your users table is not wide enough to store the complete hash; it should be at least 60 characters wide, i.e. VARCHAR(60).
Btw, you should check out PasswordLib as well, written and maintained by ircmaxell, which also supports Bcrypt quite well.
Try something like this:
$bcrypt = new Bcrypt(15);
$hash = $bcrypt->hash($pass);
echo $hash.' =? '.$row[0];
And look if it's equal
if yes, try something like this:
var_dump($hash);
var_dump($row[0]);
Must be equal

Categories