views:

56

answers:

4

I have a very basic logon system, that authenticates users by the means of a user table in a mysql database with php.

can someone explain what the point of hashing passwords it, how to do it with php, and what is actually stored in the database.

Thanks

A: 

A hash is a "one-way function". You feed in a password and get an approximately unique output that cannot be (computationally feasibly) converted back into the real password. Depending on the hash, it will look different. For instance, with sha1 (http://php.net/manual/en/function.sha1.php) you will always get a string 20 bytes long.

The benefit is that the real password is never stored in plaintext. To verify the user's password, you just compute the hash on the supposed password and compare it to the stored hash. If somebody gets a hold of your password database, they still don't have the actual passwords.

Jonathan
but for any dictionary word google will invert the hash for you...
mvds
@mvds can you explain this ?
Chris
Well, you can easily find a big list of common passwords. It's trivial to write a program to compute a hash on all of them, and then compare those hashes against the password database. This is only relevant, of course, when somebody has access to the hashed passwords. Also, it can be effectively prevented by using a salt as mentioned in another post.
Jonathan
yes, if I tell you I hash my passwords using `md5($password)`, and my hash is `08b5411f848a2581a41672a759c87380`, can you tell me what my password is?
mvds
@Jonathan: you don't have to do these things yourself anymore, they are out there and indexed for free.
mvds
That hash returned some unexpected results by the way: user tables!
mvds
@mvds yea its monitorhttp://md5decryption.com/
TechplexEngineer
Correct, but you don't need md5decryption.com for that, google will do just fine.
mvds
+1  A: 

Say someone breaks into your system (or finds a loophole in your sql queries) then you don't want them to know all passwords.

So you hash them before storing them. So you can check if the password is ok, but not deduce the password from the hash.

Unless you use a weak hash. If you would only sha1($password) then you will find putting the hash of often-used passwords into google gives the password in under 0.1 sec.* (but otherwise you could also find rainbow tables for all kinds of hashes)

So you want to add a "salt", that means, you generate some garbage value:

$salt = rand().rand().rand();

and then store

$hash = $salt."-".sha1($salt.$password);

on checking, you know the salt and you can check if the password is right, but knowing the hash and salt makes it still hard to recover the password. (unless you have a rainbow table which includes the salt, of course)

* this needs some explanation: I once took a large user table and found some hashes to appear multiple times. I googled the most-occurring one and it reversed to computer

mvds
"MD5 should be considered cryptographically broken and unsuitable for further use." http://www.kb.cert.org/vuls/id/836068
webbiedave
good point, `s/md5/sha1/g`
mvds
`rand()` is not cryptographically secure. also the salt should be a separate column, thats bad db design.
Rook
good point, `s/rand/mt_rand/g`
mvds
So if the hacker knows what the salt is, doesn't that completely destroy the purpose of salting?
TechplexEngineer
@The Rook: Even if I would agree, it's a little beside the point here. (and frankly, I don't agree, because I want to keep the password salt+hash a nice, "atomic" chunk of data wherever I take it. The salt and hash are worthless when separate, I only pack/unpack them when needed, the rest of the system just sees it as one string)
mvds
@TechplexEngineer it doesn't destroy the purpose. You salt your passwords to make it more difficult. You lock your doors at home to deter petty theft, but determined thieves won't be foiled by something like a door being locked
Robert
@Techplex: no, because if he would know the salt is, say, `7236817` then he effectively has to reverse the hash of `7236817your_password`, which will be less likely to occur in a rainbow table. Besides, a brute-force on all your user accounts will mean that the attacker has to hash every password he tries for every single salt encountered. So just make the salt long and put more than just `0-9` in there!
mvds
@mvds I guess that means your salt is alpha-numeric or maybe even just base16. A salt should be base256 (a full byte per char), you want the most entropy to string length ratio.
Rook
@Rock well, I would keep it with alphanumeric (or the OP will come back later with mysql binary data issues), but anyway the example with `rand()` was easiest to get the message across.
mvds
A: 

Noone has said why yet, so let me: most users are idiots and use the same password everywhere. You don't want a hacker to break into your system, grab the passwords then go and hack your users accounts everywhere else.

James
This is *so* not the point. The point is that if *your* database was stolen, *you* have to tell all your 1 million users that their passwords were stolen and that they must change it. They won't, so there will be some lunatic having access to accounts of 900k users on your system. So *you* have the biggest problem.
mvds
ah that makes sense thanks!
TechplexEngineer
kinda a good point @mvds, except that you can force your users to change passwords to get round that problem - it won't make you popular but it will work. But mine is still a good point to. Sure, if a hackers hacks other people's sites using passwords stolen from yours it's not really your problem - but do you think your (probably ex-)customers are going to see it that way?
James
Of course it depends. If you are a company, you can force 100% of your employees to change passwords, and they will not leave your company for that, true. If you are gmail/hotmail, you can force maybe 80% (assuming there's a lot of dead accounts), and some customers will leave you. If you are in a realm of less important stuff (social networking, gaming, forums, ...) you will most probably scare away 50% of your hard-earned users, since you will have to block accounts at some point, if the users don't respond to your request. Besides there is the problem that for that last case, you -- cont'd
mvds
-- probably don't have the proper mechanisms in place to really authenticate the user (secret question, actual birth date, ...). So the real risk is that you will just go out of business, not only because of the bad press.
mvds
A: 

can someone explain what the point of hashing passwords it,

The point of hashing passwords is for security purposes. If inserted as plain text, anyone that gets into your database will now have all of your users passwords. Another huge problem that stems with this is that it more than likely compromises the user everywhere, not just your site, as most people tend to use the same password everywhere.

how to do it with php, and what is actually stored in the database.

To use it in PHP you simply take a string, in this example $password = 'password'; and use the command sha1();. This will return something like d0be2dc421be4fcd0172e5afceea3970e2f3d940. It is also good practice to 'salt' passwords with your php script, so that the PHP script login script is required to successfully log in. Example:

<?php
    $salt1 = '2348SDasdf!^*__';
    $salt2 = '_a35j@*#(lsdf_';
    $password = sha1($salt1.$_POST['password'].$salt2); // d0be2dc421be4fcd0172e5afceea3970e2f3d940
?>

Then insert $password into your database. Upon logging in, you would need to salt the password given run it through sha1 in order for it to match the password in the database. You insert it into the database just like any other string, just make sure you have sufficient length granted to the column you're attempting to insert too.

Robert
This is not a really good answer, since the salt should be random. If the salting is constant, a brute force attack can crack passwords in parallel (i.e. per generated dictionary word, you calculate one hash and see if it matches one of the N users). But if you take a random salt, the hash needs to be calculated for every word *and* every users, adding a factor of N to the complexity.
mvds
In opposition of them knowing the salt by getting the database, both ways have their flaws. If it's random you'll have to store the salt somewhere, which if someone gets access to it will be just as easy to brute force.
Robert