**** DONE TOTP 2FA Using oathtool in the Command Line :software:diy:security:pim:blog: CLOSED: [2019-03-03 Sun 19:30] SCHEDULED: <2019-03-03 Sun> :PROPERTIES: :ID: 2019-03-03-oathtool-otp :CREATED: [2019-03-03 Sun 19:12] :END: :LOGBOOK: - State "DONE" from "DONE" [2019-09-11 Wed 13:38] - State "DONE" from "NEXT" [2019-03-03 Sun 19:30] :END: Update 2019-09-11: added link to [[https://paste.debian.net/1100018/]] So far, I was using [[https://en.wikipedia.org/wiki/2FA][two-factor authorization (2FA)]] with [[https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm][TOTP]] and [[https://freeotp.github.io/][FreeOTP]] on my Android phone only. (I don't want to use the more popular [[https://en.wikipedia.org/wiki/Google_Authenticator][Google Authenticator]] because of Google and personal preference.) TOTP provides a higher level of security in contrast to any text message-based (SMS) or network-based two-factor authorization. A couple of days ago, I stumbled over [[https://www.sendthemtomir.com/blog/cli-2-factor-authentication][a great blog post]] where the author explains how to set-up TOTP using [[https://www.nongnu.org/oath-toolkit/man-oathtool.html][oathtool]] in the GNU/Linux command line. This has the advantages that I am able to use TOTP authentication on my Linux machines without my mobile phone and it forces me to backup my TOTP secrets and not only some recovery keys. However, [[https://www.sendthemtomir.com/blog/cli-2-factor-authentication][the proposed method]] uses key-value-pairs of the services and their secrets within a clear-text file. This was a clear no-go from my point of view. It would expose my secrets to any intruder on a silver plate. Therefore, I extended the shell script with a [[https://en.wikipedia.org/wiki/Gnupg][GnuPG]] encrypted file for the secrets. ------------- First, you have to install =gnupg= and =oathtool= on your operating system. Then, you store the following source code to a shell script =otp=: #+BEGIN_SRC sh #!/usr/bin/env sh # File name of the encrypted file that holds the name/key pairs: KEYFILE="$HOME/.otpkeys" # GnuPG user ID to use for encryption: UID="myself@example.com" # GnuPG key ID to use for encryption: KEYID="AABBCCDD" # temporary file for modifying name/key pairs in plain text: TMPFILE="/tmp/temp_key_file.txt" # current list of names in KEYFILE: (used only for output on help screen): NAMES="google github" ########################################################################### print_help() { ########################################################################## cat < names: ${NAMES} Initial setup of configuration file: 1. Create new text file "configuration.txt" and add name/key pairs: Format for each line: name=key 2. Encrypt this file: gpg -u ${KEYID} -r ${UID} --encrypt configuration.txt 3. Move file to final destination: mv configuration.txt.gpg ${KEYFILE} 4. Remove plain text file if everything went fine: rm configuration.txt Update process of configuration file: 1. gpg -u ${KEYID} -r ${UID} --decrypt ${KEYFILE} > ${TMPFILE} 2. (plain text secret without spaces!) Format for each line: name=key 3. gpg -u ${KEYID} -r ${UID} --encrypt ${TMPFILE} && mv ${TMPFILE}.gpg ${KEYFILE} && rm ${TMPFILE} authors: https://www.sendthemtomir.com/blog/cli-2-factor-authentication and adaptions by Karl Voit, tools@Karl-Voit.at copyright: GPLv3 EOF ########################################################################## } if [ -z $1 ]; then print_help() fi OTPKEY=$(gpg -u ${KEYID} -r ${UID} --decrypt ${KEYFILE} | sed -n "s/${1}=//p") if [ -z $OTPKEY ]; then echo "$(basename $0): Bad Service Name '$1'" print_help() exit fi oathtool --totp -b $OTPKEY #end #+END_SRC The help screen is shown when you start =otp= without any parameter: #+BEGIN_EXAMPLE Command-line OTP tool to display OTP codes for a pre-configured set of services. Usage: otp names: google github Initial setup of configuration file: 1. Create new text file "configuration.txt" and add name/key pairs: Format for each line: name=key 2. Encrypt this file: gpg -u AABBCCDD -r myself@example.com --encrypt configuration.txt 3. Move file to final destination: mv configuration.txt.gpg /home/vk/.otpkeys 4. Remove plain text file if everything went fine: rm configuration.txt Update process of configuration file: 1. gpg -u AABBCCDD -r myself@example.com \\ --decrypt /home/vk/.otpkeys > /tmp/temp_key_file.txt 2. (plain text secret without spaces!) Format for each line: name=key 3. gpg -u AABBCCDD -r myself@example.com --encrypt /tmp/temp_key_file.txt && \\ mv /tmp/temp_key_file.txt.gpg /home/vk/.otpkeys && \\ rm /tmp/temp_key_file.txt #+END_EXAMPLE Modify the initial variables in the shell script according to your preferences. After the initial setup (explained in the help-screen), you get valid TOTP numbers when you start, e.g., =otp github=. Have fun and stay safe. [[https://www.reddit.com/r/linux/comments/axm3mx/2fa_using_oathtool_with_gnupg_encrypted_secrets/][This reddit thread]] lists some comments and further links. Update 2019-09-11: @paolog@mastodon.social [[https://mastodon.social/@paolog/102772431226446457][has published]] an extended version of my shell script which offers a =get= and a =set= option for retrieving codes and adding keys.