HOWTO check passwords without sending them on the clear

Ángel Ortega

There is a simple method to check for a valid secret among two parts without sending it on the clear. This note explains how.

1. The server accepts a connection from the client and builds a random token (a text string). This string is sent to the client.

2. The client concatenates the random token to the password and feeds the resulting string to a cryptographically-secure hashing function like, for example, <strong>sha1</strong>. The client sends the hash to the server.

3. The server does the same operation (concatenating the random token to the password and hashing it) and compares the resulting hash with the one the client sent.

4. If they match, the password is accepted and the connection goes on, otherwise is dropped.

This algorithm is related to the "salt" in UNIX passwords and to the Diffie-Hellman algorithm.

Example:

The server will only accept connections from clients that know that the password is seeKriT.

A connection is started. The server creates a random token and sends it to the client:

OK 42d4df05

The client takes that, concatenates the password and feeds it to the sha1 hash engine:

sha1("42d4df05seeKriT") = b0f3bd621ba92f5c26261d36a8ffb9cb3b7b399d

That monstrosity is sent to the server:

b0f3bd621ba92f5c26261d36a8ffb9cb3b7b399d

The server then does the same concatenation + hashing:

sha1("42d4df05seeKriT") = b0f3bd621ba92f5c26261d36a8ffb9cb3b7b399d

and tests for the result. As they are the same, it assumes the connection is valid and returns

ACCPTD

or otherwise, if the hashes do not match, returns

FCKYOU

and closes the connection.