Last week I explained how repeated hashing works. Our user Alice can prove that she knows her secret without exposing that secret, and the server can verify this without knowing what her secret is. The follow-up question is – how to make it practical?
My explanation last week told you how repeated hashing works, but that method would only be safe with a single server. If Alice was set up to use two servers, and she had authenticated ten times on one of them, then an attacker would know how to pretend to be her ten times on the other.
How?
Alice was initially set up for 1000 secure connections, so each server recorded:
Alice, n=1000, H1000(s).
The attacker saw Alice successfully respond to challenges of 999 down through 990 on server #1. Now the attacker can claim “I am Alice” to server #2 and send what he recorded as a valid response.
If the attacker only saw the most recent success, for a challenge of 990, he knows what H990(s) is. If he gets a challenge of 999 he simply sends the recorded H990(s) through nine more hash operations.
The trick is that the server must send two pieces of challenge: a number plus a “seed” string.
Let’s say that Alice must authenticate to three servers named
red,
blue, and
green.
Alice wants to have just one highly complex secret. Let’s say it’s:
j)F?qg87_DvP9@
Yes, she will need to generate and store that with something like
KeePassX.
Alice needs 1,000 authentication events. Each server will issue a challenge that is a number plus its name as the seed. So Alice sends her secret with the seed appended through a pipeline of 1,000 hash functions, setting up her record for each server:
We copy each one to the appropriate server.
Now the red server challenges her with “999, red” the first time, “998, red” the second, and so on. The blue and green servers are behind in the countdown, but the attacker can’t figure out how to respond to “999, blue” or “999, green” any more than he could respond to the next challenge from the red one.
Meanwhile Alice appends the specified seed to her secret and sends the result through the requested number of hash calculations.
It gets better yet. Alice can keep her one long-term secret indefinitely. When the red server has counted down to single-digit numbers, we can change its seed for Alice to “red2”. Alice calculates the new H1000(s,red2) and uploads it, and she can safely authenticate another 1,000 times.
We human’s can’t accurately type hash outputs like this:
0x5ff305be9ead01f4a3bd12a776bf6b48fc875533
This isn’t a problem, as we don’t have to.
“Repeated hashing” is how a mathematician or computer scientist might describe this technology. S/KEY is a practical standard for getting it done. It is defined in RFC 2289.
That RFC describes how to represent binary patterns in 4-character strings that are words or at least are pronounceable, so humans can accurately type them in.
OPIE, which stands for One-Time Passwords In Everything, is a practical cross-platform software package that has been around for many years. It’s a fully compliant implementation of S/KEY, and as long as you’re talking S/KEY to S/KEY you don’t have to worry about the operating systems of the server versus the client. OPIE client code is available in a variety of languages running on a variety of platforms.
What makes this really practical today is the availability of smartphone apps like OTPDroid. That’s OTP as in “One-Time Password”.
Here is the result of sending a secret plus a seed of “red2” through a pipeline of 998 SHA-1 hash operations:
The hash output has been converted to words and word fragments so the user can enter them accurately.
…and 997:
There used to be an OPIE module in PAM, the Linux Pluggable Authentication Module system. Learning Tree’s Linux server administration course shows you how to configure authentication with PAM.
However, the Linux PAM OPIE project seems to have faded away. Cryptographic authentication within SSH is far safer. It should be hard to guess a password, but it will be astronomically harder to break RSA.
S/KEY is instead used for user authentication into web services, with the server side programmed in PHP, Python, Java, or other languages. Smart phones make it practical to use this technology.
Thank you for following along to my series. To learn more, check out this article from Linux Magazine for some practical pointers on adding S/KEY one-time passwords to your web-based services.
image sources