My situation is this:

  • User credentials are stored on the server, bcrypt, random hashes.
  • I'm designing a REST API, so I'd like to keep this as stateless as possible!
  • The client is an Android/iPhone app.
  • All communication is done over HTTPS with newest TLS

Here are the scenarios in which I have to transmit a password over the wire:

  • User logs on
  • User changes his password (needs the old password for confirmation)
  • User changes his email (needs the current password for confirmation)

In all of these cases I'm wondering if there would be any added security benefits in additionally hashing/encrypting the password on the client side, before sending it over HTTPS to the server.

On a related note, since the passwords are stored as hashes on the server, how would I even go about implementing an additional client side hashing/encryption schema that yields some form of the original password on the server, so that I can compare it to the stored hash?


When you hash passwords on the client, the shared secret between client and server is no longer the cleartext password but the hash of the cleartext password. Your password is no longer monkey, your password is now $2a$04$RuNMmxnNakaesRjxjI3IAO70b2zK8lb5eRLb./huDLJ0OkWC0ikGm (bcrypt hash of "monkey"). The server would then hash this hash again and compare it to the hash-hash it already has in the database for that user-account.

So anyone who somehow obtains the client-calculated hash can compromise your user account.

The only advantage you have in this scheme is that the server is never aware of the user's cleartext password, not even in memory. This makes it provably impossible for the server to steal the cleartext passwords, even if it had malicious intentions.

Keep in mind that this scheme requires that the client always uses the same salt for hashing the same password. Otherwise re-hashing the hash on the server-side won't yield the same result. But you can use different salts on different clients and you can change the salt when you change the cleartext password.

| improve this answer | |
  • Your first point would only be the case if the hash that I store in the DB would equal the hash that is generated on the client side. Is there no way to have some sort of derived keys that work for comparing but aren't actually the same? – Lukas Knuth Jan 26 '18 at 10:15
  • @LukasKnuth The server would store hashes of hashes. I edited the answer to make that clear. – Philipp Jan 26 '18 at 10:17
  • Sounds like very little gain for the additional complexity. I think I'm going to stick with just HTTPS. Thanks! – Lukas Knuth Jan 26 '18 at 10:48
  • Not just little gain, but potential risk. The extra complexity in JavaScript means that users who do not have JavaScript enabled will be unable to log in. Users with very old computers may be forced to wait a long time for the password to submit. When the password absolutely must not be known by the server, there are other dedicated protocols that would be better than a homebrew "hash the hash" setup. – forest Jan 26 '18 at 14:30
  • @forest When you have a good example for such a dedicated protocol, then you might want to explain it in a separate answer. Btw: The question says this is about an Android/iPhone app, not a web application. – Philipp Jan 26 '18 at 14:36

Your Answer

