[clug] A Question About Password Handling and Authentication Mechanisms

Tony Lewis tony at lewistribe.com
Tue Nov 25 03:43:09 MST 2014

Ooh goodie, one of my favourite topics.

On 25/11/14 16:36, jm wrote:
> I've been meaning to look into/ask if there exists a challenge-response
> mechanism for passwords where the password doesn't have to be stored in
> plain text or in a recoverable form, ie it can be stored using a
> cryptographic hash. In fact, no where is the password stored or
> transmitted over a channel in a recoverable form. Does anyone know of
> such a beast?

Yes.  There is never ever ever justification for storing the password in 
plain text.  Also don't encrypt.

> I image it would operate something like this:
> Say you have a password in plain text, password. It is then stored on
> the server hashed, Hserver(password).

First, storing a plain hash is fraught with risk.  A good explanation: 

In short, if you store passwords just as a single hash, and your 
password database is compromised[0], expect passwords to be compromised 
at the rate of thousands per day (rubbery figure, I know) at least.  You 
need four weapons:
  * hash
  * unique salt per password
  * key stretching (variable multiple iterations of the hash)
  * password complexity (length, types of characters, checks against 
dictionary words)

Even then, your passwords will fall, but will be at a trickle, rather 
than a flood.  Being a trickle, you have time to implement your bulk 
password reset procedure that you diligently wrote for when this day came.

[0] Note, compromising the password database is a different risk than 
the one you're thinking of, but you must consider it.  This infographic 
will open your eyes as to why: 
(sorry, much JavaScript on that page, and it breaks NoScript's heart to 
have to temporarily allow it all)

>   Upon connection from a client a
> challenge is sent to the client and using the plain text password
> entered by the user the client carries out a one way calculation, call
> this hash Hclient(password, challenge) which is then sent to the server
> for verification. To do this the server performance another calculation
> on the hashed password, Verifier(stored_password, challenge), and
> compares it to the client supplied hash. In other words,
> 1)  Server stores password
>    stored_password = Hserver(password)
> 2) Client connects.
> 3) Server send challenge to client, challenge.
> 4) Client calculates response to challenge with a one-way function
>    response = Hclient(password, challenge)
> 5) Client sends response to server
> 6) Server calculated verifier code
>     verifier = Verifier(stored_password, challenge)

Here's where things break in this example.  Server has 
Hserver(password), and has no feasible way to calculate 
Hserver(password+challenge) because it cannot (easily) recover 'passsword'.

It could do Hserver(Hserver(password)+challenge) but that effectively 
treats Hserver(password) the secret (i.e. as good as the password) - an 
attacker would only need to know Hserver(password) from the database, 
plus intercept 'challenge' in order to authenticate.  If you use TLS 
then the channel is protected, and so this looks like it would work at 
first glance.

Oh yeah: they say that here: 

And OWASP have some stuff (though not enough on challenge-response): 


More information about the linux mailing list