Using Password_Hash and Password_Verify

Using password_hash and password_verify

On signup you get the password from the user input and generate its has using password_hash():

$hash = password_hash($_POST['password'], PASSWORD_BCRYPT);

You can provide it a custom salt to use, in a third parameter, but the documentation recommends to not do this:

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.

You save this hash in the database. Make sure you put it in a CHAR/VARCHAR field of 60 characters or longer.

When the user wants to log in you check the password they input against the hash previously saved using password_verify():

$auth = password_verify($_POST['password'], $hash);

Of course, you get the correct value of $hash from the database, searching by the provided username.

If $auth is TRUE then the provided password matches its hash computed on the registration and the user is authenticated.

Using password_hash and password_verify from different objects in OO PHP

In answer to my question, it doesn't matter which classes use password_hash and password_verify, if there's a match with the password to verify and the hash from the database it should return a positive result!

The issue was with __construct() for the RegisterUser class - the call to the parent passed in $uncheckedLastName rather than the $uncheckedPassword and therefore the password being set at registration was not what was supplied in the password field but that what was supplied in the LastName field!

Problems with password_hash() and password_verify()

This returns a boolean (true/false) value:

password_verify($user['password'], $password)

So this will never be true:

$user['password'] === password_verify($user['password'], $password)

Once you've selected the user from the database based on the provided username, just verify the password:

if (password_verify($user['password'], $password)) {

A couple notes on your terminology, becase it's important...

I want to crypt the user's password

No, you do not want to encrypt the user's password. You want to "hash" it. It's an important distinction. Encrypted things can be returned to their original form. Hashed things can not. Which is a vital part of password security.

compare the dehashed password with the hashed password

There's no "dehashed" anything. What the internals of password_verify does is hash the provided password and compare that result with the already-hashed stored password. At no point can you in any way convert the stored hashed password back to its original form.

PHP password_hash(), password_verify()

Here is what I use for password_hash and password_verify. Try it out as written, you can then start adding in the rest of your code once successful.

Modify table and column name(s) to suit.

N.B.: This is a basic insertion method. I suggest you use prepared statements instead.

Sidenote: The password column needs to be long enough to accomodate the hash VARCHAR(255). Consult "Footnotes".

INSERT file

<?php
$DB_HOST = 'xxx';
$DB_USER = 'xxx';
$DB_PASS = 'xxx';
$DB_NAME = 'xxx';

$conn = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if($conn->connect_errno > 0) {
die('Connection failed [' . $conn->connect_error . ']');
}

$password = "rasmuslerdorf";
$first_name = "john";
$password = password_hash($password, PASSWORD_DEFAULT);

$sql = "INSERT INTO users (`name`, `password`) VALUES ('" .$first_name ."', '" .$password ."')";

$query = mysqli_query($conn, $sql);
if($query)

{
echo "Success!";
}

else{
// echo "Error";
die('There was an error running the query [' . $conn->error . ']');
}

LOGIN file

<?php
// session_start();

$DB_HOST = 'xxx';
$DB_USER = 'xxx';
$DB_PASS = 'xxx';
$DB_NAME = 'xxx';

$conn = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if($conn->connect_errno > 0) {
die('Connection failed [' . $conn->connect_error . ']');
}

$pwd = "rasmuslerdorf";
$first_name = "john";

//$sql = "SELECT * FROM users WHERE id = 1";

$sql = "SELECT * FROM users WHERE name='$first_name'";
$result = $conn->query($sql);
if ($result->num_rows === 1) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (password_verify($pwd, $row['password'])) {

//Password matches, so create the session
// $_SESSION['user'] = $row['user_id'];
// header("Location: http://www.example.com/logged_in.php");

echo "Match";

}else{
echo "The username or password do not match";
}

}

mysqli_close($conn);

Footnotes:

The password column should be long enough to hold the hash. 72 long is what the hash produces in character length, yet the manual suggests 255.

Reference:

  • http://php.net/manual/en/function.password-hash.php

"Use the bcrypt algorithm (default as of PHP 5.5.0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice)."

Issue with password_hash and password_verify, always returning true in one case, false in another

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 !

PHP can not login with correct password using password_hash()/password_verify()

I've created a simple gist where you can see a version of your code which I managed to run correctly and got the correct results:

  • a user can signup
  • a user can sign in
  • a user can sign out

I find that your code was correct, in broad strokes, but I also believe you must have mixed up some of your variables and field names.

In your question you do a var_dump of $row['pwdUsers'], a field never seen in the insert statement. You also select the field username when fetching data to compare to the one submitted for login, but in the insert statement the variable that you insert into that field is named $mailuid (while a variable $username sits next to it).

Given that when extracted and applied in a controlled environment your code works, I'd wager your error is due to a possible mix-up caused by the previously mentioned confusing nomenclatures, or due to some other logic hidden from us in the snippets you provided.

How to use PHP's password_hash to hash and verify passwords

Using password_hash is the recommended way to store passwords. Don't separate them to DB and files.

Let's say we have the following input:

$password = $_POST['password'];

You first hash the password by doing this:

$hashed_password = password_hash($password, PASSWORD_DEFAULT);

Then see the output:

var_dump($hashed_password);

As you can see it's hashed. (I assume you did those steps).

Now you store this hashed password in your database, ensuring your password column is large enough to hold the hashed value (at least 60 characters or longer). When a user asks to log them in, you check the password input with this hash value in the database, by doing this:

// Query the database for username and password
// ...

if(password_verify($password, $hashed_password)) {
// If the password inputs matched the hashed password in the database
// Do something, you know... log them in.
}

// Else, Redirect them back to the login page.

Official Reference



Related Topics



Leave a reply



Submit