A do-it-yourself time-based one-time password generator. You know, for MFA.
It's like a cheap open-source RSA dongle that works with any multi-factor authentication service following the TOTP standard.
Why? Because there are some things I use so frequently (SSH) that it's actually inconvenient to unlock my phone to get the MFA code. With this device mounted on my monitor, I can save seconds at a time.
Follow the instructions below to build your own!
- Arduino Nano (16MHz ATmega328, 5v) or cheap knock-off
- I2C 128x32 OLED display (SSD1306)
- I2C real-time clock module (DS3231) with battery
- Custom PCB to integrate components
Soldering required. Fine-point solder tip definitely recommended.
-
Attach header pins to OLED (short pins and spacers below, long pins above):
-
Attach header pins to Nano (note that not all pins are needed). Set the custom PCB in place to make sure the spacing is right - my original design was a hair too wide and set the pins at an angle - but don't solder it in yet. Short pins and spacers should be on the back of the Nano; long pings should protrude through the front:
-
Attach OLED to custom PCB (insert pins through the holes marked OLED, and don't cover the RTC holes!):
-
Attach custom PCB to Nano (make sure VIN and TX align on the Nano and custom PCB):
-
Attach RTC header pins to custom PCB (long pins and spacers below, short pins above):
-
Slide RTC onto its header pins:
Assembly is now complete!
-
Download Arduino IDE.
-
Adafruit AVR Boards
by Adafruit
-
Adafruit SSD1306
by AdafruitAdafruit GFX Library
by AdafruitRTC
by Manjunath CVTOTP library
by Luca Dentella
-
Clone or export this GitHub repo.
-
Open the Arduino project (
totp-generator.ino
) in Arduino IDE. -
Connect your fully assembled device to your computer using a USB data cable. The power light should come on, and it may blink if there is a default program installed to make it do that.
-
From the
Tools
menu in the Arduino IDE, configure these options:- Board: Arduino Nano
- Processor: ATmega 328P
- Port: whichever one corresponds to the device you just plugged in
-
Click the right-arrow button at the top of the program window to compile the code and upload it to the device.
If everything worked properly up to this point, your device should now be showing either "Connect to set clock" or "Connect to set keys" (depending on the initial RTC setting):
-
Install Python 3.
-
Install required Python libraries (just
pyserial
):
pip3 install -r requirements.txt
-
Connect your fully assembled and programmed device to your computer using a USB data cable.
-
Run the Python script:
python3 setup-device.py
-
Select the USB port corresponding to your device, when prompted.
-
After establishing a serial connection to your device, the script will automatically sync the time from your computer to the RTC.
-
For first-time setup, choose option 5 to initialize the device memory.
-
Choose option 3 to add a key to your device. First enter a three-character label for the key, then enter the key in the standard Base32 format. The device currently supports one or two keys at a time, and will adjust the display accordingly. Keys are recorded in the Arduino's built-in EEPROM without encryption (fair warning).
- Google Authenticator: the app should print your key after completing setup, otherwise you can retrieve the code from the first line of your
.google_authenticator
file - AWS MFA: use the "Show Secret Key" option during setup
- Google Authenticator: the app should print your key after completing setup, otherwise you can retrieve the code from the first line of your
-
Use the other menu options to view the labels assigned to keys stored on the device, delete keys, reset the device memory (wipe all keys), and sync the time again. Choose option 6 when you're done.
Setup is now complete! Here's how it should look:
The display includes a countdown bar to let you know when the code is about to change. It uses a 30-second counter, which is the only time value I've seen used in practice. You can change this value, if necessary, by editing the Arduino code and reprogramming the device.
if you only intend to use one code, you can modify the Arduino program to use a nicer-looking large font (it's not included by default because of memory constraints).
- Delete this line:
#include <Fonts/FreeMonoBold9pt7b.h>
- Search for
FreeSansBold9pt7b
and replace all matches withFreeSansBold18pt7b
- Delete
display.setTextSize(2);
from theprintCode
function - Delete all of the code inside the
printTwoCodes
function, so that it just looks like one line:void printTwoCodes(uint8_t key1, uint8_t key2) {}
- Compile and upload the new program to your device!