To securely store a password (e.g. in a database), you use a hashing algorithm designed for this purpose (designed to be slow, e.g. bcrypt), and you use a unique salt for each password.
This makes it hard/slow for an attacker with access to the database to recover passwords, because they can't use a rainbow table, and each brute force attempt takes more time than a simple md5 or sha1.

To securely authenticate a password over a plain text protocol (i.e. not SSL), the server sends the client a nonce, and the client combines the password, and the nonce (and maybe also a timestamp), runs a hashing algorithm on them, and transmits that hash to the server, who runs the same algorithm and compares. This avoids sending the password in plain text, and also makes replay attacks impossible, as long as the server can't be tricked into accepting the same nonce twice.

The problem is, for the authentication part of this the server needs to know the actual plaintext password. So you can't store them securely as in #1.

Now, the server could transmit the salt to the client, and the client could calculate the salted, hashed password first and then do #2. But then the salted-hashed password effectively becomes the plaintext password, and so you still don't really have #1.

@timoh But you should post that as part of an answer, I can't accept a comment as an answer.
– TimJul 12 '13 at 22:05

I fail to understand one thing: Why don't you use SSL? What is the requirement of using a non SSL solution? SSL provides a standardized secure solution to all of your requirements.
– void_inJul 12 '13 at 23:30

@void_in Well, I was thinking specifically of client side javascript in an environment where I didn't want to require https. But more generally, they were just two best practices that I didn't know how to marry. Also SSL seems kind of heavy weight for some things. But I'm certainly willing to admit it's a better solution in a lot of cases.
– TimJul 13 '13 at 3:16

3 Answers
3

Yes, this is possible. There are two algorithms described here which both avoids the need to store plaintext-equivalents on the server (while making it possible to authenticate without the need to send plaintext password over the wire).

A brief look over this algorithm suggests that it doesn't provide the degree of security you would expect. I probably wouldn't trust it for anything serious without having some trained cryptographers look over it more closely.
– tylerlJul 12 '13 at 22:44

Take a look at the Secure Remote Password protocol (wikipedia, Stanford). It uses a hash of the password (pick your favorite slow, salted hash) on the client side, but the server only gets a "verifier" derived from that hash by discrete exponentiation. The actual authentication takes place by an asymmetric key exchange using two random numbers (one client-generated, one server-generated), the hash (client-side only) and verifier (server-side). It's intended that the generated key be used to encrypt the rest of the session, but it could simply be verified and discarded.

Advantages:

The key exchange itself is effectively a zero-knowledge proof, meaning that a listener, man-in-the-middle, or server impostor gains no information about the password. If these were the only types of attack possible, a single-letter password would be sufficient for security.

An online dictionary attack (client impostor) can test only one password per attempt (early versions of the protocol allowed two).

If an attacker copies the server's database of verifiers, they can run an offline dictionary attack only by running each candidate password through the slow hash and exponentiation. They cannot use the verifier to impersonate the client.

As long as the server's verifier remains secret, the exchange transaction effectively verifies the server to the client (as well as the client to the server).

Correct me if i'm wrong but, you could keep the hashed password on the server. so its stored securely. and use the nonce as salt for authentication. One big thing that I see is that the server need not know the plaintext password this way. It can still prove that the person entered the correct password on their end, but by comparing hashes, not plaintext. The only place this password would be plaintext in my scenario would be the web broswer window before it was hashed (twice, once plain and once with known salt) and then sent over the wire not in plain text

Consider the scenario below

Client tries to connect

Server Generates nonce

Server sends nonce to client. hashes the hash again with nonce as salt. a hash that takes the hash of the password as input and the nonce as salt.

Client hashes pwd through same hash algorithym, generating the same hash that get stored on the server.

Client then does it's own individual hash same way the server did (a hash of the pwd's hash with nonce as salt)

Client transmits nonced hash to server.

Server accepts it as correct for that one authentication time and would never accept same nonced hash again

Someone breaks into the server and steals the password database. Now he has the hashed passwords of everyone. Now he tries to log in. The server sends him a nonce, he hashes the hash with the nonce, and logs in successful. In other words, the hash passwords are now all you need to authenticate. This defeats the point of hashing them. It effectively makes the hash password the real password, so it effectively makes the passwords stored in plain text.
– TimJul 12 '13 at 18:24

1

@Tim The main point of hashing the password is to protect the user's password (since they tend to be reused).
– Brendan LongJul 12 '13 at 19:19

3

@BrendanLong While that is one benefit of hashing passwords, ideally it also makes a stolen password database as useless as possible. Not only should you not be able to recover the user's password and login as them at some other site, you shouldn't be able to use the hashed password to directly login on the compromised site either. Ideally a lot of work (a brute force attack involving specialized hardware and software, and a lot of time) should be involved to make any use of stolen hashes.
– TimJul 12 '13 at 20:24