I use oathtool to generate OTPs for google, github, dropbox, aws, etc... I store "secrets" on a thumb or encrypted drive. Then I make alias functions to load the key from the drive. Something like:

alias otp='oathtool --totp --base32 "`cat `/mnt/ecnrypted_drive/otprg.txt`"'

Then I can just grab it when I need it to log into whatever service:

otp | xsel --clipboard --input # I alias this to pbcopy on linux and pbcopy should work on osx

Now I don't have to get my phone out everytime I need to change AWS accounts or log in when a session expires.

My big problem came when I wanted to install oathtool on a new arch install. It wouldn't. There were failing dependency issues. I had similar problems on ubuntu in the past, but they are now solved. There are also apparently issues on OSX...

However wouldn't it be nice to go get it and just use it on any platform that has a reasonable terminal environment? The idea was born... There was even a blue sky moment where I imagined all the gnu and common userland tools implemented in Go.

So now I can at least install goathtool and use it without poking at oathtool dependencies.

How it works

It is a command line tool. Given a function Go installation you can install it like so: go get

There are examples of usage in the github README

Then you can get help by running:

goathtool -h

For easy review here's the output:

goathtool -h
usage of goathtool:
  goathtool [hotp|totp] <options> SECRET <OTP>

  SECRET is the hex or b32 encoded secret as a string
  OTP is a one-time password to validate.
Common options:
  -b=false: Use b32 encoding instead of hex
  -d=6: The number of digits in the OTP
  -v=false: Explain what is being done.
  -w=0: Window of counter values to test when validating OTPs
hotp options:
  -c=0: HOTP counter Value
totp options:
  -N="": Use this time as current time for TOTP
  -S="1970-01-01 00:00:00 UTC": When to start counting time-steps for TOTP
  -s=30: The time-step duration

Challenges I ran into

The biggest challenges were figuring out how oathtool functions. It has a pretty hairy interface. I suppose it may qualify as consistent, but it seemed a little odd how some things are positional args and others are flags. Also it seems that TOTP was bolted on after that RFC came out.

Go specific challenges for me we mostly working with flags and subcommands. I hadn't done that before. I managed to do it, but it feels like it is a bit hackish the way I accomplished shared variables.

Bolting validation on at the end also seems like quite the hack. Now there is some duplicated code and it has a bit of smell to it. It definitely needs a solid refactor.

I would be remiss if I didn't note that not knowing much about HOTP/TOTP going in was assuredly also a handicap. I would have done well to read the specs. However, wikipedia, stack overflow, and google provided sufficient information to hack up working implementations.

Accomplishments that I'm proud of

I only had about 12 hours to work on it. So I am totally proud of putting together an almost fully functional reimplementation of oathtool in that time. I think 32 hours would be enough time to finish it properly -- with tests, docs, and no known bugs. There is a bug in the TOTP validation which I am aware of, but I don't have time to fix it before I have to submit. I'll have to do it later -- and refactor.

I am also proud of choosing to do a cli rather than yet another web app (YAWA). In particular a command line tool that I use many times each day. It saves me many minutes of time not having to access my phone each time I need an OTP code from Google Authenticator.

Oh, it is also my first app entirely coded in vim. Was a longtime emacs user that converted to sublime text 2/3 about 3 years ago. I recently decided to switch to vim and this is my first app that I didn't give up using it on:)

What I learned

I learned a lot about flag sets, that CLI have have bad UI, and a slew about HOTP and TOTP.

What's next for goathtool

  1. Fix the TOTP validation bug, *. Refactor to clean up the implementation, *. godoc documentation *. update the README to be more concise *. tag the first version.

Built With

Share this project: