2fa tool for viewing your 2FA codes

This commit is contained in:
ville rantanen
2019-01-09 12:40:42 +02:00
parent 2e5838f30d
commit 90ef6170d6
3 changed files with 287 additions and 2 deletions

284
shell/2fa-view Executable file
View 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