-
Notifications
You must be signed in to change notification settings - Fork 36
/
totp
executable file
·62 lines (54 loc) · 1.74 KB
/
totp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/usr/bin/env bash
help() {
echo "Time-based One-time Password Generator"
echo
echo "USAGE: $0 <server> <key> [interval]"
echo
echo "The default update interval is 30 seconds."
echo
echo "Supported servers: Google, GitHub, GitLab, Bitbucket"
exit -1
}
TOTP_SERVER=$1
TOTP_SECRET=$2
TOTP_INTERVAL=${3:-30}
if [[ -z "${TOTP_SERVER}" || -z "${TOTP_SECRET}" ]]; then
help
fi
TOTP_SERVER=$(echo "${TOTP_SERVER}" | tr A-Z a-z)
TOTP_SECRET=$(echo "${TOTP_SECRET// /}" | tr a-z A-Z)
if [[ ! "${TOTP_INTERVAL}" =~ ^[0-9]+$ ]]; then
echo "The update interval must be a non-negative integer: ${TOTP_INTERVAL}"
echo
help
fi
# Remove leading zeros.
TOTP_INTERVAL=$(printf %d "${TOTP_INTERVAL}")
TOTP_PERIOD=$(( $(date +%s) / TOTP_INTERVAL ))
gen_digest() {
local key=$1 period=$2
printf "$(printf %016X "${period}" | sed 's/../\\x\0/g')" |
openssl dgst -sha1 -mac HMAC -macopt "hexkey:${key}" |
cut -d\ -f2
}
gen_token() {
local server=$1 secret=$2 period=$3
case "${server}" in
google | github | gitlab | bitbucket)
local key=$( echo "${secret}" | base32 -d | hexdump -ve '/1 "%02X"' )
# The digest is a 64-bit hexadecimal number string.
local digest=$( gen_digest "${key}" "${period}" )
# Read the last 4 bits and convert it into an unsigned integer.
local offset=$(( $(printf %d "0x${digest:39}") * 2 ))
# Read a 32-bit positive integer and take at most six rightmost digits.
local token=$(( ("0x${digest:offset:8}" & 0x7FFFFFFF) % 1000000 ))
# Pad the token number with leading zeros if needed.
printf '%06d\n' "${token}"
;;
*)
echo "Your server is not supported: ${server}"
echo
help
esac
}
gen_token "${TOTP_SERVER}" "${TOTP_SECRET}" "${TOTP_PERIOD}"