Article summary
Over a decade ago, my employer issued me an RSA SecurID token to protect their VPN. This little device had a six-digit LCD display that would roll over to a new random-looking number every minute. I had to add whatever it showed at the moment to my password in order to successfully authenticate.
Today, a lot of people use a similar (but open) system called TOTP, generally with an app like Google Authenticator, to prove their identity to cloud services. Here’s how it works.
One-Time Passwords
Eons ago (in Internet years), there were a number of competing standards for so-called “one-time passwords.” A user would have a series of passwords to authenticate with, and (as the name suggests) they’d only be able to use each password once. This protected against replay attacks, in which an attacker could capture a password as it was being transmitted to the server for verification, then re-use that password later.
A number of schemes were used to get the one-time passwords in the hands of users. Devices that could generate the one-time passwords were one option. Sometimes, a user would be given a printed list that they had to carry with them.
The HOTP standard would cryptographically derive one-time passwords from a shared key and a counter value. A counter would be maintained by both the server and the user’s client. The client would use its copy of the key and its counter to generate a value to send to the server. The server would check to see if it generated the same value with its own copy of the key and its counter.
Going from a key and counter to a password looks like this:
- The HMAC of the key concatenated with the counter is created.
- The four least-significant bits of the HMAC are used to create an offset.
- The offset is used to select 31 bits from the HMAC as the code.
- A number of least-significant digits from the decimal version of the code make up the password. (Six digits is common.)
Synchronization is a concern in a system like this. If the user thinks they’ve used more passwords than they actually have, they may use a higher counter value — and the server can peek ahead, using higher counter values, to see if it matches. Of course, if the server’s counter value is higher than the user’s, it can’t accept the password.
This system’s usability isn’t great. A user has to not only keep something around that can give them one-time passwords, they also have to keep track of which ones they’ve used.
Time-Based One-Time Passwords (TOTP)
Some years after HOTP, the TOTP standard was developed, replacing the counter (and the need to track it) with the ever-advancing wheels of time. TOTP drives Google Authenticator and many other compatible systems.
To make TOTP work with time, the counter is defined as the number of intervals that have passed since a reference point in time. Google-Authenticator-compatible TOTP systems standardized on thirty-second intervals and the Unix epoch. (SHA-1 is the standard, but TOTP also allows HMAC algorithms that aren’t SHA-1.)
This creates a much more user-friendly system. You’ve seen the authenticator software screens: for every one of your TOTP-protected systems, you see a six-digit number and an indicator for how long it will be until the next thirty-second window comes up. As long as your authenticator’s clock and the server’s clock stay mostly in sync (some small allowance is made for this), it’ll work great.
The setup experience is nice, too, as you can probably attest if you’ve ever pointed your phone’s camera at a QR code to set up your authenticator. There’s a special otpauth
URL scheme that encodes all the details needed to register a new secret. It looks like this:
otpauth://totp/user%40example.com?secret=ABCDEFGHIJKLMNOP
The picture looks pretty rosy from here. But there are still some problems to watch out for.
Risks of TOTP
In a world where we very carefully hash passwords to keep our users’ passwords unknown in case our user databases get stolen, it’s worth paying attention to how we store the TOTP key. Because time is public knowledge, anyone who gains access to the TOTP key we store on our server can clone the authenticator. They just need to load that secret into their own authenticator, be it a command-line tool or even the “real thing.” Unfortunately, we can’t hash the TOTP key, because TOTP depends on the server and client sharing that secret.
The weak defaults like the short secret length (ten bytes, which we can make longer and still be compatible) and the hash algorithm (SHA-1, which we can’t change) also make it possible to, if someone knows a few TOTP values and when they appeared, crack the secret offline. Thankfully, many (but not all!) services use longer-than-ten-byte secrets these days.
Finally, if you can control the clock on a working authenticator that you temporarily have possession of — changing its system date and time or feeding the wrong time to a hardware TOTP device that doesn’t have an onboard clock — you can get tokens for the future, which you can set aside and use when it’s convenient.
All that said, TOTP remains a useful tool. We should, of course, keep evolving the state of authentication. But it’s already better than passwords alone, and it doesn’t leave users open to SIM-jacking attacks that allow attackers to redirect SMS-based second-factor authentication.