Unable to implement Client and Server Side Hashing (Validation problem) 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:


The user enters the password in my app.
The password is hashed on the client side using bcrypt (slow hashing algorithm).
The password hash travels via SSL to the server.
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?
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:


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.
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.
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.
The client now computes the slow hash using the password and the given parameters and sends the hash.
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.