2

I have a MySQL 'users' table with the following columns: uname , hash, salt and pwd. I'm testing a PHP log in page that uses this table to gain user access. I don't yet have the system setup to register users at the moment so testing by adding data manually to the table with the following.....

uname: 'testuser',
pwd: 'password'

the php function that deals with checking the password is below:

function checkPwd($uname, $pwd){
    // Get the hash and salt for this user:
    $q = "SELECT hash, salt FROM users WHERE uname = '".mysql_real_escape_string($uname)."';";
    $res = mysql_query($q) or die("Could not retrieve user login data " . mysql_error());
    $tmp = mysql_fetch_assoc($res);
    $hash = $tmp['hash'];
    $salt = $tmp['salt'];
    // Hash and salt $pwd so we can make a comparison:
    $hashedInput = sha1($salt . $pwd);
    if($hash == $hashedInput) return true; // Return true if the hashed and salted $pwd matches DB entry
    return false;
}

Its not working obviously, the thing is I'm not really understanding the hash and salt way of doing things. How can I test my log in page keeping things secure with the function above. Do I have to enter anything in the salt and hash fields?

Fabio
  • 23,183
  • 12
  • 55
  • 64
davidjones
  • 67
  • 5
  • 2
    There's no point to storing the salt in your users table. If it's compromised, you're giving away the key to unlocking the hash. – Steven Moseley Jun 09 '13 at 20:29
  • PS - your code looks fine. I would venture to guess that the record was created wrong. – Steven Moseley Jun 09 '13 at 20:31
  • 1
    @StevenMoseley where do you store the salt? –  Jun 09 '13 at 20:41
  • 7
    Salt is not a secret information. It does not compromise the hashed password in any way if it's revealed. See http://stackoverflow.com/questions/213380/the-necessity-of-hiding-the-salt-for-a-hash – Ondřej Mirtes Jun 09 '13 at 20:43
  • 2
    @StevenMoseley Whoever told you that should read about what a salt is / does. – PeeHaa Jun 09 '13 at 21:02
  • @davidjones You should really consider using a hashing algorithm which is more suited for hashing passwords. What you currently have can be brute forced which speeds that make it trivial to brute force most passwords. You may want to use the following library to make it easy to correctly implement hashing of passwords: https://github.com/ircmaxell/password_compat – PeeHaa Jun 09 '13 at 21:07
  • @PeeHaa - I guess that depends on the complexity of the salt. A rainbow table, if big enough, could cover all word + salt combinations. Unhash a value, subtract the salt, and you've cracked the password data. – Steven Moseley Jun 09 '13 at 21:58
  • 1
    The salt was never meant to be private. The hash should be secure even when the salt is known. – PeeHaa Jun 09 '13 at 22:00
  • @PeeHaa埽 - Did you read my post? – Steven Moseley Jun 09 '13 at 22:52

4 Answers4

3

The purpose of using a cryptographic hash function is that the values created by those functions are not reversible. So if someone has the hash of a password, there is no feasible way determining the password other than brute-forcing it.

However, there are some techniques that can subvert brute-forcing by making a time/space tradeoff using precomputed lookup tables. These can be simple lookup tables of already known hash → password pairs. Or an extended type of such a lookup table, a so called Rainbow table.

This is where the salt comes in. It is used to add additionally entropy to the user’s passwords so that each input to the hash function is unique and thus creating a unique hash as well: password will most certainly be already in the lookup table, however, xi2B9LMweH/jM8Khxedls+password certainly won’t. And due to the way Rainbow tables are constructed, an attacker would need to construct one Rainbow table for each unique salt.

Note that the purpose of a salt is only to defeat such lookup table attacks. One can still do a dictionary attack if the salt is known, or a brute-force attack anyway. If the password is bad, it can still be guessed or brute-forced.

Now as for the implementation part, it’s better not to reinvent the wheel. So have a look at Secure hash and salt for PHP passwords and How do you use bcrypt for hashing passwords in PHP?.

Community
  • 1
  • 1
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • 1
    The salt is not just for additional entropy: it's to prevent rainbow table attacks. If one just stores hashed passwords in the database, then an attacker can build a table of pre-computed hashes for millions of possible passwords. – Lee Daniel Crocker Jun 09 '13 at 22:10
  • @LeeDanielCrocker That’s what I wrote. But if the salt is not long enough, chances are that even the salt+password combination may still be found. – Gumbo Jun 10 '13 at 04:40
0

I don't yet have the system setup to register users at the moment so testing by adding data manually to the table with the following...Its not working obviously,

What about it is not working? For your function to work you need to insert a value into hash that matches your salting method (the sha1 line).

the thing is I'm not really understanding the hash and salt way of doing things.

