Abstract

Smartphone authenticator apps such as Google Authenticator and Authy implement software tokens that are “two-step verification services using the Time-based One-time Password Algorithm (TOTP) and HMAC-based One-time Password algorithm (HOTP)”

Smartphone TOTP, a form of Two-factor authentication (2FA), displays a 6-digit code derived from a shared secret, updating every thirty seconds.

The shared secret is presented only once to the user, typically with a QR (Quick Response) Code which is scanned by the authenticator app.

By using a simple QR app (not an authenticator app) to read in the shared secret, and storing the shared secret in a secure manner, one can easily recover the state of the authenticator app on a replacement phone.

Google Authenticator Screenshot
The Google Authenticator app running on an Android phone displaying the TOTP codes for several services, including Okta (shown), GitHub, and LastPass

This procedure is designed for an Android phone and a macOS workstation, but can be adapted to an iOS phone or Linux workstation, and, with some work, to a Windows workstation.

Procedure

0. Scan in the QR URL

When scanning in a new TOTP code, rather than launching Google Authenticator, we use Android Camera’s builtin QR Code reader (we’re not familiar with iOS/iPhones, but we assume there is an equivalent feature):

Scanning in a TOTP QR code
The Android Camera has a QR code reader mini-app. The launch button (see arrow) displays when the camera recognizes a QR code

The gentle reader should rest assured that all secrets in this blog post are fakes and that we would not deliberately leak our TOTP secrets in such an indiscreet manner.

Once in the QR mini-app, we copy the link to the clipboard by pressing the “duplicate” icon. A typical link would be similar to the following (an example TOTP from Slack):

otpauth://totp/Slack (Cloud Foundry):bcunnie@pivotal.io?secret=CBL5RAL4MSCFFKMX&issuer=Slack

Note that the link has a scheme of “otpauth”, an authority of “totp”, and the secret (key) is presented as a key-value pair query component (“secret=CBL5RAL4MSCFFKMX”). For those interested in more detail, the Google Authenticator GitHub Wiki is an excellent resource (where you will discover, among other things, that the key is Base32-encoded).

Copying the TOTP URL
We copy the link to the clipboard by pressing the "duplicate" icon

1. Copy the URL to a password manager

We copy the URL to a password manager. In our case we use LastPass [LastPass] , but we believe any password manager will do.

We are interested in alternative secure storage mechanisms (e.g. Vault, 1Password) for the secrets. For those of you so inclined, pull requests describing alternatives are welcome.

We copy the URL to a “secure note”, one line per URL. We name the secure note totp.txt.

This is what our secure note looks like (the keys have been changed to protect the innocent):

otpauth://totp/Okta:bcunnie@pivotal.io?secret=ILOVEMYDOG
otpauth://totp/GitHub:brian.cunnie@gmail.com?secret=mycatisgreat2
otpauth://totp/LastPass:bcunnie@pivotal.io?secret=LETSNOTFORGETMYWIFE
otpauth://totp/LastPass:brian.cunnie@gmail.com?secret=ormylovelychildren
otpauth://totp/AWS:bcunnie@pivotal.io?secret=SOMETIMESIFORGETMYCHILDRENSNAMES
otpauth://totp/AWS:brian.cunnie@gmail.com?secret=theyrealwaysgettingintotrouble
otpauth://totp/Google:brian.cunnie@gmail.com?secret=ILETMYWIFEDEALWITHIT
otpauth://totp/Pivotal%20VPN:bcunnie@pivotal.io?secret=computersaremucheasiertohandlethankids
otpauth://totp/Coinbase:brian.cunnie@gmail.com?secret=SOMETIMESIHIDEINMYOFFICE
otpauth://totp/Joker:brian.cunnie@gmail.com?secret=buttheyopenthedoortoseehwatImdoing
otpauth://totp/Discord:brian.cunnie@gmail.com?secret=THEYGETBOREDPRETTYQUICKLY
otpauth://totp/namecheap:brian.cunnie@gmail.com?secret=soIplayminecraftwiththem

2. Display the QR code to your terminal

We make sure we have a utility which displays QR codes to our terminal; we have found qrencode quite adequate, and on macOS it’s installed as easily as brew install qrencode (assuming the homebrew package manager is already installed).

We use a three-line shell script, totp.sh to display the QR codes to our terminal. Our invocation uses the LastPass CLI to display our TOTP secrets and pipe it to our shell script:

lpass show --note totp.txt | totp.sh

A parade of QR codes scrolls on our terminal, and we use our authenticator app to scan them in. We have been able to scan as many as 12 different QR codes in under a minute!

We point our authenticator app to the QR code on our terminal (not the QR code in the site’s web page) to ensure that the URL (and secret) have been correctly copied.

TOTP Alternatives

SMS 2FA

SMS 2FA transparently migrates to new phones (as long as the phone number doesn’t change), but has been faulted for being vulnerable to Signaling System 7 (SS7) attacks. [0] [1] [2]

U2F 2FA

“Universal 2nd Factor (U2F) is an open authentication standard that strengthens and simplifies two-factor authentication (2FA) using specialized Universal Serial Bus (USB) or near-field communication (NFC) devices”

U2F’s advantage is that its secret is never shared (it never leaves the key), so the secret itself is difficult to compromise. The downside is that the secret is stored in a physical key, so if the key is lost or broken, the 2FA must be reset. Also, adoption of U2F is not as widespread as TOTP: Slack, for example, offers TOTP 2FA but not U2F 2FA as of this writing.

Further Reading

CNET describes a procedure which doesn’t require storing the secrets but does require visiting each TOTP-enabled site to scan in a new QR code. It also requires the old phone (it’s not much help if you lose your phone).

Protectimus suggests saving screenshots of your secret keys, a simple solution for the non-technical user. They also describe a very interesting mechanism to extract the keys from a rooted phone using adb and SQLite, a technique which may be useful for users who already have a rich set of TOTP sites but have not stored the URLs in a password manager.

Footnotes

[LastPass] The security-minded reader might ask, “Wait, you’re storing your TOTP secrets in LastPass, but isn’t that also where you’re storing your passwords? Isn’t that a poor choice — to store both your secrets and passwords in the same place?”

To which we reply, “Yes, it is often poor choice to store both your secrets and passwords in the same place, but never fear — we don’t store our passwords in LastPass. Yes, we are aware that the intent of LastPass is to store passwords, but that’s not what we use it for. Instead, we store our passwords in a blowfish2-encrypted flat file in a private repo. We use LastPass for storing items that are sensitive but not passwords (e.g. TOTP keys).”