An IETF standard addresses this problem; it's a system called OTP (for one-time password), which is based on S/Key, originally designed by Leslie Lamport and developed by Bellcore. While it allows a system to reliably authenticate a user, nothing on the system compromises the user's password if the system itself is compromised. The system has the ability to validate a user's current response but does not have the ability to predict what that user's next response will be.
OTP works by iteratively applying a cryptographically secure hash algorithm, starting with some initial seed value. A cryptographically secure hash algorithm is one that takes arbitrary-sized input and produces a much smaller output (something like a checksum) that has two special properties:
OTP works by starting with a seed (which is either provided by the user or generated randomly) and applying the chosen hash algorithm iteratively to get a sequence of keys. It applies the hash algorithm to the seed to get the first key, applies the hash algorithm to the first key to get the second key, applies the hash algorithm to the second key to get the third key, and so on. In order to validate a user, the system has to know some key (call it key number n) in the sequence. The system prompts the user for the previous key (key n-1), applies the hash algorithm to the user's answer (supposedly key n-1), and checks to see if the result is the key n that it knows. If the result is the key n, the user must have supplied the correct key n-1.
OTP can encode each key into a series of short words, so they are easier for a user to read and type, rather than simply generating a random-looking jumble of characters. Figure 21-1 shows how OTP works.
OTP isn't absolutely invulnerable to attack. Several attacks are possible:
To generate OTP keys on demand, the user needs a computer and a program to generate them. That user will have to provide the seed, the key number, and the cryptographic algorithm to be used, and the program will iterate the algorithm that many times to generate the key desired. The seed will have to be either entered by the user or read from a file on the computer. If the seed is entered by the user, the user would probably pick a seed the same way he or she would pick a password. Because users are notoriously poor at picking passwords, this makes the system subject to dictionary attacks, as we've described earlier. If the seed is read from a file, it can be more random (and therefore less guessable) than something the user would provide, but you have to worry about the risks -- probably low -- of the computer or file being stolen.
The alternative way to use OTP is to have the system generate and print a list of keys, enough keys to last the user for a reasonable period of time. In this case, the system randomly generates the initial seed, thus protecting itself against dictionary attacks. The printout should simply be a numbered list of keys, with no further identification or explanation. It is possible that the list could be stolen from a user, but you have to decide which you think is more likely: that the list will be stolen (and that the thief will know what it is and what to do with it), or that the user's session will be snooped on. If your users are generating keys on demand, they're probably using a seed that's subject to dictionary attack (otherwise, they would find it too hard to remember the seed); if one of their sessions is snooped on, their keys can be attacked.
We think that using a seed that's subject to dictionary attack is a greater risk than having a list of keys stolen, so we prefer using printed lists of keys to using keys generated on demand.
These systems use a variety of different ways to generate passwords. Some of them vary the password based on the time; some of them work their way through a one-time password list; and some of them use a challenge-response system, where the computer provides a challenge that the user types into the card, and the card provides a response for the user to give the computer.
Although the card-based systems have different strengths and weaknesses, they share the same general advantages and disadvantages. On the good side, they provide a guaranteed level of protection without requiring special reader hardware; on the bad side, there are considerable hardware costs for the cards, and you have to alter login software on the machines that you want to protect. Most authentication systems now contain support for the popular cards, but you will still need to install vendor libraries.
Card-based tokens are something of a hassle for their users, who have to carry the device, type things into it, read things from it, and protect a small and expensive object from being damaged or lost. Printed one-time password lists also present a certain number of user annoyances; there's nothing like turning over your list to discover that the print has worn off the next password you need.
Other hardware "something you have" options avoid many of these problems. For instance, smart cards, which put a small amount of information into a chip suitable for embedding in a credit card-sized object, are cheaper, easier to carry, and don't have keypads or readouts to fiddle with. The "secret encoder ring", which puts a small transmitter into a device that will pass for a chunky ring or a smallish ornament for your keys, is still a small, valuable object that you have to protect, but it doesn't have a keypad or a readout, and it's emotionally very satisfying. However, all of these options require reader hardware at the location where the user needs to authenticate. Smart card readers are becoming more prevalent, and smart cards are the most likely of these options to be practical for widespread use. While it's unlikely that Internet cafes and terminals in airports will provide smart card readers soon, it's relatively easy to get them for laptop computers.
You can also use hand-held computers like Palm Pilots and Windows CE machines to generate one-time passwords. It is very convenient for people who already have these devices, but it is not as secure as using devices that are designed to be security tokens. General-purpose hand-held devices do not provide hardware protection (they can be taken apart, so that people have access to the data). ost of them don't provide significant software protection, either; you can set a password, but it's generally easy to guess, and if you back the device up to a larger computer, the data is usually completely unprotected on the larger computer. If you use these devices for one-time passwords, you should consider adding additional access protection beyond that provided with the device.