Skip to content

Instantly share code, notes, and snippets.

@mgregoro
Created April 24, 2015 20:57
Show Gist options
  • Save mgregoro/9fa29f5dfb36e88878ec to your computer and use it in GitHub Desktop.
Save mgregoro/9fa29f5dfb36e88878ec to your computer and use it in GitHub Desktop.
Perl TOTP using Crypt::Sodium
#!/usr/bin/env perl
use Crypt::Sodium;
use MIME::Base32;
my $secret = join(' ', @ARGV);
my $skew_tolerance = 10;
my $interval = 60;
while (1) {
my $time_fragment = int(time / $interval);
my $remaining = ($interval - time % $interval);
my $announce_token = token_for($time_fragment . $secret);
my %candidates;
if ($skew_tolerance) {
$candidates{token_for($time_fragment . $secret)} = 1;
$candidates{token_for(int((time - $skew_tolerance) / $interval) . $secret)} = 1;
$candidates{token_for(int((time + $skew_tolerance) / $interval) . $secret)} = 1;
} else {
$candidates{token_for($time_fragment . $secret)} = 1;
}
my @candidates = sort {$a cmp $b} keys %candidates;
print "$remaining, ANNOUNCE $announce_token; ACCEPT [" . join(', ', @candidates) . "]\n";
sleep 1;
}
sub token_for {
my $str = MIME::Base32::encode(crypto_hash(shift));
my $token;
if (length($str) > 8) {
# the token is the first 4 and last 4 characters.
$token = substr($str, 0, 4) . substr($str, length($str) - 4, 4);
} else {
# the token is the string left zero padded.
$token = "0" x (8 - length($str)) . $str;
}
return $token;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment