1

I know this one has been asked before but have not been able to find a solution on previous questions.

Secure hash and salt for PHP passwords

Password verifying against database using bcrypt

php password_verify not working with database

I'm attempting to hash the password when registering and then verify it when trying to login. The query is retrieving the password associated with the username however isn't being verified correctly.

The problem is the way I am trying to use password_verify but no matter what I'v tried the past few hours I haven't been able to get it working. If anyone could take a look and try spot what I'm doing wrong it would be a great help.

The DB column length is set to 255 and Varchar to allow the full hash entry.

$SQL_Query = "SELECT * FROM user_information WHERE userName = '".$username."'"; 

            $result = mysqli_query($conn, $SQL_Query);                                                                      
            $num_rows = mysqli_num_rows($result);
            //below is the algorithm being used on the registration page
            //$hash = password_hash($ID, PASSWORD_BCRYPT, array('cost'=>10));

            if ($num_rows > 0)
            {                                                   //if there is match for the query within the database

                while($row = mysqli_fetch_array($result))       //attempts to retrieve the password associated with the username
                {
                    $row['password'];
                    $stored_hash = $row['password'];    
                }                                                   

                if(password_verify($ID, $stored_hash))
                {
                        $_SESSION['login'] = "1";                       
                        $_SESSION['username']= $username;               
                        header('Location: stats.php');              //login success

                } else {

                    $errorMessage = "Login Unsuccessful";
                    $_SESSION['error'] = $errorMessage;             
                    $_SESSION['login'] = "";                        

                    header('Location: login.php');                  //redirect the user to the login page
                }

            } else {

                $errorMessage = "Login Unsuccessful";
                $_SESSION['error']=$errorMessage;               
                $_SESSION['login'] = "";                        

                header('Location: login.php');                      //redirect the user to the login page
            }

So I know the hash being returned from the database is being set in the $stored_hash variable correctly as if I hard code the hash returned from it and compare it, login is correct. Could it be something altering the input somewhere?

<?php 

error_reporting(E_ALL); ini_set('display_errors', 1);

Function is_valid_entry($inputData,$validData)
{
    $inputData_array = str_split($inputData);
    $validData_array = str_split($validData);

    $i = 0;

    while ($i < sizeof($inputData_array)) 
    {
        if (!in_array($inputData_array[$i],$validData_array)) 
        {
            return false;
        }
        $i++;
    }
    return true;
}

//User defined global variables go here 
$username = "";                                                         
$ID = "";                                                               
$errorMessage = "";                                                     
$valid_chars = "abcdefghijklmnopqrstuvwxyz                                  
                1234567890";                                        


session_start(); //start a session