The purpose of a salt is to make the resulting hash value "unpredictable". A hash is one way, but hackers use hash dictionaries to identify passwords with brute force (Rainbow table).

A salt can be stored in your database along with the hash - it doesn't need to be secret. However, it would be rather trivial for an attacker to regenerate their dictionaries knowing the salt. That's why it's better to use methods like Scrypt. Scrypt requires significant amounts of CPU time and memory to compute a single hash.

An Scrypt hash could be configured to take 100 ms per hash. This means you could generate 10 hashes per second. Regular hashing methods, like SHA1, are built for speed. For example: With Bitcoin mining (which uses hashing) you can produce 5,000 Mega-Hashes-Per-Second with hardware for as little as $300. GPU's are also good at computing hashes. Methods like Scrypt are ideal for protecting passwords because they are hard to brute force.

How can I test my log in page keeping things secure with the function above. Do I have to enter anything in the salt and hash fields?

Yes you need to enter a value into the hash column. It seems like you need to do more work before you can test any logins.

Since you are unfamiliar with these topics, I would highly suggest using a common PHP framework that would handle these kinds of things for you. At the very least examine how these frameworks implement authentication. Security stack exchange is also a good resource.

Luke
  • 13,678
  • 7
  • 45
  • 79
-1

You only need "salt" and "password", the role of Salt is to create a random string value to use it like a public key to crypt the password with it.

For Example: $salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);

Now you can crypt your password with this Salt : $pwd = sha1($salt . $POST['pwd']); and then you save $pwd and $salt in the Database.

Now if you want to check for the login in: you do a SELECT query for a unique value (email, username) from the Database, then you crypt the entered password by the solt and test.

Edit:

For the Salt line: we create a random value for the uniqid (php.net/manual/fr/function.uniqid.php) between any couple of numbers you like I choose 16 and 36, Then sha1 to make it stronger and finally we clean up our Salt with php.net/manual/fr/function.base-convert.php

Hope it help.

  • You might want to go into explaining exactly what the `$salt` line does. +1 btw! – pattyd Jun 09 '13 at 20:57
  • For the Salt line: we create a random value between any couple of numbers you like I choose 16 and 36, then you create a uniqid for it. http://php.net/manual/fr/function.uniqid.php Then sha1 to make it stronger and finally we clean up our Salt with http://php.net/manual/fr/function.base-convert.php – mark marich Jun 09 '13 at 21:01
  • Why not add the explanation to the answer instead of a comment? – pattyd Jun 09 '13 at 21:05
  • Your answer implies (maybe that's not what you intended, but if so your should be clearer) that password can be stored in the database. that's the worst possible thing to do. – Lee Daniel Crocker Jun 09 '13 at 22:12
-1

Standard password security method is this:

Your server-side database should store two columns for each user: username and hash. If you want to use a separate salt for each user, then it can be stored as well. It's simpler to have a single salt for the site and include the username in the hash. If you don't want to include the username in the hash, then a separate salt for each user is recommended (it can be computed from the username and something site-specific if desired or cah just be random).

Most important point: passwords should NEVER be stored in a database, ever.

When the user signs up and chooses a password, build a string from the password + salt + username (or password + unique salt if you're going that route), then run this through a cryptographically secure hash function. MD5 is outdated and not very secure. SHA1 is probably fine. SHA256 would be better. Don't use a block cipher AES--these are not designed to be collision-resistant. Store the result of this hash in the table.

When the user logs in next time, take his username and password, add your salt, and compute the same hash function. Compare that to the one stored in the database. If they match, let her in. If you do this right, even if your database gets published, no one will be able to use it find anyone's password.

For extra security (probably overkill for now if you did the rest right, but good for future-proofing), use a hash function that is deliberately slow and complex to calculate. One way to do that is to simply iterate your hash function a few hundred times. Another is to use a memory-hard problem like scrypt.

The purpose of salting is to prevent "rainbow table" attacks, where potential attackers pre-compute hashes of billions of potential passwords rather than having to break them individually by brute force.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
  • sha1 is certainly not fine. It is (just like md5) a very fast algorithm. And using a slow hashing method is not overkill. Just compare sha1 with bcrypt in the following benchmark: http://hashcat.net/oclhashcat-plus/ – PeeHaa Jun 09 '13 at 22:46
  • A properly salted good hash--even a fast and parallelizable one like SHA1, is enough to force an attacker to use brute-force calculation for each user rather than being able to crack millions of passwords at once, making your site an unattractive target. That's pretty much your basic lock-on-the-door. A slow hash will make even a determined single-user brute force attack untenable. That's a steel-reinforced door. – Lee Daniel Crocker Jun 09 '13 at 22:53
  • The things with fast algorithms is that the brute forcing happens with millions and millions guesses per second. And this will only be more a month from now. – PeeHaa Jun 10 '13 at 08:25