Authen-OATH-v1.0.0000755000000000000 011376774127 14221 5ustar00unknownunknown000000000000Authen-OATH-v1.0.0/Build.PL000444000000000000 204411376772420 15644 0ustar00unknownunknown000000000000#!/usr/bin/perl ################################################################################ # $Id: Build.PL 3 2010-05-25 16:04:32Z v89326 $ # $URL: file:///S:/svn/Authen-OATH/trunk/Build.PL $ ################################################################################ # # Title: Build.PL # Author: Kurt Kincaid # VERSION: 1.0.0 # ################################################################################ use strict; use warnings; use Module::Build; my $builder = Module::Build->new( module_name => 'Authen::OATH', license => 'perl', dist_author => q{Kurt Kincaid }, dist_version_from => 'lib/Authen/OATH.pm', build_requires => { 'Test::More' => 0, 'Test::Simple' => 0, 'Moose' => 0, 'Math::BigInt' => 0, 'Digest::HMAC' => 0, 'Digest::SHA1' => 0, }, add_to_cleanup => [ 'Authen-OATH-*' ], create_makefile_pl => 'traditional', ); $builder->create_build_script(); Authen-OATH-v1.0.0/Changes000444000000000000 16511376771306 15627 0ustar00unknownunknown000000000000Revision history for Authen-OATH 1.0.0 Date/time First version, released on an unsuspecting world. Authen-OATH-v1.0.0/Makefile.PL000444000000000000 104311376774126 16325 0ustar00unknownunknown000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.3607 use ExtUtils::MakeMaker; WriteMakefile ( 'NAME' => 'Authen::OATH', 'VERSION_FROM' => 'lib/Authen/OATH.pm', 'PREREQ_PM' => { 'Digest::HMAC' => 0, 'Digest::SHA1' => 0, 'Math::BigInt' => 0, 'Moose' => 0, 'Test::More' => 0, 'Test::Simple' => 0 }, 'INSTALLDIRS' => 'site', 'EXE_FILES' => [], 'PL_FILES' => {} ) ; Authen-OATH-v1.0.0/MANIFEST000444000000000000 22411376770663 15466 0ustar00unknownunknown000000000000Build.PL Changes MANIFEST README lib/Authen/OATH.pm t/00-load.t t/01-cases.t t/manifest.t t/pod-coverage.t t/pod.t Makefile.PL META.yml Authen-OATH-v1.0.0/META.yml000444000000000000 111011376774127 15620 0ustar00unknownunknown000000000000--- abstract: 'OATH One Time Passwords' author: - 'Kurt Kincaid ' build_requires: Digest::HMAC: 0 Digest::SHA1: 0 Math::BigInt: 0 Moose: 0 Test::More: 0 Test::Simple: 0 configure_requires: Module::Build: 0.36 generated_by: 'Module::Build version 0.3607' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Authen-OATH provides: Authen::OATH: file: lib/Authen/OATH.pm version: v1.0.0 resources: license: http://dev.perl.org/licenses/ version: v1.0.0 Authen-OATH-v1.0.0/README000444000000000000 262611376771232 15236 0ustar00unknownunknown000000000000Authen-OATH This is an implementation of the HOTP and TOTP One Time Password algorithms as defined by OATH (http://www.openautentication.org). Please note that some of the code was largely influenced by the excellent Authen::HOTP module. I modified that portion of the code to make it more portable and to make use of Moose. No doubt there are still some similarities, and I am indebted to Iain Wade who wrote the Authen::HOTP module. INSTALLATION To install this module, run the following commands: perl Build.PL ./Build ./Build test ./Build install SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc Authen::OATH You can also look for information at: RT, CPAN's request tracker http://rt.cpan.org/NoAuth/Bugs.html?Dist=Authen-OATH AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/Authen-OATH CPAN Ratings http://cpanratings.perl.org/d/Authen-OATH Search CPAN http://search.cpan.org/dist/Authen-OATH/ LICENSE AND COPYRIGHT Copyright (C) 2010 Kurt Kincaid This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. Authen-OATH-v1.0.0/lib000755000000000000 011376774127 14767 5ustar00unknownunknown000000000000Authen-OATH-v1.0.0/lib/Authen000755000000000000 011376774127 16213 5ustar00unknownunknown000000000000Authen-OATH-v1.0.0/lib/Authen/OATH.pm000444000000000000 1325611376774115 17465 0ustar00unknownunknown000000000000#!/usr/bin/perl ################################################################################ # $Id: OATH.pm 4 2010-05-25 16:18:21Z v89326 $ # $URL: file:///S:/svn/Authen-OATH/trunk/lib/Authen/OATH.pm $ ################################################################################ # # Title: Authen::OATH # Author: Kurt Kincaid # VERSION: 1.0.0 # ################################################################################ package Authen::OATH; use warnings; use strict; use Digest::HMAC; use Math::BigInt; use Moose; has 'digits' => ( 'is' => 'rw', 'isa' => 'Int', 'default' => 6 ); has 'digest' => ( 'is' => 'rw', 'isa' => 'Str', 'default' => 'Digest::SHA1' ); has 'timestep' => ( 'is' => 'rw', 'isa' => 'Int', 'default' => 30 ); =head1 NAME Authen::OATH - OATH One Time Passwords =head1 VERSION Version 1.0.0 =cut our $VERSION = "1.0.0"; =head1 SYNOPSIS Implementation of the HOTP and TOTP One Time Password algorithms as defined by OATH (http://www.openauthentication.org) All necessary parameters are set by default, though these can be overridden. Both totp() and htop() have passed all of the test vectors defined in the RFC documents for TOTP and HOTP. totp() and hotp() both default to returning 6 digits and using SHA1. As such, both can be called by passing only the secret key and a valid OTP will be returned. use Authen::OATH; my $oath = Authen::OATH->new(); my $totp = $oath->totp( "MySecretPassword" ); my $hotp = $oath->hotp( "MyOtherSecretPassword" ); Parameters may be overridden when creating the new object: my $oath = Authen::OATH->new( 'digits' => 8 ); The three parameters are "digits", "digest", and "timestep." Timestep only applies to the totp() function. While strictly speaking this is outside the specifications of HOTP and TOTP, you can specify digests other than SHA1. For example: my $oath = Authen::OATH->new( "digits" => 10, "digest" => "Digest::MD6" ); =head1 SUBROUTINES/METHODS =head2 totp my $otp = $oath->totp( $secret [, $manual_time ] ); Manual time is an optional parameter. If it is not passed, the current time is used. This is useful for testing purposes. =cut sub totp { my ( $self, $secret, $manual_time ) = @_; $secret = join( "", map chr( hex() ), $secret =~ /(..)/g ) if $secret =~ /^[a-fA-F0-9]{32,}$/; my $mod = $self->{ 'digest' }; if ( eval "require $mod" ) { $mod->import(); } my $time = $manual_time || time(); my $T = Math::BigInt->new( int( $time / $self->{ 'timestep' } ) ); die "Must request at least 6 digits" if $self->{ 'digits' } < 6; ( my $hex = $T->as_hex ) =~ s/^0x(.*)/"0"x(16 - length $1) . $1/e; my $bin_code = join( "", map chr hex, $hex =~ /(..)/g ); my $otp = _process( $self, $secret, $bin_code ); return $otp; } =head2 hotp my $opt = $oath->hotp( $secret, $counter ); Both parameters are required. =cut sub hotp { my ( $self, $secret, $c ) = @_; $secret = join( "", map chr( hex() ), $secret =~ /(..)/g ) if $secret =~ /^[a-fA-F0-9]{32,}$/; my $mod = $self->{ 'digest' }; if ( eval "require $mod" ) { $mod->import(); } $c = Math::BigInt->new( $c ); die "Must request at least 6 digits" if $self->{ 'digits' } < 6; ( my $hex = $c->as_hex ) =~ s/^0x(.*)/"0"x(16 - length $1) . $1/e; my $bin_code = join( "", map chr hex, $hex =~ /(..)/g ); my $otp = _process( $self, $secret, $bin_code ); return $otp; } =head2 _process This is an internal routine and is never called directly. =cut sub _process { my ( $self, $secret, $bin_code ) = @_; my $hmac = Digest::HMAC->new( $secret, $self->{ 'digest' } ); $hmac->add( $bin_code ); my $hash = $hmac->digest(); my $offset = hex substr unpack( "H*" => $hash ), -1; my $dt = unpack "N" => substr $hash, $offset, 4; $dt &= 0x7fffffff; $dt = Math::BigInt->new( $dt ); my $modulus = 10 ** $self->{ 'digits' }; if ( $self->{ 'digits' } < 10 ) { return sprintf( "%0$self->{ 'digits' }d", $dt->bmod( $modulus ) ); } else { return $dt->bmod( $modulus ); } } =head1 AUTHOR Kurt Kincaid, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Authen::OATH You can also look for information at: =over 4 =item * RT: CPAN's request tracker L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS =head1 LICENSE AND COPYRIGHT Copyright 2010 Kurt Kincaid. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. =cut 1; # End of Authen::OATH ################################################################################ # EOF Authen-OATH-v1.0.0/t000755000000000000 011376774127 14464 5ustar00unknownunknown000000000000Authen-OATH-v1.0.0/t/00-load.t000444000000000000 26511376772221 16116 0ustar00unknownunknown000000000000#!perl -T use Test::More tests => 1; BEGIN { use_ok( 'Authen::OATH' ) || print "Bail out! "; } diag( "Testing Authen::OATH $Authen::OATH::VERSION, Perl $], $^X" ); Authen-OATH-v1.0.0/t/01-cases.t000444000000000000 246311376773115 16323 0ustar00unknownunknown000000000000#!perl use strict; use warnings; use Authen::OATH; use Test::Simple tests => 20; my $pwd = '12345678901234567890'; my $oath = Authen::OATH->new(); my $OATH = Authen::OATH->new( 'digits' => 8 ); ok( defined $oath, "successfully created new object" ); ok( $oath->isa( 'Authen::OATH' ), "correct class." ); ok( $oath->{ 'digits' } == 6, "default digits set to 6" ); ok( $oath->{ 'digest' } eq 'Digest::SHA1', "default digest set to Digest::SHA1" ); ok( $oath->{ 'timestep' } == 30, "default timestep set to 30" ); print "Checking test vectors for totp()...\n"; ok( $OATH->totp( $pwd, 59 ) eq "94287082" ); ok( $OATH->totp( $pwd, 1111111109 ) eq "07081804" ); ok( $OATH->totp( $pwd, 1111111111 ) eq "14050471" ); ok( $OATH->totp( $pwd, 1234567890 ) eq "89005924" ); ok( $OATH->totp( $pwd, 2000000000 ) eq "69279037" ); print "Checking test vectors for hotp()...\n"; ok( $oath->hotp( $pwd, 0 ) eq "755224" ); ok( $oath->hotp( $pwd, 1 ) eq "287082" ); ok( $oath->hotp( $pwd, 2 ) eq "359152" ); ok( $oath->hotp( $pwd, 3 ) eq "969429" ); ok( $oath->hotp( $pwd, 4 ) eq "338314" ); ok( $oath->hotp( $pwd, 5 ) eq "254676" ); ok( $oath->hotp( $pwd, 6 ) eq "287922" ); ok( $oath->hotp( $pwd, 7 ) eq "162583" ); ok( $oath->hotp( $pwd, 8 ) eq "399871" ); ok( $oath->hotp( $pwd, 9 ) eq "520489" ); Authen-OATH-v1.0.0/t/manifest.t000444000000000000 43511376772221 16567 0ustar00unknownunknown000000000000#!perl -T use strict; use warnings; use Test::More; unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => "Author tests not required for installation" ); } eval "use Test::CheckManifest 0.9"; plan skip_all => "Test::CheckManifest 0.9 required" if $@; ok_manifest(); Authen-OATH-v1.0.0/t/pod-coverage.t000444000000000000 107111376772221 17351 0ustar00unknownunknown000000000000use strict; use warnings; use Test::More; # Ensure a recent version of Test::Pod::Coverage my $min_tpc = 1.08; eval "use Test::Pod::Coverage $min_tpc"; plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" if $@; # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, # but older versions don't recognize some common documentation styles my $min_pc = 0.18; eval "use Pod::Coverage $min_pc"; plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" if $@; all_pod_coverage_ok(); Authen-OATH-v1.0.0/t/pod.t000444000000000000 36411376772221 15544 0ustar00unknownunknown000000000000#!perl -T use strict; use warnings; use Test::More; # Ensure a recent version of Test::Pod my $min_tp = 1.22; eval "use Test::Pod $min_tp"; plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; all_pod_files_ok();