if (isset($_POST['submit'])) {                                          //submit button has been clicked
    $username = $_POST['username'];                                     
    $username = trim($username);                                        //trim any white spaces in the input value
    $username = lcfirst($username);                                     //attempts to convert upper case to lower
    $username = htmlspecialchars($username);                            //convert special chars to html rendering null
    $username = strip_tags($username);                                  //Strip tags from input string

    $ID = $_POST['ID'];                                                 //read in the value the user has entered for the password and assign to $ID
    $ID = htmlspecialchars($ID);                                        
    $ID = strip_tags($ID);                                              
    $ID = trim($ID);                                                    


    if (!is_numeric($ID)) {                                             //if $ID is not numeric redirect to login page
        $errorMessage = "Invalid username or password.";
        $_SESSION['error'] = $errorMessage;                             //sets the value of the 'errorMessage' session variable
        $_SESSION['login'] = "";                                        //set the value of the 'login' session variable to ''
                                                                        //redirect to login page & send error message
        header('Location: login.php');                                  

    } else if (!is_valid_entry($username,$valid_chars)) {               //check that user name is a valid char
        $errorMessage = "Invalid username or password";                 
        $_SESSION['error'] = errorMessage;                              //sets the value of the 'errorMessage' session variable
        $_SESSION['login'] = "";                                        //set the value of the 'login' session variable to ''
                                                                        //redirect to login page & send error message
        header('Location: login.php');                                  //redirect the user to the login page
    } else {                                                            //if user name & $id are both valid

                                                                        //now check if they are in the database
        $mySQL_Server = "127.0.0.1";                                    
        $db_userName = "root";                                      
        $db_password = "";                                              
        $database = "projectdatabase";                                  

        //connect to the database on the MySQL server & store the connection in $conn
        $conn = mysqli_connect($mySQL_Server, $db_userName, $db_password, $database);

        if (mysqli_connect_errno($conn))
        {
            print("Error connecting to MySQL database: " . mysqli_connect_error($conn));
        } else 
        {
            print("Connected to the MySQL database");
        }
            $SQL_Query = "SELECT * FROM user_information WHERE userName = '".$username."'"; 

            $result = mysqli_query($conn, $SQL_Query);                                                                      
            $num_rows = mysqli_num_rows($result);
            //below is the algorithm being used on the registration page
            //$hash = password_hash($ID, PASSWORD_BCRYPT, array('cost'=>10));

            if ($num_rows > 0)
            {                                                   //if there is match for the query within the database

                while($row = mysqli_fetch_assoc($result))       //attempts to retrieve the password associated with the username
                {
                    $row['password'];
                    $stored_hash = $row['password'];    
                }                                                   

                if(password_verify($ID, $stored_hash))
                {
                        $_SESSION['login'] = "1";                       
                        $_SESSION['username']= $username;               
                        header('Location: stats.php');              //login success

                } else {

                    $errorMessage = "$ID, $stored_hash";            //test to ensure is reaching this statement
                    $_SESSION['error'] = $errorMessage;             
                    $_SESSION['login'] = "";                        

                    header('Location: login.php');                  //redirect the user to the login page
                }

            } else {

                $errorMessage = "Login Unsuccessful";
                $_SESSION['error']=$errorMessage;               
                $_SESSION['login'] = "";                        

                header('Location: login.php');                      //redirect the user to the login page
            }

        mysqli_close($conn);
    }
}

?>

Community
  • 1
  • 1
Stuart_M65
  • 27
  • 5
  • Are you sure `$row['password'];` is set? Since we cannot see the top of your code I am going to assume that you have started the session properly. What sets `$username`? – Jay Blanchard May 06 '15 at 16:55
  • $username is set from clicking submit on the login form `$ID = $_POST['ID'];` which logs in correctly if I remove the password verify section. Also as far as I am aware it is setting properly as I have another test form which echo's the result of $row and returns the correct password associated with the username. – Stuart_M65 May 06 '15 at 17:05
  • Add error reporting to the top of your file(s) right after your opening ` – Jay Blanchard May 06 '15 at 17:45
  • @JayBlanchard I have added it right after each opening ` – Stuart_M65 May 06 '15 at 17:55
  • There is nothing obvious here.You're sure it is entering the conditional statement? – Jay Blanchard May 06 '15 at 17:57
  • Seems to be entering it alright, I edited the error message variable in the else section of the password verify statement and its returning the new error message. – Stuart_M65 May 06 '15 at 18:01
  • 1
    Are you *sure* the passwords match? If they don't that is the only thing which will get you to the error message. – Jay Blanchard May 06 '15 at 18:03
  • I will double check that now just to be 100% sure, `$stored_hash` is the hash inside the database password field and `$ID` is their entered password, is it possible the way I am trying to call the `password_verify` function? – Stuart_M65 May 06 '15 at 18:06
  • No, you're calling it correctly. – Jay Blanchard May 06 '15 at 18:07
  • I printed the `$stored_hash` variable in the statement error message, to check that it is entering the statement and which password it is returning which seemed to match exactly when I compared them against the database one – Stuart_M65 May 06 '15 at 18:11
  • 1
    I have no idea why you would run the password (`$ID`) through `htmlspecialchars()` or `strip_tags()` and why does it need to be numeric (just wondering)? Are you sure you're running the same functions on it before generating the hash and storing it to database? – Haprog May 06 '15 at 19:11
  • 2
    Also there is no need for the while loop when fetching the password hash from database since you're probably wanting to fetch only one row. You could also add "LIMIT 1" to the SQL query. – Haprog May 06 '15 at 19:15
  • @KariSöderholm running `$ID` through them was one of the things last semester the lecturer had said to include as was making it numeric, I was re-using some old PHP code in project I'm working on (non-commercial so not to worried about SQL injection in this case). I took them out just to check but still no luck. Also I'm not running it through the same functions on registration side. – Stuart_M65 May 06 '15 at 19:29

0 Answers0