Skip to content

Instantly share code, notes, and snippets.

@MarkusH
Last active September 18, 2024 14:38
Show Gist options
  • Save MarkusH/e18efb744439fe828610b5086d953021 to your computer and use it in GitHub Desktop.
Save MarkusH/e18efb744439fe828610b5086d953021 to your computer and use it in GitHub Desktop.
Simple Bash TOTP client
#!/bin/bash
# Copyright (c) 2018, info AT markusholtermann DOT eu
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e
set -o pipefail
SOURCE_DIR=~/.config/2fa
function init() {
mkdir -p $SOURCE_DIR
chmod 0700 $SOURCE_DIR
if ! hash gpg 2>/dev/null ; then
echo "Please ensure that GnuPG is installed!"
exit 1
fi
if ! hash oathtool 2>/dev/null ; then
echo "Please ensure that oathtool is installed!"
exit 2
fi
}
function add_key() {
echo "Adding a new key"
if [ "x$1" != "x" ] ; then
identifier=$1
else
echo "What's the identifier?"
read -r identifier
fi
echo "What's the secret?"
read -r secret
echo "$secret" | gpg --quiet --symmetric --out "$SOURCE_DIR/$identifier"
}
function get_totp() {
if [ "x$1" != "x" ] ; then
identifier=$1
else
echo "What's the identifier?"
read -r identifier
fi
secret="$(gpg --quiet < "$SOURCE_DIR/$identifier")"
oathtool --base32 --totp "$secret"
}
function list() {
ls -1 "$SOURCE_DIR"
}
function help() {
echo "Setup a new TOTP account or generate a new TOTP token from an existing account."
echo
echo "Usage: totp.sh [--add|--list|--totp] [IDENTIFIER]"
echo
echo -e "--add Will ask for an identifier (i.e. 'google', 'slack', ...) and\\n" \
" then for the secret provided by the service provider."
echo -e "--list Will list all available identifiers."
echo -e "--totp Will ask for an identifier (i.e. 'google', 'slack', ...) and\\n" \
" then return the TOTP token."
}
init
case $1 in
--add)
add_key "$2"
;;
--list)
list
;;
--totp)
get_totp "$2"
;;
*)
help
esac
@BebeSparkelSparkel
Copy link

On OpenBSD I was having a problem with gpg finding the correct IOCTL device.

$ totp.sh --add failed with

gpg: problem with the agent: Inappropriate ioctl for device
gpg: error creating passphrase: Operation cancelled
gpg: symmetric encryption of '[stdin]' failed: Operation cancelled

Adding

export GPG_TTY=$(tty)

to the top of the script as detailed in the stackoverflow solution solved this issue.

Perhaps this should be added to the script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment