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.
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.
The process described here is not lightweight—it’s as burdensome as resetting all your TOTP secrets. The target user is someone who prefers TOTP 2FA over SMS 2FA and who frequently upgrades phones (or factory resets them). Or someone who keeps spare phones.
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):
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):email@example.com?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).
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
This is what our secure note looks like (the keys have been changed to protect the innocent):
otpauth://totp/Okta:firstname.lastname@example.org?secret=ILOVEMYDOG otpauth://totp/GitHub:email@example.com?secret=mycatisgreat2 otpauth://totp/LastPass:firstname.lastname@example.org?secret=LETSNOTFORGETMYWIFE otpauth://totp/LastPass:email@example.com?secret=ormylovelychildren otpauth://totp/AWS:firstname.lastname@example.org?secret=SOMETIMESIFORGETMYCHILDRENSNAMES otpauth://totp/AWS:email@example.com?secret=theyrealwaysgettingintotrouble otpauth://totp/Google:firstname.lastname@example.org?secret=ILETMYWIFEDEALWITHIT otpauth://totp/Pivotal%20VPN:email@example.com?secret=computersaremucheasiertohandlethankids otpauth://totp/Coinbase:firstname.lastname@example.org?secret=SOMETIMESIHIDEINMYOFFICE otpauth://totp/Joker:email@example.com?secret=buttheyopenthedoortoseehwatImdoing otpauth://totp/Discord:firstname.lastname@example.org?secret=THEYGETBOREDPRETTYQUICKLY otpauth://totp/namecheap:email@example.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
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,
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.
“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.
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.
[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).”