password/login system in php

For a login system in php would this be a suitable outline of how it would work:

users types in username and password, clicks login button.

  1. Checks if user exists in database,
  2. if it does, then retrieve the salt for that user
  3. hash the password and salt (would this be done on the client or server side? I think client side would be better, but php is server side so how would you do this?)
  4. check value against value in database,
  5. if the values match then user has typed in correct password and they are logged in.

Answers


Checks if user exists in database, if it does then retrieve the salt for that user hash the password and salt

No. This means you are hitting your database twice.

hash the password and salt (would this be done on the client or server side? I think client side would be better

No. The point of hashing the password is so that if someone compromises your database, they can't (easily) find out what they need to send to your system (or other systems) to log in as that user.

If you hash the password before sending it to the server, then the attacker can bypass the JS and send the prehashed password read from the database to your system.

  1. User submits username and password
  2. Password is hashed with the standard salt for the system
  3. SELECT some,cols FROM your_users WHERE username=? and password=?
  4. Count the number of rows returned from the database.

Checks if user exists in database, if it does then retrieve the salt for that user hash the password and salt (would this be done on the client or server side? I think client side would be better, but php is server side so how would you do this?)

The important thing to remember is that you never ever trust the user which means where authentication is concerned you should do as much as possible on the server side. Give the user as little information as possible and don't trust them with anything.

In regards to your question, the obvious point is that there is far more data transfer involved if you let the user precompute the hash. Rather than the single request and response there are 3 requests and responses required. It also increases the requirements from a browser to a browser with JavaScript enabled. Depending on your audience a lot of users can have JavaScript disabled (usually via the NoScript plugin).

Regarding security, while allowing the the user to see the salt wouldn't effect the defense against rainbow tables, showing them how you combine the salt and the password does.

Brute force attempts through the web interface are not that much of an issue anyway as hopefully you would only allow 5 (or so) login attempts per username per hour. Knowing the salt and hashing algorithm doesn't help at all (It just reduces your sever load ;) ). However if they have the database and know how to combine the salt and the hash it becomes that much easier to do a brute force attack.

While security through obscurity is no real defence, it does make your system that much harder to break, so I would reccomend that you don't attempt to do hashing on the client side.


It has to be Server Side


You are on the right track, but let me help you improve your system.

Generate a strong random key and store it in a file above your document root:

/home/username/key
/home/username/public_html/login.php

The file should contain (pseudo) random binary data with as much strength as possible. 512-bits of random data should be quite okay.

Then generate a unique salt for each user in your system. This salt does not have to be stronger than 16-bits of random binary data.

Finally, the password hashes should be something like:

hash('sha256', $password . $salt . $key);

where the hash algorithm matters a lot. Do not use MD5 or SHA-1. Use the SHA-2 family, typically SHA-256 or SHA-512. Also, Whirlpool is a good choice.

If you want to improve your system even more, you could iteratively hash again and again like:

public static function hash($algorithm, $data, $iterations = 1, $rawOutput = false)
{
    if ($iterations < 1)
        throw new Exception('There must be at least one iteration.');

    while ($iterations--)
    {
        $data = hash($algorithm, $data, true);
    }

    return ($rawOutput ? (binary) $data : bin2hex($data));
}

Why such many moves?

  1. Check if user exists in database, with given salted hashed password
  2. if it does, then retrieve the user information

that's all

If you're talking of secure password transfer from client to the server - that's another story, you can refer to the HTTP digest authorization description for the schema. In short, it's client-side password hashing using random one-time token stored on the server side. OR SSL, of course


Need Your Help

Qt Translation lupdate and namespaces

c++ qt internationalization

While developing a Qt Application, I ran into a problem in using QTranslator. After a little research, I found out that the problem was with lupdate from Qt having problem with the

Creating recurring events mysql fullcalendar

events calendar fullcalendar recurring recurring-events

I'm using FullCalendar to create a calendar for my project.