3
votes

I'm looking for an established security mechanism to apply client side password hashing in addition to server side password hashing. The client is either a web app or a mobile app. The communication between client and server uses HTTPS. The server should use bcrypt or a similarly secure password hashing algorithm.

Now, I don't want to send the unencrypted password from the client to the server in order to prevent insider attacks against the user. I want to make sure that none of our admins is able to get the original password, since -- as we all know -- most people re-use their password on multiple web sites or use a password scheme to derive passwords that are easy to remember.

Additionally, I would like to implement an additional two-factor-layer of security into the authentication protocol that makes use of a secret stored on the client in order to strengthen the overall security even more.

Are there any published and validated mechanisms that can be used for this situation?

EDIT In my scenario, evil admins cannot control the code of the app. The server that is doing the authentication and that provides sensitive data is a REST server. The application code is delivered by a different server (for the web app) or via the AppStore (for the mobile app). And I am also thinking about scenarios where an attacker has only read-only access to an internal network segment that connects the HTTPS server with the application server. In most real world setups, SSL termination is done on a dedicated server.

1
Evil admin controls the code that hashes the password on the client. This won't work.Neil McGuigan
Be really careful when trying to do this. If you hash the user's input you can end up with some issues involving null bytes. See this article for more details. blog.ircmaxell.com/2015/03/…haxim

1 Answers

2
votes

In contrast to a website, your scenario with an app is well suited for client side hashing. The app already contains the code for calculating the hash, and the code cannot be intercepted/altered as this would be the case with JavaScript. Even more, you can relieve the server from the CPU intensive calculation.

These are the necessary steps for registration:

  1. On client side, calculate the hash of the password, using a slow hash function with a cost factor. Appropriate algorithms are BCrypt, PBKDF2 or SCrypt. Most libraries will generate a random salt on their own and include it in the resulting hash-value.
  2. Send the client-hash to the server (you already mentioned the SSL connection).
  3. On server side, again calculate a hash of the sent client-hash. This time you don't need a salt and you can use a fast algorithm like SHA-256. This is safe, because the client-hash is already a very strong "password", it is not possible to forge the client-hash out of the server-hash.
  4. Extract the parameters like salt, cost factor, and algorithm from the client-hash.
  5. Store the server-hash and the parameters (salt, …) in the database.

These are the steps for login:

  1. The client has to ask for the parameters (salt, …), stored in the database on the server.
  2. The client calculates the hash of the password with the same parameters as by the registration.
  3. Send the client-hash to the server.
  4. The server again hashes the client-hash with the fast algorithm and compares it with the stored hash in the database.

This is a bit more complex than sole server-side hashing, because you have to take care of storing the parameters (salt, …) separately.