Ian Patrick Badtrousers

Recovery codes considered harmful

Thursday, 16 Jan 2020

Recovery codes:

  1. Provide complete override of 2FA procedures;
  2. Add no security whatsoever;
  3. Users rarely pay attention, they are confused by it.

I dare to think recovery codes could be the most retarded case of groupthink. First of all, they are not part of the TOTP-related RFC 6238 standard. Yes, recovery codes are exclusively provider-dependent. Moreover, many sources recommend to generate them arbitrarily: either with, or without a seed. The seed will save you some space, but as long as I’m concerned, you should just spit a bunch of random hex-encoded strings, which completely override the whole 2FA protocol, and then store them somewhere on your back-end. In U2F, they enjoy the luxury of public-key cryptography, where only the users themselves own the secret, but in TOTP we are stuck with shared secrets. My friend, you should feel really proud about them totp and recovery_codes tables you’ve set up last week in Postgres. Or did you not? Of course you didn’t! You’re webscale, and webscale means Vault.

Worry you shall not, my faith in you is unshakeable!

And I’m not even trying at clickbait.

For anyone who ever had the hassle of setting up two-factor authentication online, chances are they were introduced to recovery codes at some point. Not only that, chances are they never actually wrote these down, or made any effort to secure them whatsoever.

I think there’s a good reason for that and it has very little to do with the fact that average users are likely to neglect their security. No–no, it’s one hundred percent our fault, as software engineers: the very idea of TOTP recovery codes is incredibly impractical, and to put it frankly, stupid.

Naturally, we should expect users to reject stupid ideas, so there’s that.

A little bit of introduction for the uninitiated: there are two widely adopted multi-factor protocols: TOTP[1], the one-time password standard, and U2F[2], which is used in hardware authentication units, such as Yubikey. Please, don’t get me wrong; I’m just as obssessed with security as the next man, but hey, it don’t take no Einstain to figure U2F ain’t gonna happen fast enough for most of us. Even though it should, it ain’t. Google Authenticator[3] it is, then. I’m pretty sure some people claim this app is no good, and some would even go as far as to recommend Authy, but… doesn’t it defy the very purpose of 2FA to keep all your one-time passwords in a single basket somewhere online? Oh, please!

Why do we do this 2FA thing? The idea is that having a second point of failure—something you have, as opposed to something you know, like your password—greatly increases your overall security. That is how we reason about security, by making ourselves dependent on our 2FA devices, completely impairing our ability to authenticate with our phones dead, lost, or stolen.

“Recovery codes!”, — shall scream some confused neurotic from the audience.

I dare to think recovery codes could be the most retarded case of groupthink. First of all, they are not part of the TOTP-related RFC 6238[4] standard. Yes, recovery codes are provider-dependent. Moreover, many sources recommend to generate them in a completely arbitrary fashion: either with, or without a seed. The seed will save you some space, but as long as I’m concerned, the best practice out ther is to spit a bunch of random hex-encoded strings, which completely override the whole 2FA protocol, and then store them somewhere up your rear end. In U2F, they enjoy the luxury of public-key cryptography, where only the users themselves own the secret, but in TOTP we are stuck with shared secrets. My friend, you should feel really proud about them totp and recovery_codes tables you’ve set up last week in Postgres. Or did you not? Of course you didn’t! You’re webscale, and webscale means Vault[5]. Worry you shall not, my faith in you is unshakeable!

The token itself is the ultimate recovery key.

There is absolutely no need for any of this security circus. “There is no spoon.” What do you do when there’s no spoon? Well, you certainly don’t come up with elaborate user-hostile schemes, which will only ever land you more and more manual account recovery requests.

But that’s exactly what we do.

Recovery codes:

  1. Provide complete override of 2FA procedures;
  2. Add no security whatsoever;
  3. Users are confused by it.

Before you even think about it; no, nobody cares about that encrypted and thoroughly replicated doomsday partition, where you keep your vast collection of recovery codes. We all have got one, you’re not the only security freak out there. The point is, why bother with recovery codes when we already show the user-friendly security token alongside the handsome computer-friendly QR code?

Blimey, I’ll be done writing down my actual key before you’ll get down to the third or forth of your one-time recovery condoms! Meanwhile, Wikipedia’s help[6] on this subject reads like coming-of-age cypherpunk. They call them scratch codes, you need to use one to log in, one to reset. I have to admit, it’s rather cute.

At Veritas.icu[7], we actually take security of our users seriously, so instead we choose to make them suffer.

First you see this:



<Click.> Immediately, you have to re-enter the secret by hand (pasting is disabled, too).

We care so deeply, it’s borderline evil!

I was told that some fancy old Swiss bank still maintains all of its communications via one-time pads. Bank employees would still get these old-fashioned notepads, but instead of doing all encryption by hand, they just punch them into computer, crossing-out one key at a time.

Maybe this is the way to go with consumer security, but I think not.

-badt