Everywhere I looked there seemed to only be an "app" for storing 2FA "Google Authenticator" secrets, here is short script that stores an encrypted file with the entered password.
2fa.pl:
#!/usr/bin/perl
use strict;
use warnings;
use Authen::OATH;
use Convert::Base32;
use File::Slurp;
use Data::Serializer;
=pod
perl 2fa.pl password nickname [secret]
prints out the current and next 6 digit "Google Authenticator" token
the secret is from the first line of the .google_authenticator file (o
+r the "Secret" from
online 2FA codes)
./2fa.pl mylocalpassword myremoteacct@server WRFPU2CIXFIGYYYC
stores the secret (WRFPU2CIXFIGYYYC) with the nickname myremoteacct@se
+rver
./2fa.pl mylocalpassword myremoteacct@server
prints
826651 377440
which is the current 6 digit code (826651) and the next one (377440),
+just in case :-)
Note: the save file (2fa.txt) is encrypted using your password
A good tutorial for adding 2FA to your SSH connections:
https://www.digitalocean.com/community/tutorials/how-to-set-up-multi-f
+actor-authentication-for-ssh-on-ubuntu-14-04
Adding 2FA to Perl scripts:
https://blog.darkpan.com/article/6/Perl-and-Google-Authenticator.html
parameters:
password - the password for the save file, which contains the map betw
+een nicknames and secrets
nickname - if the third parameter, secret, is not supplied then this d
+isplays the 6 digit code
secret - if supplied, then this secret is stored in the save file (./2
+fa.txt) for nickname
=cut
my $passwd = shift @ARGV;
my $nickname = shift @ARGV;
my $secret_base32 = shift @ARGV;
my $filename = "2fa.txt";
my $ser = Data::Serializer->new(
serializer => 'Storable',
digester => 'MD5',
cipher => 'DES',
secret => $passwd,
compress => 1
);
my $data;
if (-e $filename) {
eval { $data = $ser->deserialize("" . read_file($filename))};
if ($@) {
die "error reading $filename: $@\n";
}
}
if (defined($secret_base32)) {
$data->{$nickname} = $secret_base32;
# no check on format of $secret_base32, if you can't get that right
+ it ain't my problem
open FA2, ">", $filename or die "Can't open $filename for writing $
+@\n";
print FA2 $ser->serialize($data);
close FA2;
die "$nickname saved\n";
}
die "$nickname not found\n" unless defined($data->{$nickname});
$secret_base32 = $data->{$nickname};
my $correct_token = sprintf("%06s",
Authen::OATH->new->totp(
decode_base32( $secret_base32 )
)
); # the current token
$correct_token .= " " . sprintf("%06s",
Authen::OATH->new->totp(
decode_base32( $secret_base32), time() + 30
)
); # the next token
die "$correct_token\n";