I would like to verify my stored hashed passwords with the inputs that the users insert.
What theory says...
After read about the mechanism of password_hash and password_verify, I realized that, theoretically, the string that is inserted will be compared with a hash, which, at least in my case, is stored in the site db.
What is happening to me...
I register my users with password_hash and then to verify the login I use password_verify. If I am good and the code is right, this function should verify the input of the user (even if it's plain text(?) ) with the stored hash.
Let's see the code:
Registration code:
$passwordHash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 12));
Note: There is more code but I guess that this is the most important part so I decided to paste only this part.
Login code:
<?php
//controller!
require "../model/backend.php";
$username = $_POST['user'];
$password = $_POST['password'];
$dbcom = new dbInteraction;
$dbcom->admlog($username, $password);
$dbcom->conclose();
?>
Verification code:
$this->username = $username;
$this->password = $password;
//$this->pdo = $pdo;
//$adm = 1;
$myquery = 'SELECT username, password, isadmin FROM users WHERE username = :username';// AND password = :password';
$stmt = $this->pdo->prepare($myquery);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if($user === false){
die('1Incorrect username / password combination!');
} else{
//Compare the passwords.
$dbpass = $user['password'];
echo $dbpass;
echo '<br>bd<br>input<br>';
echo $password;
$validPassword = password_verify($dbpass, $password);
echo '<br>debug <br>';
echo 'pre pass:<br>';
echo $validPassword;
if($validPassword){
//Provide the user with a login session.
$_SESSION['user_id'] = $user['username'];
$_SESSION['logged_in'] = time();
//header('Location: home.php');
exit;
}else{
die('<br>no pass--Incorrect username / password combination!');
}
}
Do I have some theoretical base problem in my code or it's just bad coded? I'm still trying to realize.
Thank you very much.
The problem was in the order of password_verify params.
It should be like $validPassword = password_verify($password, $dbpass);
or in generic words:
$validPassword = password_verify('String to verify', 'Saved password');
Special thanks to #JonStirling
Related
I'm using password_hash to secure password in database, but when I use password_verify, it doesn't match. In the fist case, I use password_verify for the connection of the user, and it always return true, even when it's not the good password. In the second case, I use password_verify when the user wants to change his password, he is asked to give his actual password to change it. In this case, it always return false, even if I use password_verify in the same way I do for the connection.
In my database, password is stored as VARCHAR(60). I also tried VARCHAR(255), makes no difference.
Here is how I use password_hash when user create his account :
if(isset($_POST['username']) && isset($_POST['password']) && isset($_POST['psw-confirmation'])) {
$username = htmlspecialchars($_POST['username']);
$password = htmlspecialchars($_POST['password']);
$pswConfirmation = htmlspecialchars($_POST['psw-confirmation']);
if($password == $pswConfirmation) {
// Connection to database
require('database-connection.php');
$request = $database->prepare("SELECT * FROM users WHERE username = :username");
$request->execute(array(
":username" => $username
));
$return = $request->fetch();
// If the username doesn't exist yet in the database
if(!$return) {
$request->closeCursor();
$hash = password_hash($password, PASSWORD_BCRYPT);
$addProfile = $database->prepare("INSERT INTO users(username, password) VALUES(:username, :password)");
$addProfile->execute(array(
":username" => $username,
":password" => $hash
));
I guess this part is working well because I do have a hashed password in my database : $2y$10$AFV2zouzirBhS30tCCRx9uyZDNMGSJWffUbXMO876T/9nJ8UDQJRi
Here is how I verify the password for the connection :
if(isset($_POST['username']) && isset($_POST['password'])) {
$username = htmlspecialchars($_POST['username']);
$password = htmlspecialchars($_POST['password']);
// Connection to database
require('database-connection.php');
$request = $database->prepare("SELECT * FROM users WHERE username = :username");
$request->execute(array(
":username" => $username
));
$return = $request->fetch();
$hash = $return['password'];
// If the username exists in the database
if($return) {
// And if the password match
if(password_verify($password, $hash)) {
echo "connected";
}
And here how I verify the password when the user want to change his password :
if(isset($_POST['actual-psw']) && isset($_POST['new-psw']) && isset($_POST['confirm-psw'])) {
$actualPsw = htmlspecialchars($_POST['actual-psw']);
$newPsw = htmlspecialchars($_POST['new-psw']);
$confirmPsw = htmlspecialchars($_POST['confirm-psw']);
// Connection to database
require('database-connection.php');
$request = $database->prepare("SELECT * FROM users WHERE id = :id");
$request->execute(array(
':id' => $_SESSION['id']
));
$return = $request->fetch();
$hash = $return['password'];
if(password_verify($actualPsw, $hash)) {
echo "success";
} else {
echo "fail";
}
$_SESSION['id'] is returning the good id of the actual user.
I don't understand why it doesn't work, and it makes me even more confuse that in one case it's always true and in another it's always false, because I used the same way in both cases.
I find out where my mistake were;
I had this database-connection.php file :
$host = 'localhost';
$dbname = 'japonwebsite';
$user = 'root';
$password = 'mysql';
try
{
$database = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user,
$password);
}
catch (Exception $e)
{
die('Erreur : ' . $e->getMessage());
}
I include this file on all the pages where I need to connect to database, so I have it included on the page to add users to database and the one that verify log in.
Thing is, on both of those pages, I was doing $password = $_POST['password']; to stock in a variable the password entered by the user on the sign in or sign up form.
After that, i was doing include('database-connection.php'); to connect to database. So $password was always equal to mysql, because I also have a variable $password in database-connection.php. So I was always adding the hash of "mysql" in the database, and always verifying that the hash in the database was equal to "mysql", so it was always true. I Just renamed the variable $password in database-connection to fix it !
I have a PHP login form which uses a MD5 hash for my password security (I know MD5 is bad, I am going to change its later on; it is just for developing purposes right now). When I use == on the password comparing it won't log me in.
Does md5ing return a string or something else maybe because in my database I just have the string of the word password as if it were MD5'ed ("5f4dcc3b5aa765d61d83")? This is the beginning stages of my login I will be added prepare statements and all that as well after I better research them and get this working.
Also the domain I was given is running PHP version 5.3.28, so password_verify() won't work for this development site.
The index page (login)
<?php
session_start();
if (isset($_POST['username'])) {
// Include the databas connection script
include_once("includes/connect.inc.php");
// Set the posted data from the form into local variables
$usname = $_POST['username'];
$paswd = $_POST['password'];
$usname = mysqli_real_escape_string($connect, $usname);
$sql = "SELECT * FROM dealerEmployees WHERE firstName = '$usname' LIMIT 1";
$query = mysqli_query($connect, $sql);
$row = mysqli_fetch_row($query);
$uid = $row[0];
$dbUsname = $row[1];
$firstName = $row[1];
$lastName = $row[2];
$dbPassword = $row[3];
$permission = $row[4];
$address = $row[5];
$email = $row[6];
$phone = $row[7];
$profilePhoto = $row[8];
$bannerPhoto = $row[9];
// Check if the username and the password they entered was correct
if ($usname == $dbUsname) {
if($paswd == $dbPassword){
// Set session
$_SESSION['id'] = $uid;
$_SESSION['userId'] = $uid;
$_SESSION['username'] = $usname;
$_SESSION['firstName'] = $firstName;
$_SESSION['lastName'] = $lastName;
//$_SESSION['password'] = $dbPassword;
$_SESSION['permission'] = $permission;
$_SESSION['address'] = $address;
$_SESSION['phone'] = $phone;
$_SESSION['email'] = $email;
$_SESSION['profilePhoto'] = $profilePhoto;
$_SESSION['bannerPhoto'] = $bannerPhoto;
// Now direct to users feed
header("Location: hub.php");
}
} else {
echo "<h2>Oops that username or password combination was incorrect.
<br /> Please try again.</h2>";
}
}
?>
<form id="form" action="index.php" method="post" enctype="multipart/form-data">
<input type="text" name="username" placeholder="Please Enter Your First Name"/> <br />
<input type="password" name="password" placeholder="Please Enter Your Password"/> <br />
<button class="button" type="submit">Log In</button>
</form>
First off, this is a very bad idea:
$paswd = strip_tags($_POST['password']);
If I'm being careful to generate strong passwords, there's a good chance my password may be something like c5<dZIuJYWUP3>y. You just turned my password into the very crackable c5y.
Using MD5 is also a very bad idea. Use password_hash and password_verify to take advantage of PHP's built-in handling for the industry-standard bcrypt algorithm. There's no reason to practice writing bad code.
Does md5ing return a string or something else maybe?
Yes, it'll return a 32 character string made up of the 0-9 and a-f characters. The MD5 hash of password, for example, is 5f4dcc3b5aa765d61d8327deb882cf99.
But when I use == on the password comparing it wont log me in.
Then the MD5 hash of the password the user entered doesn't match the MD5 hash you have stored in the database.
For ease of debugging, consider manually editing your database row to use the hash 5f4dcc3b5aa765d61d8327deb882cf99, and try logging in with the password password. If this works, you either weren't storing a MD5 hash in the database or you were storing the wrong MD5 hash in the database - possibly because of your strip_tags stuff.
If it doesn't, you have something more fundamental going on - possibly made easier to debug by using mysqli_fetch_assoc instead of mysqli_fetch_row on your SELECT * query.
I see a lot of insecurity in your login script. You need to use prepared statements. Or anyone with a clue could inject you and delete your database or login as admin. You should also use sha512 to hash, it is almost impossible to decrypt.
But to your question:
= is to assign something.
== is to check if they are the same basic value.
=== is to check if they are the same value and same type.
You were assigning $paswd to $dbPassword in your if statement instead of checking if they match.
Corrected the if:
// Check if the username and the password they entered was correct
if ($usname === $dbUsname && $paswd === $dbPassword) {
// Set session
$_SESSION['id'] = $uid;
$_SESSION['userId'] = $uid;
$_SESSION['username'] = $usname;
$_SESSION['firstName'] = $firstName;
$_SESSION['lastName'] = $lastName;
$_SESSION['password'] = $dbPassword;
$_SESSION['permission'] = $permission;
$_SESSION['address'] = $address;
$_SESSION['phone'] = $phone;
$_SESSION['email'] = $email;
$_SESSION['profilePhoto'] = $profilePhoto;
$_SESSION['bannerPhoto'] = $bannerPhoto;
// Now direct to users feed
header("Location: hub.php");
} else {
echo "<h2>Oops that username or password combination was incorrect.
<br /> Please try again.</h2>";
}
Here is a pretty secure login script. Its just part of it, but if you read it it should really shed some ligh on what you need to do. No offence, but your script is not good.
function login($email, $password, $mysqli) {
// Using prepared statements means that SQL injection is not possible.
if ($stmt = $mysqli->prepare("SELECT id, username, password, salt
FROM members WHERE email = ? LIMIT 1")) {
$stmt->bind_param('s', $email); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
// get variables from result.
$stmt->bind_result($user_id, $username, $db_password, $salt);
$stmt->fetch();
// hash the password with the unique salt.
$password = hash('sha512', $password . $salt);
if ($stmt->num_rows == 1) {
// If the user exists we check if the account is locked
// from too many login attempts
if (checkbrute($user_id, $mysqli) == true) {
// Account is locked
// Send an email to user saying their account is locked
return false;
} else {
// Check if the password in the database matches
// the password the user submitted.
if ($db_password == $password) {
// Password is correct!
// Get the user-agent string of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT'];
// XSS protection as we might print this value
$user_id = preg_replace("/[^0-9]+/", "", $user_id);
$_SESSION['user_id'] = $user_id;
// XSS protection as we might print this value
$username = preg_replace("/[^a-zA-Z0-9_\-]+/",
"",
$username);
$_SESSION['username'] = $username;
$_SESSION['login_string'] = hash('sha512',
$password . $user_browser);
// Login successful.
return true;
} else {
// Password is not correct
// We record this attempt in the database
$now = time();
$mysqli->query("INSERT INTO login_attempts(user_id, time)
VALUES ('$user_id', '$now')");
return false;
}
}
} else {
// No user exists.
return false;
}
}
}
if ($usname == $dbUsname && $paswd = $dbPassword) {
To execute this sentence also, what you're doing is to set the variable $paswd value $dbPassword.
The comparison should be more or less like this:
if (($usname == $dbUsname) && ($paswd == $dbPassword)) {
I am using password_hash to store passwords in a MySQL database field of type VARCHAR(255). When I try to login the user and verify credentials, the password_verify function always returns false.
Here is the code excerpt that stores the password in the MySQL database:
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// Generate API Key
$api_key = $this->generateApiKey();
// Insert Query
$stmt = $this->conn->prepare("INSERT INTO user(email, password, name, api_key, status) values(?, ?, ?, ?, 1)");
$stmt->bind_param("ssss", $email, $password_hash, $name, $api_key);
$result = $stmt->execute();
$stmt->close();
And the piece of code that checks the password:
// Query user by email
$stmt = $this->conn->prepare("SELECT password FROM user WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->bind_result($password_hash);
$stmt->store_result();
if ($stmt->num_rows > 0) {
// Found user with that email address
// Now verify the password
$stmt->fetch();
$stmt->close();
if (password_verify($password, $password_hash)) {
// User password is correct
return TRUE;
Then I wrote this test code and grabbed the data straight from the MySQL field and it still fails. When I create the password_hash in the same file ($hash2 in the file below) - then the password verifies correctly.
$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';
$hash2 = password_hash($password, PASSWORD_DEFAULT);
echo $hash . " - " . strlen($hash);
echo "<br />";
echo $hash2 . " - " . strlen($hash2);
echo "<br />";
if (password_verify($password, $hash)) {
echo "Password Valid!";
} else {
echo "Password invalid!";
}
echo "<br /><br />";
if (password_verify($password, $hash2)) {
echo "Password 2 Valid!";
} else {
echo "Password 2 invalid!";
}
This proves that something is wrong with your hash
<?php
// See the password_hash() example to see where this came from.
$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';
$hash2 = '$2y$10$gMJKYZUc1FKSZBnsONxLOebOHj.uuEWSiCP0jo4Zv0iAHBz6iz.NG';
if (password_verify('pass1234567890', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
echo "<br>";
if (password_verify('pass1234567890', $hash2)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
Screenshot
In my case the probme was that I stored the database connection query in another file which included the same variable that I used for fetching current password, so what happened was that first I assigned a variable "password" to current password and then included my connection query file which had the same variable "password" therefore what happened was that, "password" variable of signup form was reassigned by "password" variable of connection query, and that's why it actually hashed another password. So by changing the variable name this problem was solved.
Here is my code for reference,
signup.php
$email = $_POST["email"];
$password = $_POST["password"];
include 'partials/php/_dbconnect.php';
$passwordHash = password_hash($passwd, PASSWORD_DEFAULT);
_dbconnect.php
<?php
$server = "localhost";
$username = "root";
$password = "";
$database = "demo";
$connectionquery = mysqli_connect($server, $username, $password, $database);
?>
which I changed to;
$email = $_POST["email"];
$passwd = $_POST["password"];
include 'partials/php/_dbconnect.php';
$passwordHash = password_hash($passwd, PASSWORD_DEFAULT);
password_verify($password,trim($password_hash)))
While I am unsure if it happened when the hash was stored or during retrieval, the password_hash had a space at the end. Trimming the hash before feeding it to password_verify fixed the issue for me.
Just make a variable for if(password_verify($pass_input, $pass_db))
where $pass_input is the value given from the textified form and $pass_db is the value stored in mysql (hashed)
Like this:
$verif_pass = (password_verify($pass_input, $pass_db));
if($verif_pass){echo "TRUE"} else {echo "FALSE";}
and just modify TRUE/FALSE as you want.
I'm hashing my passwords with blowfish using Anthony Ferrara's password compactibility library. When I hash 'em they're good, BUT when I try to verify the passwords, doing this:
public function Login($username, $postpassword) {
$stmt = $this->mysqli->prepare("SELECT username, password FROM users WHERE username=? AND password=?");
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$stmt->bind_result($username, $password);
$stmt->store_result();
if($stmt->num_rows == 1) {
while($stmt->fetch()) {
if (password_verify($postpassword, $password)) {
$SESSID = $this->newSession($username);
$_SESSION['admin_user'] = $username;
$_SESSION['last_login'] = time();
header("Location: home.php?SESSID=$SESSID");
exit();
}
}
}
else {
header("Location: index.php?e=false");
exit();
}
$stmt->close();
$stmt->free_result();
}
It tells me that me details are wrong... And YES, i did define the $username and $password:
if(isset($_REQUEST['login'])) {
$username = $_POST['username'];
$postpassword = $_POST['password'];
$users->Login($username, $postpassword);
}
Does anybody see the mistake I made?
You are selecting the user from the database where the username matches the entered username and the password hash matches the entered plaintext password. Of course this will never match anything. You will have to select the username and password from the database only based on the username, then verify the password using password_verify.
This question already has an answer here:
How to use php's password_hash() method..?
(1 answer)
Closed 6 years ago.
I want to save passwords in my database using:
$insert_pass = password_hash($pass, PASSWORD_BCRYPT);
And when a user needs to login, and if his password is equal to admin and as a hash the admin string is in the database as the following:
$2y$10$T5Gbe.VJyXihIJGhRJuP9ep3ydh/okw4rlKS/oe9KH3ho83mpmQ1y
And then when I make a query to see if user have correct credentials:
$user = $_POST['user_name'];
$pass = $_POST['user_pass'];//From text boxes
$hash = password_hash($pass, PASSWORD_BCRYPT);
if($user == "" || $pass == "")
{
echo $msg = "Please add user name and password";
}
else
{
$sql = "SELECT * FROM login WHERE user_name = :u LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bindValue(':u', $user, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll();
if($result)
{
//echo $msg = "user exist";
if(session_status() == PHP_SESSION_NONE)
{
session_start();
foreach($result as $row)
{
if(password_verify($row['user_pass'], $hash))
{
$_SESSION['userid'] = $row['user_id'];
$_SESSION['role'] = $row['user_role'];
header("Location: homepage.php");
}
}
}
}
}
It is not working and it's not logging in, how to compare a hash password into an existing hashed string ?
I am new to encryption methods and I am building a login system for a company so I need to build a secure method. Any help is appreciated.
You do not compare a hashed password with the aready hashed password stored on your database. The password_verify() does the hashing of the string password using the information the password_hash() stored in the hash it made
So your test shoudl be like this
password_verify($_POST['user_pass'],$row['user_pass'])