Simple TOTP commandline tools on Linux

Categories: Linux, Security

Authenticating with websites by sending passwords across a network is a bad idea. If a site offers support for TOTP codes as either a password replacement or as an additional “second factor” then it is a good idea to enable that.

Using a hardware token such as a Yubikey (together with corresponding application on either phone or desktop) is the most secure way of generating TOTP codes.

Using a smartphone-based software TOTP client such as Google Authenticator is moderately secure, and convenient if you always have that phone with you (though you need to think about what happens if you lose that phone).

But even just running TOTP software on your laptop/desktop is a significant improvement over a password. It is easier than setting up a hardware token, and unlike a phone, your usual backups also cover the credentials. The negative side is that if you get malware on your client system, then both the password and TOTP secret can theoretically be stolen (though a fairly sophisticated attacker would be necessary). However does your threat-model include dealing with an attacker who has access to files in your home directory on your laptop? That problem is fortunately not high on my list..

This article shows how to deal with TOTP codes from the commandline on Linux.

Benefits of TOTP as a primary or second factor:

  • if you are lazy and reuse the “password” part of the login, you are still secure against guessing attacks
  • regardless of how poor you are at choosing passwords, the totp secret is a high-quality one and resistant to dictionary and brute-force attacks.

On Ubuntu, the pass package provides a cool cli-based password manager app which encrypts multiple credentials with a single master password. There is an extension package pass-otp but this does not appear to be pre-packaged for Ubuntu, and downloading source from non-controlled sources for security-sensitive software is probably not a good idea. As alternative, the totp cli application works with pass to handle HOTP/TOTP codes and is available via the Python package index (PyPI). While better than building native code from Github, I still have some concerns with using code installed via pip for security-sensitive operations.

Given that neither of the above pass-related tools are available as an Ubuntu package, perhaps (directly) using the simple oathtool package is easiest:

apt install oathtool

mkdir ~/.otpkeys
chmod 0700 ~/.otpkeys

# obtain secret somehow
echo $SECRET > ~/.otpkeys/somekeyname

# or when secret is in clipboard under X11
xclip -o -selection clipboard > ~/.otpkeys/somekeyname

# now generate codes
cat ~/.otpkeys/$otpkey | xargs /usr/local/bin/oathtool --totp --base32 

# or generate into X11 clipboard (use -selection primary for middle-click-to-paste)
cat ~/.otpkeys/$otpkey | xargs /usr/bin/oathtool --totp --base32 | xclip -i -selection clipboard

For convenience, I have defined the following shellscript helper for oathtool (and named it getoath):

# Compute an OATH-TOTP authentication code using one of the secrets in $HOME/.otpkeys and
# place it in the X clipboard ready for pasting into another application (eg a web-browser)
cat ~/.otpkeys/${1}*.otp | xargs /usr/bin/oathtool --totp --base32 | xclip -i -selection clipboard

This oathtool approach does not encrypt the secrets, which is not perfect (pass-otp or similar would be better, if available as a trustworthy package). But in my opinion this TOTP approach is still better than just using plain passwords; the question is:

  • is your threat model attackers guessing your passwords or stealing passwords from sites you use them with, or
  • is your threat model attackers with access to files in your home directory on your laptop?

If only the first is a concern, then local encryption of credentials is not critical. If you need to care about both, then obviously more care is needed - and a Yubikey might be the right solution.

Further Reading

  • jAuth – a Java-based implementation of Google Authenticator
  • Bash-otp – a trivial (but convenient) shellscript wrapper around oathtool