I am looking for a simple Perl implementation that verifies a Google authenticator token that has been created using a server side secret. For instance,
The following Go
Ok it took a little while but I've got a Perl solution (hopefully this makes up for the slightly lazy question :) Thanks to Borodin for his help with this (Taking the SHA1 HMAC of hex strings in Perl)
#!/usr/bin/perl -w
use strict;
use warnings;
use Convert::Base32;
use Digest::HMAC_SHA1 qw/ hmac_sha1_hex /;
my $base_32_secret = "JBSWY3DPEHPK3PXP";
print "".totp_token($base_32_secret)."\n";
sub totp_token {
my $secret = shift;
my $key = unpack("H*", decode_base32($secret));
my $lpad_time = sprintf("%016x", int(time()/30));
my $hmac = hmac_sha1_hex_string($lpad_time, $key);
my $offset = sprintf("%d", hex(substr($hmac, -1)));
my $part1 = 0 + sprintf("%d", hex(substr($hmac, $offset*2, 8)));
my $part2 = 0 + sprintf("%d", hex("7fffffff"));
my $token = substr("".($part1 & $part2), -6);
return $token;
}
sub hmac_sha1_hex_string {
my ($data, $key) = map pack('H*', $_), @_;
hmac_sha1_hex($data, $key);
}