tl;dr: I am wondering what the best way is to check a password when the client does not trust the server.

I know of two common ways servers can check if a user's password is correct:

  1. The server stores hash of password, the client sends the password, and the server hashes the password and compares hash with stored hash. If they match, the password is correct.
  2. The server stores the password in plaintext, and generates a salt which it combines with the password and hashes, and then sends the salt to the client. The client hashes the password and salt, and sends that hash back. The server compares the two hashes and if they match, the password is correct.

However, both these methods require that the client trusts the server, and the first one requires that the connection be secure (while the second one obviously doesn't).

I have thought of a way, but I don't know if it's good since I don't have a background in cryptography, I don't know what contortions can compromise security.

The method is that when the client creates an account, the client generates an RSA key pair from its password by seeding the random number generator with the hash of the password, and sends the public key to the server. Later, when the server wants to check if a user has the correct password, it can generate some data and send it to the client to sign. The client responds with the signature and the server can verify the signature, and if it's valid then the client had the correct password.

This way, the server never gets to see the client's password.

This might be a stupid way of doing it. However, I'd like to know what the common way of doing this is, and if there isn't a common one, what the security experts here think of the way I outlined. As I said, I know only of cryptography what I have learned for web development, which is laughable, so I might have missed something obvious.

Additional info

I know that you can just generate an RSA key pair and store a file that contains the key on your computer, like what you can do for SSH logins, however it requires you to store your key somewhere, and if the computer is seized then your password is compromised. The method I am looking for should require just a password besides the username.


2 Answers 2


Some variants of Password Authenticated Key Exchange (PAKE) allow for mutual authentication using a password; also take a look at Zero Knowledge Password Proofs. Here the server still has the user's password (created during account setup), but during key exchange the client doesn't give the server the password, rather the client and the server run a protocol that proves possession of the password and (in the case of PAKE) establishes a shared symmetric key.

Section 4.2 and 4.3 of the tcpcrypt paper give a useful intro to a couple of protocols (though it does rely on a concept introduced in the rest of tcpcrypt, namely the session ID).

Your proposed method provides authentication of the client to the server, but not the server to the client (c.f. the Internet PKI or the above protocols, which attempt to authenticate servers to clients as well). It is also vulnerable to offline password guessing - given a single example signature over the challenge data, an attacker can go through a password list, generating the key pair and seeing if it matches the example signature.

  • Thanks. With my method, couldn't the client verify who the server was by just doing the same thing, have the server generate an RSA key pair and send the client the public key, and the client would send the server data to sign, etc?
    – Jecko
    Jun 11, 2013 at 20:40
  • Yes, modifying the approach described in the question to be symmetric would give you mutual authentication.
    – Michael
    Jun 11, 2013 at 20:41
  • Why don't all websites use this scheme or one like it? It seems to have blanket superiority over sending the password to the server and hashing it there.
    – Jecko
    Jun 14, 2013 at 18:10
  • It's a UI / legacy problem. A website could deliver some javascript over TLS that implemented such a protocol but there are problems. Better, browsers could implement the necessary the protocol and UI elements needed to allow users to be able to differentiate between secure password entry and insecure entry, but it's a hard problem to solve and browser developers evidently have decided there is more value to be had working on something else (for now).
    – Michael
    Jun 14, 2013 at 19:19
  • 1
    It doesn't meet the property of requiring interaction with the a genuine party to be able to brute force guess the password - given a single example signature over the challenge data, an attacker can go through a password list, generating the key pair and seeing if it matches the example signature.
    – Michael
    Jun 15, 2013 at 9:55

One of the coolest methods I've seen for something like this is Bank of America's SiteKey. The way it works:

  1. You select an image from their non-published database. (this is stored)
  2. Then you provide them with a custom description for the image. (this is also stored)

This combination is called their SiteKey. Before entering your password they show you the SiteKey for verification. If it's what you entered when you setup the account, then you should be able to trust the server, because anyone exploiting the server would have to have the images from their image library. Their database of users, passwords, and SiteKey match-ups, and present those in a method that looks authentic.

If it's not, then you would not enter your password.

A potential problem outside of banking implementation is this one is so flashy, that if someone cached your session they could pull out the image and the sitekey if they were directly targeting you. Likely they would have used other bits from your session to pull money directly from your account though (or transferred it somewhere else). They have precautions for transferring funds to corporate accounts from private accounts though.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .