What to transfer? Password or its hash?

If you transfer the hash from the client, this affords no security benefit, and makes the hash pointless:
If a user can login by sending the hash to the server, then the hash is effectively the password.


If your authentication protocol is about sending to the server a password, or a hash of the password, with plain HTTP, then this is inherently very weak, for two reasons:

  • Someone spying on the line could record what the client sends. If just sending these bytes grants access, then the attacker could simply send them again. That's a replay attack. This issue is what @AviD alludes to in his answer. No amount of hashing will fix that. Some protocols try to correct this issue by including a "challenge" from the server (a random value, created anew for each connection), to be hashed together with the password on the client; that's what HTTP Digest authentication is about.

  • Even if the authentication worked, this is still plain HTTP, so whatever data will be sent afterwards will be vulnerable to eavesdropping and alterations by attackers. If the transport medium is unprotected, then the authentication will deter only the most unsophisticated of attackers. This is where HTTP Digest fails.

Therefore, you really need SSL (aka HTTPS), not only to convey the password or hash thereof, but also the remainder of the conversation between client and server.


I hereafter assume that the protocol is run within a SSL tunnel. You are right to want to use a slow hash like bcrypt or PBKDF2; note that a salt is also needed to prevent cost sharing (e.g. precomputed tables). Slow, salted hashing is used to cope with the intrinsic weakness of passwords. Now, you might want to offload some of the hashing effort on the client. This may work, but it raises some practical issues:

  • Since the password processing must include a salt, a new one for each password instance, then the salt must be conveyed to the client, so that the client may include it in the hashing it performs. This increases the protocol complexity: the client must first send the user name to the server, then the server must send back the salt, and (only then) can the client begin to hash the password. This is one more network roundtrip than with the usual "send user name and password as one POST request".

  • Slow hashing is about accepting to spend a lot of CPU on each password, so that the attacker also has to spend a lot of CPU on each password. But if the spent CPU is on the client, then we cannot raise it as much as we would like, because: 1) there are clients which have very little CPU (say some cheap smartphones or tablets), and 2) the Web context implies using Javascript, and Javascript performance is really bad when it comes to hashing (say at least 20 times slower than C code).

Therefore usual wisdom is that making part of the password hashing on the client is not worth the effort.


Both options are insecure.

Transferring the password will make your protocol plain-text. Transferring the hash, will make you vulnerable to replay attacks.

APOP is a login implementation for the POP protocol. This allow the protocol to keep the password private from any listeners on the network. A drawback to this is that both the client and the server need to know the password in plain text, as this is the shared secret. Prior to the that of the protocol both the client and the server have < password > The protocol communication is basically like this:

  1. Client connects to server and send a random token (T1)
  2. Server sends a random token (T2)
  3. Client send M = sha( T1 + T2 + < password: client's copy > ) to the server
  4. The server checks if sha( T1 + T2 + < password: server's copy > ) matches M (the hash just received).

Here, the server knows both the magic and the password, and is able to determine if the user knows the correct password without exposing it to any listeners.

The best practice would be to securely store the hashes in the database, and rely on encrypted channels.