0

I have a problem. my hashed password values are not matching when retrieving salt value from database.

Register.php

  1. User enters username and password.
  2. Collect the username and password through POST.
  3. Generate a random salt value Add the salt value onto the end of the password value(entered by user). And hash the full value.
  4. Insert username, salt,hashedpassword and original password into database (just for testing)

    if (isset($_POST["usernameReg"]) && isset($_POST["passwordReg"])){
     // filter everything but numbers and letters
    $username = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["usernameReg"]); 
    $password = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["passwordReg"]); 
    
    $salt = openssl_random_pseudo_bytes(1024);
    
    $hashedPassword = hash('sha256', $password.$salt);
    //$hashedPassword1 = hash('sha256', $password);
    
    $query = "INSERT INTO users (username, salt, hashedPassword, password) VALUES (:username, :salt, :hashedPassword, :password)";
    
    $statement = $pdoConnection->prepare($query);
    $statement->bindValue(':username', $username, PDO::PARAM_STR);
    $statement->bindValue(':salt', $salt, PDO::PARAM_STR);
    $statement->bindValue(':hashedPassword', $hashedPassword, PDO::PARAM_STR);
    $statement->bindValue(':password', $password, PDO::PARAM_STR);
    $statement->execute();
    

    }

login.php

  1. User enters username and password.
  2. Collect the username and password through POST.
  3. Check the username exists in the database.
  4. Get the salt value for that username from the database and add it to the end of the password entered by the user in the login form. Hash this value and store it into $_SESSION["newHashedValue”] variable.(for testing)
  5. Retrieve the original hashedValue from the database. Store it in $_SESSION[" dbHashedValue”] and compare values.
  6. If the values match then we know the login password is correct. Problem: these values do not match and they should because im entering the same login details.

    if (isset($_POST["username"]) && isset($_POST["password"])){ $username = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["username"]); $password = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["password"]);

        //check if this username and password exist in our database and are therefore valid
        $query = "SELECT * FROM users WHERE username=:username LIMIT 1";
    
        $statement = $pdoConnection->prepare($query);
        $statement->bindValue(':username', $username, PDO::PARAM_STR);
        $statement->execute();
        $statement->setFetchMode(PDO::FETCH_ASSOC);
    
        while($row = $statement->fetch()){
            $saltPassword = $password.$row["salt"];
            $newHashedValue = hash('sha256', $saltPassword);
            $dbHashedValue = $row["hashedPassword"];
            //these two values are not matching but they should match
            $_SESSION["newHashedValue"] = $newHashedValue;
            $_SESSION["dbHashedValue"] = $dbHashedValue;
        }
    

    }

stored in database

Sarah
  • 1,943
  • 2
  • 24
  • 39
  • That should be impossible. Can you please check if the columns `hashedPassword` and `salt` are long enough to store your information? Maybe your salt or hash are being cut off at one point which would ruin everything. Keep in mind `salt` should be of length 2048 and not 1024. – Cârnăciov Feb 26 '16 at 16:22
  • How are your database columns set up? Is there enough room to store the full hash? – Gavin Feb 26 '16 at 16:24
  • 1
    Just use [`password_hash`](https://secure.php.net/manual/en/function.password-hash.php) and [`password_verify`](https://secure.php.net/manual/en/function.password-verify.php). – Alexander O'Mara Feb 26 '16 at 16:26
  • Thanks for pointing that out.. my hash field is varchar 200.. how big should the salt field be? I have it as varchar 64.. is that too short? – Sarah Feb 26 '16 at 16:26
  • @aron9forever thanks .. that is probably my mistake. my salt field is varchar 64... what should it be? – Sarah Feb 26 '16 at 16:27
  • @Sarah the `salt` field is the issue, it should be varchar 2048. Either that or replace `$salt = openssl_random_pseudo_bytes(1024);` with `$salt = openssl_random_pseudo_bytes(32);` – Cârnăciov Feb 26 '16 at 16:27
  • @aron9forever thanks a million. I am only learning how salts work so it was a silly mistake. thank you :) – Sarah Feb 26 '16 at 16:28
  • @aron9forever ah ok I might do that instead . $salt = openssl_random_pseudo_bytes(32); thank you – Sarah Feb 26 '16 at 16:29
  • @Sarah posted as a full answer then, please mark it as correct if it solved your issue. – Cârnăciov Feb 26 '16 at 16:30
  • @Alexander O'Mara thanks for that. I was just investigating password_hash and password_verify .. I read they are supported from php 5.5 upwards. is that true? My hosting providers are currently using 5.4.45 so i'm not sure it will be compatible? – Sarah Feb 26 '16 at 20:55
  • 1
    @Sarah Yes, but PHP 5.4 is already end-of-life. There are polyfills for obsolete PHP versions though, here's one: https://github.com/ircmaxell/password_compat – Alexander O'Mara Feb 26 '16 at 20:58
  • @Alexander O'Mara thanks. i will check that out.. so is php 5.4 not secure at all or does it just not work with password_verify etc? .. eg do you think my code in this question is secure enough even in php 5.4? – Sarah Feb 26 '16 at 21:35
  • 1
    @Sarah PHP 5.4 isn't currently receiving security updates, I don't know if there are presently any unpatch vulnerabilities, but I generally don't recommend using obsolete versions of PHP. As for which is otherwise more-secure, see [SHA512 vs. Blowfish and Bcrypt \[closed\]](http://stackoverflow.com/questions/1561174/sha512-vs-blowfish-and-bcrypt) (`password_hash` presently uses Bcrypt with a cost of 10). – Alexander O'Mara Feb 26 '16 at 22:12
  • @Alexander O'Mara ok.. thanks a lot for the info :) I will get in touch with my hosting company about an update :) – Sarah Feb 26 '16 at 23:55

1 Answers1

2
$salt = openssl_random_pseudo_bytes(1024); //will generate 2048 chars since a character is half a byte.

Will generate a string of 2048 characters. Therefore the solution is to either increase the size of your salt column to 2048 which is sort of overkill, or generate 32 bytes which will be 64 characters.

$salt = openssl_random_pseudo_bytes(32); //will generate 64 chars

More info on the function here http://php.net/manual/en/function.openssl-random-pseudo-bytes.php

The sha256 hash is of length 64 so the hashedPassword column should be of length 64.(as the name suggests, 256 bits = 32bytes = 64 characters)

Cârnăciov
  • 1,169
  • 1
  • 12
  • 24