Back up your TOTP codes by just printing themAndrew Quinn's TILsAdd me on X / Twitter!<br>You can cite this post as a reason if you're shy.
Scan the Quick Response (QR) code above with your favorite Two-Factor Authentication (2FA) app.<br>You should get a six digit number, rotating every<br>30 seconds, that looks something like<br>237601<br># as of Wed May 20 09:44:53 AM EEST 2026
If you then take the secret key that QR code maps to,<br>say<br>otpauth://totp/?secret=JBSWY3DPEHPK3PXP
or often even just the raw secret itself1<br>JBSWY3DPEHPK3PXP
, you can regenerate the exact sequence of six digit Time-based One-Time Password (TOTP)<br>codes someone else will get, in order, to infinity.<br>If you have a clock which happens to agree with<br>them, you can regenerate it at the same time that they do.<br>That’s it. At its heart, a TOTP code is just a password,<br>hashed and salted with a sawed-off timestamp.2<br>We can prove it here. Go to both<br>Dan Hersam’s TOTP code generator<br>and<br>BaseToolbox’s TOTP code generator.<br>Paste in that same JBSWY3DPEHPK3PXP secret to both.<br>Put the two windows side by side.<br>The same code will appear every 30 seconds,<br>plus or minus epsilon, because the universe has a hard<br>speed limit on how fast information can propagate<br>of about 300,000,000 meters per second.3<br>One nice property of this is that, because the math to<br>calculate TOTPs is not owned by anyone proprietary, there<br>are actually a lot of privacy-focused third party apps<br>that can handle TOTP codes if you’re not entirely trusting<br>of Google or Microsoft.<br>I like Aegis,<br>and Aegis and I have a mutual understanding that the instant<br>I start to think it’s seeing anyone else this relationship is<br>finito.<br>One even nicer property of this is that<br>you can just print TOTP QR codes and scan them later .<br>Your coworkers or loved ones can scan them.<br>An estate planner helping a tech-clueless loved one sort through<br>your things will probably figure out what these QR codes are<br>in a matter of minutes, and then it’s more of a question of<br>figuring out what they actually correspond to than anything.<br>For all the hate<br>it gets in the digital age, it is nearly impossible to find<br>a more cost effective medium than<br>ordinary copy paper, in a cool, dry environment for mid-term archival purposes of “small data”<br>in individual operations. By “small data” I mean<br>anything under about a megabyte,<br>and by “mid-term” I mean “one to two decades”.4 Copy paper retails<br>for about one penny apiece. You could probably back up every<br>TOTP code you ever use for under a dollar of upfront cost, assuming<br>you already had a place to put them. If you don’t, spend one<br>more dollar to buy a folder, put it in a closet, and set an invite<br>on your Google Calendar to reprint them in 4 or 5 years or so.<br>Maybe spend one more dollar to leave a copy of those big, bulky<br>QR codes with grandma.<br>Now for my pitch. TOTP codes are, theoretically, less secure than<br>having a dedicated hardware key.<br>I do love my hardware keys, don’t get me wrong.<br>The ease of use of just plugging in a tiny dedicated computer<br>and pressing its built in button to e.g. use sudo can’t be beat.<br>And these things are probably going to survive for 5 or 10 years<br>themselves, too.5<br>But TOTP codes are so easy! You can implement them<br>without needing to buy anything! You can back them up with the<br>same old black and white printer you’ve been using for the past<br>decade, and they’ll be usable a decade hence unless you actively<br>choose to rotate them! Consider using TOTP codes if you don’t<br>already have a more robust plan in place. The fact that they are<br>much easier to back up than basically any other 2FA system I know<br>of is a very nice bonus — a small win in the long, slow campaign<br>against entropy that is keeping a digital life going.<br>JBSWY3DPEHPK3PXP is the canonical test-vector secret you see in every TOTP tutorial on the internet. It is base32; decoded, it is Hello! concatenated with 0xDEADBEEF. You can verify this yourself with printf 'Hello!\xDE\xAD\xBE\xEF' \| base32. ↩︎
TOTP is specified in RFC 6238, itself a thin wrapper over RFC 4226 (HOTP — HMAC-based One-Time Password). The “time-based” part just means HOTP’s counter is replaced with floor(unix_time / 30). That is the entire trick. You could implement a working TOTP generator in ~20 lines of Python. ↩︎
Exactly 299,792,458 meters per second in vacuum, a number which since 1983 is true by definition. The meter is now defined in terms of the second and c, rather than the other way around. In a sense the speed of light is no longer measured but decreed. But the reason your two browser tabs agree on the code is more about the Network Time Protocol, which both of their host machines almost certainly run, and which keeps consumer clocks synchronized to within tens of milliseconds of UTC. A typical consumer quartz wristwatch, by comparison, is usually rated at ±15 seconds per month, so a computer that...