Client side password hash versus plain text

1.4k views Asked by At

I'm putting together an android client (and possibly in the future iOS, web portal, etc) and php mysql server. Server side I am currently using the PHPass library to hash and salt the incoming passwords.

Should I make the client send plain text passwords over HTTPS/SSL or should the client do some form of hashing first. For example should every client simply sha1 (or some other algorithm) every outgoing password?

3

There are 3 answers

0
martinstoeckli On BEST ANSWER

Most websites will send the password plain-text over an encrypted connection SSL/HTTPS. Hashing the password client-side can be done, but the advantage is small and often client-side languages (JavaScrypt) are slow so you can calculate less rounds in the same time, what weakens the hash. In every case the server must calculate a hash as well to be safe.

The advantage is small, because if an attacker can do a ManInTheMiddle attack, he can also modify/remove the script (JS) which does the hashing. Only an encrypted connection with SSL/HTTPS can protect against a MITM attack, so you need SSL anyway.

In your case with an app, it looks slightly different. Because the user first has to install your software, there is no need to send a script to the client, so a MITM cannot modify this script. Moreover, the app can calculate the hash relatively fast (if it can run native code) and therefore can do enough rounds on client-side.

This is what i would do:

  1. For easiness send the password plain-text over an encrypted SSL/HTTPS connection and calculate the slow BCrypt hash server side, as you do now.
  2. Only if the load on the server grows too heavy, then you can move the calculation of the slow BCrypt hash to the client app. Still use HTTPS to send the hash, and then calculate an additional fast hash (e.g. SHA-256) on the server. This is more complex, because you have to exchange and store the salt separately.
0
MvdD On

Another disadvantage of hashing passwords on the client is that you cannot change the hashing algorithm or iteration count without also having to update your clients.

For JavaScript clients that is not a problem, but you cannot easily guarantee that your users will be on the most recent version of your native client.

So I would stick with sending plain passwords over HTTPS.

0
mbakereth On

In the early days of HTTP, there was Digest authorization as an alternative to Basic authorization. Instead of the HTTP header

Authorization: Basic <credentials>

you would use

Authorization: Digest <credentials>

It was an algorithm that increased security by avoiding the password being sent as cleartext. This was in the days when TLS/SSL came at a performance cost so this was an alternative. However the algorithm meant the password had to be stored as cleartext on the server. So you had a choice of sending the password cleartext but having a hash on the server, or sending the password as a hash but having cleartext on the server.

Unsurprisingly, as martinstoeckli said in his answer, now that TLS/SSL is widespread and easy to implement, HTTPS is used instead. You can store the password as a hash on the server but not expose the plaintext password if it is intercepted by a MITM attacker.