A common way to prevent replay attacks when logging in is for the server to present a challenge (chall) and request a response in the form hash(chall+secret) where the secret is already known by the server, and can be determined from the user's password (e.g. password hash).

However, as far as I understand, that means that in the event of a server data breach, the data stored on the server (hashed password) is enough to complete the challenge, nullifying the reason why passwords are stored hashed in the first place.

How can this problem be solved?

  • add time and restrict usage with a threshold? – kelalaka Jan 22 at 16:57
  • passwords are "hashed" (and salted) to protect the password on other servers more so that to protect the password on the compromised server. – dandavis Jan 22 at 17:41

... the data stored on the server (hashed password) is enough to complete the challenge

What you describe is a known problem with digest authentication.

An alternative might be to use digital signatures. In this case the client creates a key pair, keeps the private key and publishes the public key. When the client should authenticate itself the server sends a challenge to the client and the client signs this challenge using its private key and sends the result back to the server. The server can verify that signature using the known public key and thus can be sure that the client owns the secret private key. This secret key gets only stored on the client side.

Basically the same mechanism is used with client certificates (mutual authentication) in TLS. And TLS also adds protection against man in the middle attacks and against sniffing or modifying the traffic. So it is probably better to just use TLS with client certificates instead of implementing this by your own.

Your Answer

