views:

57

answers:

1

Hi,

I am now creating a sha2 login form after researching and asking for help around online, I find the example code from this link below is quite useful and practical (I hope I am right!??), the only thing I don't understand is the way this programmer wrote the function and getting the salt value from the function.

http://hungred.com/useful-information/php-better-hashing-password/

define('SALT_LENGTH', 15);

function HashMe($phrase, &$salt = null)
{
    $pepper = '!@#$%^&*()_+=-{}][;";/?<>.,';

    if ($salt == '')
    {
        $salt = substr(hash('sha512',uniqid(rand(), true).$pepper.microtime()), 0, SALT_LENGTH);
    }
    else
    {
        $salt = substr($salt, 0, SALT_LENGTH);
    }

    return hash('sha512',$salt . $pepper .  $phrase);
}

what is the difference if I change the function to this?

function HashMe($phrase, $salt)  {..}

of course this function will fail, what is it for to have a '&' before $salt? is it necessary to have 'null' like this &$salt = null? what if I put '&$salt'?

and then, to get the salt value, you just can get it straight and put it the sql query like below,

$username = cleanMe($_POST('username'));
$password = cleanMe($_POST('password'));
$salt = '';
$hashed_password = HashMe($password, $salt);
$sqlquery = 'INSERT INTO  `usertable` ("username", "password", "salt") VALUES  ("'.$username.'", "'.$hashed_password .'", "'.$salt.'") WHERE 1';
..

how can I get the salt value from the function like this below before preparing the sql query,

$salt = "'".salt."'";
$username = "'".$username."'";
$hashed_password = "'".$hashed_password."'";

then,

$sqlquery = 'INSERT INTO  `usertable` ("username", "password", "salt") VALUES  ($username, $hashed_password, $salt) WHERE 1';

the reason I dont like/ want to have this - "'" in my sql query is that I have null value sometimes like $firstname = 'NULL'; and I want the row to 'tick' the empty field as null if the firstname is empty/ null.

besides, having "'" in my sql query, making me dizzy and difficult to debug when things gone wrong...

sorry, I have lots of questions in this thread!

thanks.

+3  A: 

Let's see if I can answer your questions one at a time.

First, you asked why function HashMe($phrase, $salt) fails, while function HashMe($phrase,&$salt = null) does not. This will become clear after explaining parts two and three.

Second, you asked why you need the & before $salt in your function declaration. What the & means is that you are passing the value by reference. Normally when you pass a value to a function, a copy of that value is created and you work on the copy. So for instance:

function addOne($number){
    $number = $number + 1;
}

$myNumber = 3;
addOne($myNumber);
echo $myNumber;

this code will output 3, not 4. This is because the function doesn't change $myNumber, it creates a copy of it and changes that copy. When you pass by reference, you tell it to work on the original number rather than create a copy. Therefore if we make this slight change:

function addOne(&$number){
    $number = $number + 1;
}

$myNumber = 3;
addOne($myNumber);
echo $myNumber;

Now our code outputs 4. The function passes $salt by reference because it changes the value of $salt. Therefore after the function has run you now have the new value of $salt.

As for why you need &$salt = null, that's auto-declaring the variable if you don't declare it yourself. Therefore if you want to just generate a random hash (with no means of recreating it since you don't know what salt was used) you can just call the function with HashMe("message to hash");. The = null means that if there was no second parameter, automatically set the second parameter to "null". Later in the code, however, it says that if the second parameter is "null", generate a random salt:

if ($salt == '')
{
    $salt = substr(hash('sha512',uniqid(rand(), true).$pepper.microtime()), 0, SALT_LENGTH);
}

Thus, if you call the function this way you will create a hash which you may never be able to reproduce.

For your fourth question you wanted to get the value of $salt for use in an SQL query. That's the beauty of pass by reference. Since the variable $salt was passed by reference, after the function has run you can just use $salt again and it will have the new value. One important thing to notice is that all the function does to change $salt is ensure that it is 15 character long. Anything longer is truncated, but anything shorter will remain untouched. For this reason if you store the (15 character) salt which is returned by the function, you can use it in the future and it won't change the salt again. So your SQL query should work perfectly.

$sqlquery = "INSERT INTO  `usertable` ('username', 'password', 'salt') VALUES  ($username, $hashed_password, $salt) WHERE 1";

Note that I swapped the double and single quotes from your original query. This is because in some versions of PHP variables will not be parsed in single quotes. For instance:

$secret = "Hello, there";
echo '$secret'; // "$secret"
echo "$secret"; // "Hello, there"
steven_desu
thank you so much in breaking down the explanation with details! thanks! now I understand the original code! :-)
lauthiamkok
Glad I could help =)
steven_desu
u did mate! :-))
lauthiamkok