-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtokens
executable file
·142 lines (130 loc) · 4.1 KB
/
tokens
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/bin/bash
# tokens - shows time-based one-time passwords - TOTP
# Depends on oathtool package
# Check for main dependency
if ! command -v oathtool > /dev/null; then
echo "oathtool not found" 1>&2
exit 1
fi
# Initial settings
rc=${TOKENSRC:-~/.tokensrc}
# shellcheck source=.tokensrc
[[ -r "$rc" ]] && source "$rc"
secretsfile=${secretsfile:-tokens.secrets}
cipherfile="${secretsfile}.cipher"
barstyle=${barstyle:-:.}
COLSIZE=28
XCLIP=""
[[ -z "$XCLIP" ]] && command -v termux-clipboard-set > /dev/null && XCLIP="termux-clipboard-set"
[[ -z "$XCLIP" ]] && command -v xclip > /dev/null && XCLIP="xclip -selection c"
[[ -z "$XCLIP" ]] && command -v xsel > /dev/null && XCLIP="xsel -ib"
declare -ar keys=({1..9} {a..z} {A..Z})
# Handle window resizing
trap '((redraw = 1))' SIGWINCH
# Load the secrets
if [[ -f "$cipherfile" ]]; then
# Decrypt the secrets file
if ! command -v openssl > /dev/null; then
echo "openssl not found" 1>&2
exit 1
fi
# Check if the version of OpenSSL is 1.1.1 or greater and add -pbkdf2 parameter
ossl111=""
read -r vmajor vminor vpatch <<< "$(
openssl version | while read -ra v; do v1="${v[1]}"; echo "${v1//./ }"; done
)"
read -r vmajor vminor vpatch <<< "${vmajor//[^0-9]/} ${vminor//[^0-9]/} ${vpatch//[^0-9]/}"
if [[
1 -lt $vmajor
|| (1 -eq $vmajor && 1 -lt $vminor)
|| (1 -eq $vmajor && 1 -eq $vminor && 1 -le $vpatch)
]]; then
ossl111="-pbkdf2"
fi
# Input the passphrase
read -rsp "Enter the passphrase: " pass
export pass
# Decrypt the secrets file
origin="openssl enc -aes128 -d -in '$cipherfile' -pass env:pass $ossl111"
if ! sh -c "$origin" > /dev/null; then
echo 1>&2
echo "Check the passphrase" 1>&2
exit 1
fi
origin="$origin | gzip -d"
else
origin="cat '$secretsfile'"
fi
declare -A secrets
((cnt = 0))
while read -r name secret; do
secrets[${keys[$cnt]}]="$name $secret"
((++cnt))
done < <(sh -c "$origin")
unset pass
# Calculate and print the tokens
((lasthalf = -1))
((redraw = 1))
while true; do
# Eval the time period and verify if must calc the tokens
((seconds = $(date '+%-S')))
((half = seconds / 30))
((remaining = 30 - seconds % 30))
if ((half != lasthalf)) || ((redraw)); then
((redraw = 0))
if ((half != lasthalf)); then
# Calculate the tokens
((lasthalf = half))
unset tokens
declare -A tokens
for key in "${!secrets[@]}"; do
read -r name secret <<< "${secrets[$key]}"
token=$(oathtool --totp --base32 "$secret")
tokens[$key]="$name $token"
done
fi
# Format in columns
((cols = $(bash -i -c 'echo $COLUMNS') / $COLSIZE))
((rows = ${#tokens[@]} / cols))
unset lines
declare -a lines
((line = 0))
for ((cnt = 0; cnt < ${#tokens[@]}; ++cnt)); do
key=${keys[$cnt]}
read -r name token <<< "${tokens[$key]}"
printf -v lines[$line] '%s%s) %-10.10s: %s%7s' "${lines[$line]}" \
"$key" "$name" "$token" ''
((line = line < rows? ++line: 0))
done
# Print the columns of tokens
clear
for ((cnt = 0; cnt < ${#lines[@]}; ++cnt)); do
echo "${lines[$cnt]}"
done
echo -e '\n0) Exit\n'
fi
# Format and print the progress bar
printf -v bar '%-030.*d' $remaining 0
printf -v bar '%s' "${bar//0/${barstyle:0:1}}"
printf -v bar '%s' "${bar// /${barstyle:1:1}}"
now=$(date '+%Y-%m-%d %H:%M:%S')
printf '\r Remaining : %6d %s %s ' $remaining "$bar" "$now"
# Check for key press
read -N 1 -t 1 -rs key
case "$key" in
"")
;;
0)
# Exit
echo
break
;;
[1-9a-zA-Z])
# Copy token to clipboard
if [[ -n "$XCLIP" && -n "${tokens[$key]}" ]]; then
read -r name token <<< "${tokens[$key]}"
$XCLIP <<< "$token"
fi
;;
esac
done