Search code examples
phppassword-hash

Unable to use password_verify($password, $hash)


So I have a Registration page and a Login page, the registration page works perfectly fine but the Login page doesnt seem to work and I cant seem to figure it out.

My database seems to be working as I am able to echo out the hashed password onto the page of the login, it seems to have something to do with password_verify()

Registration Page (Working)

<?php 
include("assets/includes/conn.php");

$user = $_POST['username'];
$pass = $_POST['pass'];
$cPass = $_POST['c-pass'];
$email = $_POST['email'];

$options = [
    'cost' => 11
];

if($pass == $cPass){

    $stmt = $conn->prepare("INSERT INTO users (username, pass, email) VALUES (?, ?, ?)");
    $stmt->bind_param("sss", $user, $h_p, $email);

    $user = $_POST['username'];
    $h_p = password_hash($pass, PASSWORD_DEFAULT, $options)."\n";
    $email = $_POST['email'];
    $stmt->execute();

    echo "Created";
    echo $h_p;
    $stmt->close();
    $conn->close();

}

Login Page (Not working)

<?php 
include("assets/includes/conn.php");

$username = $_POST['username'];
$password = $_POST['pass'];

$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);

if ($result->num_rows == 1){
    $row = $result->fetch_assoc();
    $hash = $row['pass'];

    if(password_verify($password, $hash)){
        echo "Yes";
    } else {
        echo "No<br/>";
        echo "" . $hash . "<br/>";
        echo $password;

    }
}

Solution

  • The problem here is that the \n in:

    $h_p = password_hash($pass, PASSWORD_DEFAULT, $options)."\n";
                                                             ^^
    

    is (invisibly) adding a carriage return/linefeed at the end of your password/hash.

    You can either remove it.

    $h_p = password_hash($pass, PASSWORD_DEFAULT, $options);
    

    or trim() it:

    $h_p = password_hash($pass, PASSWORD_DEFAULT, $options)."\n";
    $h_p = trim($h_p);
    

    I honestly don't know why the manual on password_hash() doesn't make a mention about it and the usage of it for storing it in a database (or a file).

    NOTE: What the docs haven't used here, was to assign a variable to the example, which is what was done in the question here. Some may think that using the example and assigning a variable to it will work; it won't; not for storing the hash and then verifying it after.

    The example from the manual reads as:

    echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
    

    But doing:

    $var = password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
    

    will in fact (theoretically) contain a 61-length string (because of the concated linefeed character), instead of the intended 60 without the linefeed character.

    • So now you need to clear out your present hashes and start over with a new set of hashes.

    Have a look at this sandbox code example

    When run, it will output something like this:

    $2y$10$494GPYzaynEkfYxE3wcAj.OtwBU3CCwTMXOHKbdJmOqwMXRmq6v1u
    61
    

    Just in case the URL's a 404 later on, here's the code for the above:

    <?php
    $foo = password_hash('mypass',  PASSWORD_DEFAULT)."\n";
    echo $foo;
    echo strlen($foo);
    

    On an added note; you should also use a prepared statement for your SELECT just as you did for the INSERT; it's much safer.