How to generate a Base32 TOTP secret string on a Mac


I needed a way to generate a TOTP secret using a fairly locked-down Mac. No Brew. No NPM. No Python. No Prolog, COBOL, or FORTRAN. No Internet connection. Just whatever software is native to MacOS.

As I've mentioned before, the TOTP specification is a stagnant wasteland. But it does have this to say about the secret:

The secret parameter is an arbitrary key value encoded in Base32 according to RFC 3548.

The Base32 alphabet is pretty simple. The upper-case letters A - Z, and the numbers 3 - 7.

But that's only half the problem.

How long should the secret be?

This is an area where the official spec is silent. Around the web, you'll find people saying things like:

The length in bytes of generated shared secrets. The minimum is 20 (or 160 bits), and the default is 32 (or 256 bits). In most use cases 32 is sufficient. Though some authenticators may have issues with more than the minimum. Our minimum is the recommended value in RFC4226, though technically according to the specification 16 bytes (or 128 bits) is the minimum. Authelia

Although that's for the HOTP algorithm, rather than TOTP.

Looking through my 49(!) different TOTP codes, the shared secret ranges from 16 characters to 52 characters. No consistency whatsoever.

The Code

Run this on your command line.

cat /dev/urandom | LC_ALL=C tr -dc 'A-Z3-7' | fold -w 24 | head -n 1

That generates a random-enough0 string using the correct alphabet and truncated to a sensible length.

Let's go through each part of it.

cat /dev/urandom spits out random data from your machine. You may wish to use /dev/random if you feel like it.

LC_ALL=C sets the Locale to by ANSI bytes.

tr is "Translate, squeeze, and/or delete characters.".

-dc 'A-Z3-7' is delete the complement (i.e. delete anything which isn't in the following string).

fold -w 24 is wrap the input text with a line length of 24.

head -n 1 displays the first line of the file.

Next Steps

Now... How do I locally generate a QR code without anything else being installed...?


  1. This is a shared secret. It doesn't need an infinite supply of high-quality entropy. Any decent login protection service should throttle incorrect attempts long before someone can brute-force it. Remember, TOTP codes are not random - they're deterministic product of the secret. Your adversary isn't someone who can crack your secure vault - it's someone who already has your username as password, but doesn't have your token generating device. ↩︎


Share this post on…

  • Mastodon
  • Facebook
  • LinkedIn
  • BlueSky
  • Threads
  • Reddit
  • HackerNews
  • Lobsters
  • WhatsApp
  • Telegram

4 thoughts on “How to generate a Base32 TOTP secret string on a Mac”

  1. said on risc.social:

    @Edent

    Neat article, definitely bookmarking this because I know it'll come in handy having worked with TOTP stuff before, so thanks for sharing! One question:

    Just whatever software is native to MacOS.

    What version of macOS? Python 3 has been bundled with macOS by default for some time now - unless you mean that it's been removed/disabled by some policy on your machine, in which case, fair enough, forgive me!

    Reply | Reply to original comment on risc.social
  2. You can generate a QR Code using a Shortcut — in fact, you could probably include your secret generation command as a part of that, so you have an all in one button in the Shortcuts app to if that suits you 🙂

    Reply

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.

Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">