2fa tool for viewing your 2FA codes
This commit is contained in:
284
shell/2fa-view
Executable file
284
shell/2fa-view
Executable file
@@ -0,0 +1,284 @@
|
||||
#!/bin/bash
|
||||
_help() {
|
||||
echo '
|
||||
2FA code viewer
|
||||
|
||||
Usage:
|
||||
- Create a (possible encrypted) folder for your service keys
|
||||
- When the service presents you the QRCode, you typically can
|
||||
view the actual code as text. It looks something like:
|
||||
I5XXIY3IMEWCA3LBMRSSA6LPOUQGY33PNMQQU===
|
||||
- Store this piece of text in a file: "Service name".key
|
||||
- Run 2fa-view command in the folder
|
||||
|
||||
Viewer:
|
||||
- Codes and service names are printed on the screen
|
||||
- The upper timer shows the 30 second interval when
|
||||
the code changes
|
||||
- The lower timer shows time left before the program exits
|
||||
|
||||
Options:
|
||||
--light to disable animations
|
||||
--color X to prefer a color for the skull. Choose color from:
|
||||
k r g b c m y w K R G B C M Y W
|
||||
'
|
||||
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
for (( i=1; i<=$#; i++ )); do
|
||||
value=${!i}
|
||||
j=$(( i + 1 ))
|
||||
[[ "$value" = "--help" ]] && _help
|
||||
[[ "$value" = "--light" ]] && { LIGHT=1; continue; }
|
||||
[[ "$value" = "--color" ]] && {
|
||||
TFA_COLOR_TITLE="${!j}"
|
||||
((i++))
|
||||
continue;
|
||||
}
|
||||
[[ "${value}" = "-"* ]] && {
|
||||
[[ "$value" =~ -.*h ]] && { _help; }
|
||||
continue
|
||||
}
|
||||
done
|
||||
|
||||
|
||||
timeadjust=0
|
||||
update_frequency=30
|
||||
exit_timeout=120
|
||||
if [ "$1" = "light" ]; then LIGHT=1; fi
|
||||
shopt -s nullglob
|
||||
. qolop
|
||||
|
||||
picture=" ..;;;::;:;::;;:;,.
|
||||
.:::::;;;:;:::::::;;;;::;:;:.
|
||||
.::::;;::;::;:;::::::::::;:;::;::.
|
||||
,::::;:::::::;;;::;:;;::::;::::::::.
|
||||
';:::::::::::::::;;;;;;;:::;;::;;;:..
|
||||
';;::::',',',;:::;:;;;,'.;::::;;:;...
|
||||
.'. . .,:,.. ..
|
||||
' @ .::;:;. @ ..
|
||||
.:' .;: .::. .::.
|
||||
..,;;;:;:;;:' ,;,'';;,..,,'
|
||||
. .;;. .. .,::, .
|
||||
';:;;;::;;:::..:::
|
||||
,:::...;:. . .,,
|
||||
..
|
||||
"
|
||||
picture_colors="kkKKwwbm$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE$TFA_COLOR_TITLE"
|
||||
picture_color_codes=()
|
||||
for x in $( seq 0 $(( ${#picture_colors} - 1 )) ); do
|
||||
picture_color_codes+=( $( _qCol ${picture_colors:$x:1} ) )
|
||||
done
|
||||
picture_eye=$( _qCol R )
|
||||
|
||||
_skull() {
|
||||
if [ "$LIGHT" = 1 ]; then return; fi
|
||||
_qPos abs 4 1
|
||||
for x in $( seq 1 ${#picture} ); do
|
||||
chr="${picture:$x:1}"
|
||||
if [ "$chr" = " " ]; then _qPos right 1; continue; fi
|
||||
color="${picture_color_codes[$(( $RANDOM % ${#picture_colors} ))]}"
|
||||
if [ "$chr" = "@" ]; then color="$picture_eye"; chr="o"; fi
|
||||
printf "%s%s" \
|
||||
"$color" \
|
||||
"$chr"
|
||||
done
|
||||
|
||||
_qCol z
|
||||
}
|
||||
|
||||
flame=( )
|
||||
for x in $( seq 1 $(( 44 * 8 )) ); do
|
||||
flame+=( 0 )
|
||||
done
|
||||
flame_mask_array=( \
|
||||
"11111000000000000000000000000000000000001111" \
|
||||
"11000000000000000000000000000000000000000001" \
|
||||
"00000000000000000000000000000000000000000000" \
|
||||
"00000000000000000000000000000000000000000000" \
|
||||
"10000000000001110110111111001110000000000001" \
|
||||
"11100000010111111111011110111101100000000111" \
|
||||
"11100000011111111111111111111111110000000111" \
|
||||
"11110001111111111111111111111111110100011111" \
|
||||
)
|
||||
flame_mask=( )
|
||||
for y in {0..7}; do
|
||||
for x in {0..43}; do
|
||||
flame_mask+=( ${flame_mask_array[$y]:$x:1} )
|
||||
done
|
||||
done
|
||||
flame_chars=" .:##@"
|
||||
flame_colors="zzzmryYY"
|
||||
flame_color_codes=()
|
||||
for x in $( seq 0 $(( ${#flame_colors} - 1 )) ); do
|
||||
flame_color_codes+=( $( _qCol ${flame_colors:$x:1} ) )
|
||||
done
|
||||
flame_next=$( _qPos right 1 )
|
||||
flame_corner=$( _qPos abs 1 1 )
|
||||
|
||||
_flames() {
|
||||
if [ "$LIGHT" = 1 ]; then return; fi
|
||||
width=43
|
||||
height=7
|
||||
seq_x=$( seq 0 $width )
|
||||
for x in $seq_x; do
|
||||
pos=$(( ( $height ) * ( $width + 1 ) + $x ))
|
||||
flame[$pos]=$(( $RANDOM % 256 ))
|
||||
done
|
||||
|
||||
for y in $( seq 0 $(( $height - 1 )) ); do
|
||||
for x in $seq_x; do
|
||||
if [ $x -eq $width ]; then continue; fi
|
||||
if [ $x -eq 0 ]; then continue; fi
|
||||
pos=$(( $y * ( $width + 1 ) + $x ))
|
||||
pos_under=$(( ( $y + 1 ) * ( $width + 1 ) + $x ))
|
||||
new_value=$(( ( ( \
|
||||
${flame[$(( $pos_under ))]} + \
|
||||
${flame[$(( $pos_under + 1 ))]} + \
|
||||
${flame[$(( $pos_under - 1 ))]} \
|
||||
) * 17 ) / 48 ))
|
||||
|
||||
if [ $new_value -gt 255 ]; then
|
||||
new_value=255
|
||||
fi
|
||||
flame[$pos]=$new_value
|
||||
done
|
||||
done
|
||||
flame_buffer="${flame_corner}${flame_next}${flame_next}${flame_next}"
|
||||
for x in $( seq 0 $(( ( $width + 1 ) * ( $height + 1 ) - 1 )) ); do
|
||||
if [ $(( $x % ( $width + 1 ) )) -eq $width ]; then flame_buffer+="\n${flame_next}${flame_next}${flame_next}"; fi
|
||||
if [ ${flame_mask[$x]} -eq 1 ]; then flame_buffer+="${flame_next}"; continue; fi
|
||||
print_value=$(( flame[$x] / 32 ))
|
||||
flame_buffer+="${flame_color_codes[${print_value}]}${flame_chars:${print_value}:1}"
|
||||
done
|
||||
printf "$flame_buffer"
|
||||
_qPos abs 1 1
|
||||
}
|
||||
|
||||
_stars() {
|
||||
if [ "$LIGHT" = 1 ]; then return; fi
|
||||
wall_chars=" ,.'\`"
|
||||
wall_colors="kkkKKKzzzr"
|
||||
wall_color_codes=()
|
||||
for x in $( seq 0 $(( ${#wall_colors} - 1 )) ); do
|
||||
wall_color_codes+=( $( _qCol ${wall_colors:$x:1} ) )
|
||||
done
|
||||
|
||||
lines=$(( 25 + $KEY_FILES ))
|
||||
_qPos abs 1 1
|
||||
seq_x=$( seq 1 50 )
|
||||
for y in $( seq 1 $lines ); do
|
||||
for x in $seq_x; do
|
||||
chr="${wall_chars:$(( $RANDOM % ${#wall_chars} )):1}"
|
||||
if [ "$chr" = " " ]; then _qPos right 1; continue; fi
|
||||
color="${wall_color_codes[$(( $RANDOM % ${#wall_colors} ))]}"
|
||||
printf "%s%s" \
|
||||
"$color" \
|
||||
"$chr"
|
||||
done
|
||||
printf "\n"
|
||||
done
|
||||
_qCol z
|
||||
}
|
||||
|
||||
_exit() {
|
||||
clear
|
||||
_skull
|
||||
_qPos down 4
|
||||
exit
|
||||
}
|
||||
_get_code() {
|
||||
oathtool -b --totp $( cat "$1" | tr -dc '[:print:]' )
|
||||
}
|
||||
_print_codes() {
|
||||
#~ printf 'L%.0s' $( seq -1 $update_frequency )
|
||||
if [ "$LIGHT" = 1 ]; then
|
||||
_qPos abs 3 1;
|
||||
else
|
||||
_qPos abs 20 1
|
||||
fi
|
||||
even=0
|
||||
for k in *key; do
|
||||
if [ $even -eq 0 ]; then
|
||||
_qCol z Y
|
||||
else
|
||||
_qCol z G
|
||||
fi
|
||||
name=${k%.key}
|
||||
name=${name//_/ }
|
||||
_qPos right 6
|
||||
printf "[ %s ]%s %s \n" \
|
||||
$( _get_code "$k" ) \
|
||||
$( _qCol s ) \
|
||||
"$name"
|
||||
even=$(( 1 - $even ))
|
||||
done
|
||||
_qCol z
|
||||
}
|
||||
|
||||
_show_clock() {
|
||||
for foo in {1..1}; do
|
||||
i=$(( ( $( date +%s ) - $timeadjust ) % $update_frequency ))
|
||||
l=$(( $update_frequency - $i ))
|
||||
if [ "$LIGHT" = 1 ]; then
|
||||
_qPos abs $(( $KEY_FILES + 5 )) 1
|
||||
else
|
||||
_qPos abs $(( $KEY_FILES + 22 )) 1
|
||||
fi
|
||||
_qCol CLREND z g;_qPos right 5; date
|
||||
# seconds to code update
|
||||
_qCol z g
|
||||
printf "\r"; _qPos right 4; printf "[";
|
||||
printf ' %.0s' $( seq 1 $update_frequency )
|
||||
printf ']\r'; _qPos right 5
|
||||
if [ $l -gt 8 ]; then _qCol z G;
|
||||
elif [ $l -gt 3 ]; then _qCol z Y;
|
||||
else _qCol z R;
|
||||
fi
|
||||
printf '=%.0s' $( seq 1 $l )
|
||||
_qCol z c
|
||||
# seconds to this client shutdown
|
||||
left=$(( $update_frequency * ( $exit_timeout - $SECONDS ) / $exit_timeout ))
|
||||
printf "\n\r"; _qPos right 4; printf "[";
|
||||
printf ' %.0s' $( seq 1 $update_frequency )
|
||||
printf ']\r'; _qPos right 5
|
||||
if [ $left -gt 8 ]; then _qCol z c;
|
||||
elif [ $left -gt 3 ]; then _qCol z y;
|
||||
else _qCol z r;
|
||||
fi
|
||||
printf '#%.0s' $( seq 1 $left )
|
||||
_qCol z; printf "\n"
|
||||
_qCol CLREND
|
||||
# die if key pressed, or client open for exit_timeout length
|
||||
wait_for_second=$SECONDS
|
||||
for i in {1..10}; do
|
||||
read -t 0.1 foo
|
||||
[[ "$?" -eq 0 ]] && _exit
|
||||
[[ $SECONDS -gt $exit_timeout ]] && _exit
|
||||
_flames
|
||||
if [ $SECONDS -gt $wait_for_second ]; then break; fi
|
||||
done
|
||||
done
|
||||
}
|
||||
if [ -f "$1" ]; then _get_code "$1"; _get_code "$1" | xclip; exit; fi
|
||||
for key in *key; do ((KEY_FILES++)); done
|
||||
clear
|
||||
_print_codes
|
||||
_skull
|
||||
_flames; _flames; _flames; _flames
|
||||
|
||||
while :;do
|
||||
set -e
|
||||
new_codes=$( _print_codes )
|
||||
set +e
|
||||
[[ ! "$new_codes" = "$codes" ]] && {
|
||||
# print codes only if they change, this keeps selection in shell intact
|
||||
_stars
|
||||
codes=$new_codes
|
||||
echo -e "$codes"
|
||||
echo ''
|
||||
}
|
||||
_show_clock
|
||||
done
|
||||
Reference in New Issue
Block a user