Skip to content

Instantly share code, notes, and snippets.

@michaelkitson
Last active March 20, 2026 18:55
Show Gist options
  • Select an option

  • Save michaelkitson/e3860a63ec3cbc574cbdd40d94d5695c to your computer and use it in GitHub Desktop.

Select an option

Save michaelkitson/e3860a63ec3cbc574cbdd40d94d5695c to your computer and use it in GitHub Desktop.
A bash function to generate TOTP codes
#!/usr/bin/env bash
set -euo pipefail
# Generates a TOTP code and copies it to your clipboard. Hardcode your own key if you'd like.
#
# Usage: totp [key-base32]
#
# Dependencies: openssl, coreutils (base32)
hex2bin() {
for ((i = 0; i < ${#1}; i += 2)); do
printf '%b' "\\x${1:i:2}"
done
}
bin2hex() {
od -An -tx1 | tr -d ' \n'
}
# generate_totp key [time_sec [digits]]
generate_totp() {
key=$1
key_hex=$(tr '[:lower:]' '[:upper:]' <<<"$key" | base32 -d | bin2hex)
time_sec=${2:-$(date +%s)}
digits=${3:-6}
time_step=$((time_sec / 30))
time_step_hex=$(printf "%016x" $time_step)
hash_hex=$(hex2bin "$time_step_hex" | openssl sha1 -mac HMAC -macopt "hexkey:$key_hex" -binary | bin2hex)
offset=$((16#${hash_hex:39}))
offset_str="${hash_hex:$((offset * 2)):8}"
byte0=$(((16#${offset_str:0:2} & 127) << 24))
byte1=$((16#${offset_str:2:2} << 16))
byte2=$((16#${offset_str:4:2} << 8))
byte3=$((16#${offset_str:6:2}))
bin_code=$((byte0 + byte1 + byte2 + byte3))
printf "%0${digits}d" $((bin_code % (10 ** digits)))
}
copy() {
if command -v pbcopy &> /dev/null; then
pbcopy
elif command -v xclip &> /dev/null; then
xclip -selection clipboard
elif command -v wl-copy &> /dev/null; then
wl-copy
fi
}
generate_totp "${1:-AC6ZWNRLFOG5JUQHC5YW6BXX2K675AZL}" | tee >(copy)
# Print a newline after the code, but we don't want it in the clipboard
printf "\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment