2
$\begingroup$

I'm trying to implement hashing on both client and server Sides for my web/mobile Application.

  • On the client side, I implemented the slow hashing algorithm (bcrypt)

  • On the server side, I tried to use a fast hashing algorithm (MD5)

Here's what I did:

  1. The user enters the password in my app.
  2. The password is hashed on the client side using bcrypt (slow hashing algorithm).
  3. The password hash travels via SSL to the server.
  4. On the server side I use MD5 (fast hashing algorithm).

The problem here is: on the client side, as I mentioned already, I'm using bcrypt (with a random salt). So, every time the resulting hash is a different one.

Further hashing the resulting hash from the client ends up with a different one on the server side, since MD5 (without salt) produces a different server hash for different client hash.

So users are not able to log in.

How can I solve my problem? Which algorithm would be better suited for my problem here?

$\endgroup$
0

1 Answer 1

2
$\begingroup$

In my answer, I'll largely reproduce / use what is written in "Method to Protect Passwords in Databases for Web Applications" by Scott Contini, you definitely should read at least section 4 for the actual guidance and the whole paper for the background and the whys.

The paper has a more distinguished approach than you, but in principle does the same. The problem with the salt is solved by storing a per-user salt in the database and upon request hash(username||domain||per-user-salt) is computed by the server and served to the client as the salt.


Now for the procedure as outlined in section 4:

  1. Store the username, $H(s)$ and $v$ in your database upon registration / password change. $v$ is said per-user salt (which should be 128-bit random and regenerated upon password change), $H(s)$ is the fast hash of the slow hash.
    The salt is as described above. Additionally store a system-level secret $\sigma$ of the same properties as $v$, regenerate it occasionally.
  2. The client (the app) gets the username from the user (or from its storage). It now sends a request with said username to the server.
  3. The server looks the user up. If the user does not exist, $\sigma$ replaces $v$ in the salt computation. The salt and the (system-wide) parameters of the slow hash are sent.
  4. The client now computes the slow hash using the password and the given parameters and sends the hash.
  5. The server hashes the received result. The user is accepted if and only if the user exists in the database (you may make a new query here) and the hashes (from the DB and the computation) match.

Oh and you may want to use a more modern hash-function than MD5 here, because if it comes out that you use MD5 people (who have heard that "MD5 is broken") will come to you and complain about why you use a broken hash function. This might cost you users, because not everybody is going to care about the (correct) explanation that the "broken-ness" of MD5 doesn't matter in this particular case. So rather use a PR-friendly hash function like SHA-256.

$\endgroup$
3
  • $\begingroup$ Beware, those people might have heard of the length-extension attack against SHA-256 ;) $\endgroup$
    – Lery
    Commented Sep 8, 2017 at 13:07
  • $\begingroup$ @Lery that attach isn't a concern for password-auth situations $\endgroup$
    – swrobel
    Commented Jun 1, 2020 at 22:54
  • $\begingroup$ @swrobel No, it's not a problem since length-extension doesn't allow to break preimage resistance. But if you worry about what people who've heard it was weak against something might say about your design, then... I was just saying that SHA-256 was not that PR-friendly, maybe. $\endgroup$
    – Lery
    Commented Jun 4, 2020 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.