NAME

Authen::TOTP - Interface to RFC6238 two factor authentication (2FA)

Version 0.0.2

SYNOPSIS

use Authen::TOTP;

DESCRIPTION

Authen::TOTP is a simple interface for creating and verifying RFC6238 OTPs as used by Google Authenticator, Authy, Duo Mobile etc

It currently passes RFC6238 Test Vectors for SHA1

USAGE

 my $gen = new Authen::TOTP(
	 secret		=>	"some_random_stuff",
 );

 #will generate a TOTP URI, suitable to use in a QR Code
 my $uri = $gen->generate_otp(user => 'user\@example.com', issuer => "example.com");
 
 print qq{$uri\n};
 #store $gen->secret() someplace safe!

 #use Imager::QRCode to plot the secret for the user
 use Imager::QRCode;
 my $qrcode = Imager::QRCode->new(
           size          => 4,
           margin        => 3,
           level         => 'L',
           casesensitive => 1,
           lightcolor    => Imager::Color->new(255, 255, 255),
           darkcolor     => Imager::Color->new(0, 0, 0),
       );

 my $img = $qrcode->plot($uri);
 $img->write(file => "totp.png", type => "png");
 #...or you can pass it to google charts and be done with it

 #compare user's OTP with computed one
 if ($gen->validate_otp(otp => <user_input>, secret => <stored_secret>, tolerance => 1)) {
	#2FA success
 }
 else {
	#no match
 }

new Authen::TOTP

 my $gen = new Authen::TOTP(
	 digits 	=>	[6|8],
	 period		=>	[30|60],
	 algorithm	=>	"SHA1", #currently only this supported
	 secret		=>	"some_random_stuff",
	 when		=>	<some_epoch>,
	 tolerance	=>	0,
 );

Parameters/Properties (defaults listed)

digits

6=> How many digits to produce/compare

period

30=> OTP is valid for this many seconds

algorithm

SHA1=> only SHA1 currently supported by the module as well as most (?) clients

secret

random_12byte_string=> Secret used as seed for the OTP

base32secret

base32_encoded_random_12byte_string=> Alternative way to set secret (base32 encoded)

when

epoch=> Time used for comparison of OTPs

tolerance

1=> Due to time sync issues, you may want to tune this and compare this many OTPs before and after

Utility Functions

generate_otp=>

Create a TOTP URI using the parameters specified or the defaults from the new() method above

Usage:

 $gen->generate_otp(
	 digits 	=>	[6|8],
	 period		=>	[30|60],
	 algorithm	=>	"SHA1", #currently only this supported
	 secret		=>	"some_random_stuff",
	 issuer		=>	"example.com",
	 user		=>	"some_identifier",
 );
 
 Google Authenticator displays <issuer> (<user>) for a TOTP generated like this
validate_otp=>

Compare a user-supplied TOTP using the parameters specified. Obviously the secret MUST be the same secret you used in generate_otp() above/ Returns 1 on success, undef if OTP doesn't match

Usage:

 $gen->validate_otp(
	 digits 	=>	[6|8],
	 period		=>	[30|60],
	 algorithm	=>	"SHA1", #currently only this supported
	 secret		=>	"the_same_random_stuff_you_used_to_generate_the_TOTP",
	 when		=>	<epoch_to_use_as_reference>,
	 tolerance	=>	<try this many iterations before/after when>
	 otp		=>	<OTP to compare to>
 );
 

Revision History

 0.0.2
	Added Digest::HMAC_SHA1 and MIME::Base32 to cpanfiles requires (still
	getting acquainted with L<Minilla>)
 0.0.1
	Initial Release

DEPENDENCIES

Digest::HMAC_SHA1,

one of MIME::Base32::XS or MIME::Base32

Imager::QRCode if you want to generate QRCodes as well

SEE ALSO

Auth::GoogleAuth for a module that does mostly the same thing

https://tools.ietf.org/html/rfc6238 for more info on TOTPs

CAVEATS

Only SHA1 currently supported. It should be trivial to add SHA256 and SHA512, but I didn't bother

Some stuff definitely isn't as efficient as it can be

BUGS

Initial release...what do you expect ;)

ACKNOWLEDGEMENTS

Github user j256 for his example implementation

Gryphon Shafer <gryphon@cpan.org> for his Auth::GoogleAuth module that does mostly the same job, but I discovered after I had written most of this

AUTHOR

Thanos Chatziathanassiou <tchatzi@arx.net> http://www.arx.net

COPYRIGHT

Copyright (c) 2020 arx.net - Thanos Chatziathanassiou . All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See http://www.perl.com/perl/misc/Artistic.html