Skip to content

Instantly share code, notes, and snippets.

@Val
Created August 31, 2022 19:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Val/e8f98e7267756df8f4cd00882c6beb62 to your computer and use it in GitHub Desktop.
Save Val/e8f98e7267756df8f4cd00882c6beb62 to your computer and use it in GitHub Desktop.
Calculate the Yubikey serial number from the OTP (bash only)
#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'
# adapted from Python: https://gist.github.com/href/dad244512c320bd9b5d6ff50e7c7e0b2
declare -ra ALPHABET=(c b d e f g h i j k l n r t u v)
index_of() {
local -r element="$1"
local -i index=-1
for i in "${!ALPHABET[@]}" ; do
if [[ "${ALPHABET[$i]}" = "$element" ]] ; then
index=$i
printf '%i' "$index"
break
fi
done
}
yubikey_otp_to_serial() {
local -r otp_str="cccc${1:0:12}"
# splits into array bash trick
[[ "$otp_str" =~ ${otp_str//?/(.)} ]]
declare -ar otp_arr=("${BASH_REMATCH[@]:1}")
local -i index=-1
local -i keep=0
local -i toggle=0
local -a bytesarray=()
for char in ${otp_arr[*]} ; do
index=$(index_of "$char")
if [ "$toggle" -eq 0 ] ; then
toggle=1
keep="$index"
else
toggle=0
bytesarray+=($(( (keep << 4) | index )))
fi
done
local -i value=0
for index in {0..7} ; do
value+=$(( (${bytesarray[$index]} & 255) << ( ( (4 - 1 - index) * 8) & 0x1f ) ))
done
printf '%i\n' "$value"
}
printf 'touch your yubikey: '
read -r otp
yubikey_otp_to_serial "$otp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment