0

I'm using this tutorial to help me when salting and hashing users passwords when they create an account and then bringing those passwords back and comparing then when the user enters the password to log in.

In this tut they have two functions that I am suppose to call.

create_hash()

and

validate_hash()

I have subsequently created another function myself that explodes the resulted so I can strip the salted string from the entire has.

function explode_hash($password) {
    return substr( $password, strrpos( $password, ':' ) + 1);
} 

So when I am inserting the data in the database it looks like this

INSERT INTO `users` (`id`, `email`, `passwd`, `passwdhash`)
VALUES
(1,'email@email.com','sha256:1000:mvhkKCAoLgCHb2/Ie0muPIRH0YISriOr:+Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS','+Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS'); 

Note that the last column contains the last part of the string in the third column.

So the last step is when logging in the user will enter their email and password and my system will get the hash from the DB (based on the email) and run it through the function called

validate_hash()

But the result is always false.

Would anyone have a couple minutes to look over these steps and attempt to understand the reason I'm not able to get produce a proper comparison?

Todd Jenk
  • 301
  • 1
  • 3
  • 13

4 Answers4

4

PHP 5.5 will have it's own functions password_hash() and password_verify() ready, to simplify generating BCrypt hashes. They work very similar to the functions you proposed. I recommend to use this excellent api, or it's compatibility pack for earlier PHP versions. The usage is very straightforward:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

As you already saw, the salt is included in the resulting hash-value and can be extracted from there to verify the password. The function above will extract this information (salt and cost factor) automatically from the hash-value, there is no need to store the salt separately.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87
2

I don't know what exactly is your problem but if you want to explode and validate hash it's very simple.

$str = 'sha256:1000:mvhkKCAoLgCHb2/Ie0muPIRH0YISriOr:+Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS'; //str from database
$params = explode(':', $str);
print_r($params);

It will print

 Array ( [0] => sha256 [1] => 1000 [2] => mvhkKCAoLgCHb2/Ie0muPIRH0YISriOr [3] => +Ak9g9KV1BPMIRjUorx3/auhU5dgH0lS )

now you can check $params[1] to get alorithm and other params to get proper values and use proper hashing function.

Hashing with salt looks like

hash_function('string_to_be_hashed' + 'unique random salt');

I don't know why you have 2 hashes in your mysql query instead of one. If you want hash to be salted function should return 1 hash instead of 2.

Robert
  • 19,800
  • 5
  • 55
  • 85
2

I took a quick look at the tutorial you posted. The usage should be pretty straight forward. You should not need to do any exploding or anything:

  1. Put the password you get from the user into create_hash($password) and store the result from that function in your database. No exploding, no anything.
  2. When the user no logs in and presents you with a password, just call validate_password($user_password, $password_from_database) and let the user in if the function returns true and deny entry otherwise.

The functions do all the splitting and exploding for you, you do not need to care for that.

korius
  • 359
  • 2
  • 6
-1

EDIT: DO NOT USE THIS SORT OF FUNCTION, EXPLANATION IN COMMENTS

I will leave this answer hear because I have seen many examples of this method, but never seen an explanation of why this is the wrong way to do it. Credit to ircmaxell for pointing this out

Original Post

I currently use these functions to hash and check my passwords

function createPassHash($uname, $pass){
    $salt = hash('sha256', uniqid(mt_rand(), true) . 'yourPersonalStringHere' . strtolower($uname));
    $hash = $salt . $pass;
    for ( $i = 0; $i < 100000; $i ++ ) {
        $hash = hash('sha256', $hash);
    }
    $hash = $salt . $hash;  
    return $hash;
}
function checkPassHash($input, $stored){
    $salt = substr($stored, 0, 64);
    $hash = $salt . $input;
    for ( $i = 0; $i < 100000; $i ++ ) {
        $hash = hash('sha256', $hash);
    }
    $hash = $salt . $hash;
    if ( $hash == $stored ) {
        return true;
    }
    else{
        return false;
    }
}

This adds an extra degree of entropy by using a random number, a secret string and the username hashed together as the salt. It is also recommended that the salt is at least as long as the hash, which this also ensures.

Adi Bradfield
  • 2,063
  • 1
  • 17
  • 27
  • -1 Please don't try to invent this yourself. This is nothing short of bad advice. This code contains multiple issues (first and formost that you're severely reducing the collision resistance of SHA256 by just doing an output-feedback into itself). [Just use a library](http://stackoverflow.com/a/17073604/338665). Cryptography is hard. And you *are* doing it wrong... – ircmaxell Jun 20 '13 at 14:22
  • @ircmaxell Hmm these functions are based off a very highly rated tutorial that I read a couple of years back. I have seen many methods extremely similar to this all over the web, including on that website that reverse hashes md5? Can't remember the name – Adi Bradfield Jun 20 '13 at 15:04
  • just because it's in a tutorial doesn't mean it's good. I'll show one major issue. You're feeding the output of SHA256 back into itself. That means if a collision is ever reached, it will collide for the rest of time. Which reduces the collision resistance significantly of SHA256 (this is the exact reason PBKDF1 is not used anymore). And yes, people keep doing this, because they don't understand cryptography and the principles behind *why* this is done. I was guilty of this for a long time as well. But today there's no reason **not** to just use a library. – ircmaxell Jun 20 '13 at 15:14
  • 1
    Okay, looks like I have quite a bit of code look back over then! Plus find a way to convert passwords over? How would you advise doing this? A new column in a database for the new password hashes. If a login is successful with the new method carry on as normal; if unsuccessful, try the old method. If thats successful convert the entered password using the new method and store it in the database? And keep this function until all active users have a 'new' password? – Adi Bradfield Jun 20 '13 at 15:23
  • To migrate: http://stackoverflow.com/questions/8841719/update-old-stored-md5-passwords-in-php-to-increase-security/8842142#8842142 – ircmaxell Jun 20 '13 at 15:26