Search code examples
phpmysqlmysqliphp-password-hash

Pulling a hashed username from MySQL database


I'm working on a project where both the username and password need to be hashed with Argon2. I'm not having any trouble hashing them both in the registration and inserting them into the database, but I'm unable to pull the information for the login. Here is my login script:

<?php  session_start(); ?>
<?php
include 'config.php';
if(isset($_POST['submit'])){
$submittedUser = $_POST['username'];
$submittedPass = $_POST['password'];
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);

$con=mysqli_connect($servername, $dbusername, $dbpassword, $dbname);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if ($stmt = mysqli_prepare($con, "SELECT * FROM users Where username =?")) {
                    mysqli_stmt_bind_param($stmt, "s", $encrypteduser);
                    mysqli_stmt_execute($stmt);
                    $result = mysqli_stmt_get_result($stmt);
}

while($row = mysqli_fetch_array($result))
{
$username = $row['username'];
$password = $row['password'];
}
if (password_verify($submittedUser, $username) && password_verify($submittedPass, $password))
{
$_SESSION['user']=$username; 

echo "<script> location.href='index.php'; </script>";
        exit;   
}
else
{
 echo "<script> location.href='login.php'; </script>";
        exit;   
}
mysqli_close($con);
}
?>

My current theory is that the hash being generated and stored in $encrypteduser does not match the one in the database. That would explain why no result is being pulled. Is there a way to get around this?


Solution

  • This does not encrypt, it hashes:

    $encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
    

    I.e., it's one way. You (theoretically) can never get the original text back from it. It will also generate a different result every time you run it. As a result, you'll never be able to run a query with a WHERE clause to pick out one matching user. Rather, you'd have to iterate over every user in the system, running password_verify() against each of them.

    So... don't do that. Leave the username in plain text so that you can benefit from the database index.