May 11, 2015 Leave a comment
I have been using a time-based one time password (TOTP) generator on my phone with my clod-based accounts at Google, Amazon AWS, GitHub, Microsoft — every service that supports it — for years now. I have over a dozen of these and dragging my phone out every time I need a 2-factor token is a real pain.
I spend a lot of my time working on a trusted computer and I want to be able to generate the TOTP codes easily from that without having to use my phone. I also want to have reasonable confidence that the system is secure. I put together an old-school Bourne Shell script that does the job:
- My OTP keys are stored in a file that is encrypted with gnupg and only decrypted momentarily to generate the codes.
- The encrypted key file can by synchronized between computers using an untrusted service like DropBox or Google Drive as long as the private GPG key is kept secure.
- I’m using
oathtoolfrom oath-toolkit to generate the on-time code.
Pro Tip: Most sites don’t intend you to have more than one token that generates passwords. Their enrollment process typically involves scanning a QR Code to enroll a new private key into Google Authenticator or other OATH client. I always take a screen shot of these QR Codes and keep them stored in a safe place.
Save this script as an executable file in your path such as
In order to use my script you need to already have gnupg installed and configured with a private key.
You then need to create a plain text file that contains key:value pairs. Think of these as an associative array or dictionary where the lookup key is a memorable name and the value is a base32 encoded OATH key.
Encrypt this file of name and key associations with gpg in ASCII-armor format with yourself as the recipient and save the output file as
$ gpg --encrypt --armor --recipient email@example.com otpkeys $ mv otpkeys.asc ~/.otpkeys.asc
Now the script will start working. For example, generate a code for the “fake” key in the sample file (your result should be different as the time will be different):
$ otp fake 487036
Extracting keys from QR Codes
At this point you may be thinking, “OK, but how the hell do I get the OTP keys to encrypt into the .otpkeys file?”
The ZBar project includes a binary
zbarimg which will extract the contents of a QR Code as text in your terminal. The OATH QR Codes contain a URL and a portion of that is an obvious base32 string that is the key. On rare occasions, you may need to pad the ‘=’ at the end of the string to make it a valid base32 string that works with
oathtool is picky.
My favorite package manager for OS X, MacPorts, doesn’t have ZBar so I had to build it from source. Homebrew has a formula for zbar. If you are using Linux, it is probably already packaged for you. Zbar depends on ImageMagick to build. If you have ImageMagick and its library dependencies, Zbar should build for you. Clone the Zbar repo with git, check out the tag for the most recent release — currently “0.10” — and build it.
$ git clone firstname.lastname@example.org:Zbar/Zbar $ cd Zbar $ git checkout 0.10 $ make $ sudo make install
Once you have ZBar installed, you should have
zbarimg in your path and you can use it to extract the otpauth URL from your QR Code screenshot.
$ zbarimg ~/Documents/personal/totp-fake-aws.png QR-Code:otpauth://totp/breiter@fake-aws?secret=ORUGS4ZNNFZS2YJNMZQWWZJNNNSXS=== scanned 1 barcode symbols from 1 images in 0 seconds
I hope you already have screen shots of all your QR Codes or else you will need to generate new OTP keys for all your services and take a screen shot of the QR Code this time.
Syncing OTP key file with other computers
otp script looks for an environmental variable OTPKEYS_PATH. You can use this to move your otp key file database to another location than
~/.otpkeys.asc. For example put it in Google Drive point the
otp script to it by setting
#path to GPG-encrypted otp key database export OTPKEYS_PATH=~/Google\ Drive/otpkeys.asc
Now you can generate your OTP codes from the terminal in your trusted computers whenever you need them and enjoy a respite from constantly dragging your phone out of your pocket.