PHP security sha2: &$salt = null?

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.

define('SALT_LENGTH', 15);
    
    function HashMe($phrase, &$salt = null)
    {
    	$pepper = '!@#$&#37;^&*()_+=-{}][;";/?<>.,';
    	
        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.

No, there is only understanding. What you’ve read is rubbish.

there are a few people suggesting that creating a separate database to store salts. I incline to this idea.

But thinking it a bit further, where should I keep this salt table? if my db is stolen, my users table and salts table are stolen at the same time. isn’t the matter of time the hacker will match the salts table with users’ and crack the password?

assume that I have a users table and a salts table like below,

usr_id usr_password
1         34444gfaggxxx...
2         3ddggg4gfaggxxx...
3         aaafgfaggxxx...
salt_id  salts     usr_id
4         fggxx... 1
5         ttgxx... 2
6         dfvxx... 3

can u see that the user id in the users table must always matches the user id in salts table. don’t u think the hacker can match them when they have these two tables in their hands?

then what’s the difference to have the salts stored in users table or a separate one?

if the solution is to keep the salts table in another database - but some servers just won’t let u to have two database and it is difficult to manage multiple databases for one website. and if the hacker can break into the server, I am sure they will take these two databases bcos they won’t be stupid I think.

thanks :rolleyes:

I agree that PDO/MySQLi are better solutions. The resources provided are in response to the code that the OP is currently working with.

While a salt is not the same things as a pin number, it’s just as bad to have the both of them together in the same database table. Is there a more useful metaphor that helps to explain the weakness of keeping encrypted passwords together in the same table as their hash?

thanks Paul for replying so quickly! :smiley:
I now understand it! :slight_smile:

It is impossible to store passwords in complete security. But you can improve the odds.

Typically the salt should be treated similar to other critical database config info.

What is seen above is where the username, encrypted password, and salt, are all stored in the same table of the database.

The salt is typically the same for all passwords within a table. You can store the salt in a similar place as for your other critical database config info.

You’re better off using a large number of characters for the salt. I’ve seen some people use 50 to 80 characters for the salt, which is a good idea.

What I mean is that storing the username, encrypted password, and the salt that’s used to encrypt that password, all together in the same table is a bad idea.

By moving the salt to where your other database config info is stored, at least you can then apply separate access rights to different tables.

That’s right, refer to the first sentence of this post.

I heard once that the only way to guarantee complete security of a computer system is to turn off all the power, disconnect all the cables, and surround it with concrete. Even then it’s still not guaranteed.

With your database security, all you can do is to make it that much harder for others to gain unauthorized access, without making it too hard for you to manage it.

I would also like to point out that if the salt is stored in the db on the same table as the password the lookup can be handled entirely in SQL itself


$sql = "SELECT * WHERE username = :username AND 
	password = MD5(CONCAT(MD5(:password), (
		SELECT salt FROM username WHERE username = :username
	))) AND active = 1";

$params = array(':username' => $_POST['username'], ':password' => $_POST['password'] );

$pdo->query($sql, $params);

PDO is used in this example since it handles any necessary escaping for you. The query above returns no result if the password is wrong.

Related topic - I use the same salt schema as vbulletin – md5(md5($password).$salt). I determine the salt by taking a random 5 char chunk from md5($password). Any other (better) schemes out there?

The difference is that the function will fail when provided with only a phrase.

The ampersand ensures that the $salt variable is passed by reference, which ensures that any and all changes to $salt remain once you return from the function.

Yes it is, for the assignment allows the function to be called with only the phrase and no salt.

If you do that then the function will fail when called without a salt, which breaks one of the intended uses for the function.

You should not store the salt value the same place as the password itself! Ideally you should not store your salt in the same database as your passwords. That’s like writing your pin number with a Sharpie directly on to your bank card. It is not a good idea.

The function does not provide any salt value. I think that you need to read up on what salt is and how it should be used.

Please look at the code examples on the mysql_query page that make use of [url=“http://php.net/manual/en/function.mysql-real-escape-string.php”]mysql_real_escape_string.

thanks hash! I’m using MySQLi. :smiley:

You should not store the salt value the same place as the password itself! Ideally you should not store your salt in the same database as your passwords. That’s like writing your pin number with a Sharpie directly on to your bank card. It is not a good idea.

This is NOTHING like writing your pin on the back of your bank card. The purpose of a salt is to protect users from dictionary attacks. Perhaps you can elaborate on how you can have your db of passwords hacked and still feel safe because your db of salts is untouched?

@OP, Paul got the rest right (re the function call), but re mysql_query/escape_string, forget about it. Use PDO/MySQLi prepared statements and be done with it.

Thanks Paul for explaining the function above and the link. its very useful! :slight_smile:

I would like to know where I should keep the salt then - some servers only allow you to have one database. besides, I won’t go for having 2 database for a single website - this can be very inconvenient when you want to move your website to another server, etc.

‘it’s just as bad to have the both of them together in the same database table.’ do you mean that this maybe safer to create table for salt? if so, if my database is stolen by a hacker, then this salt table cannot escape like the password table, isn’t it?

The same applies to having the salt kept in a different database - if both database are stolen - bcos they are kept in the same server, then the salt can never be safe, isn’t it?

thanks! :slight_smile:

The salt is typically the same for all passwords within a table.

If this is referring to code in this thread, I missed it, but if not, this is bad advice. Generate a salt per user, store it per user. The reason for this is that a potential attacker cannot generate a dictionary based on one salt, they must generate a dictionary per user. Generating dictionaries is not trivial in terms of time.

The reason for hashing a password is to protect the user from themselves (e.g. same password for facebook as bank account and nuclear launch code). With plain text, hacking my db gives access to the actual passwords; with a hash (such as md5) hacking the db gives almost the same access - rainbow tables have been generated that can reverse these hashes. With salt, new rainbow tables need to be generated after the db is hacked - this involves terabytes of data and takes weeks to run. With salt per user, this means that it takes weeks/terabytes to run per user, not just per site.

Bottom line: if your db is hacked, you have some rather more impressively worrying things to deal with than salts and stupid users. Creating a separate database to store salts is akin to protecting your farmhouse the same way a drug lord protects his lair.