What will you miss when this site closes?





198 votes ~ 6 comments

This site will turn read-only at the end of September 2017.

Implementing two factor authentication with perl

Posted by Steve on Wed 12 Jul 2017 at 17:23

Tags: ,

Two factor authentication is a system which is designed to improve security, by requiring a second factor, in addition to a username/password pair, to access a particular resource. Here we'll look briefly at how you add two factor support to your applications with Perl.

The two factor system we'll be looking at is the time-based TOTP algorithm (RFC6238).

In brief the TOTP protocol ensures that if two hosts have an accurate clock they can prove they both know a particular secret without actually having to reveal what that secret is. This is achieved by completing a calculation which involves the time and the secret, and then sharing the result. Much like a standard hash you can't work backwards from this public/shared value to the secret.

Becase I like coding in Perl we'll be implementing out system using the Authen::AOTH module, which is packaged for Debian GNU/Linux and installable via:

apt-get install libauthen-oath-perl libconvert-base32-perl

Once installed we'll write a simple script:

#!/usr/bin/perl

use strict;
use warnings;

use Authen::OATH;
use Convert::Base32;

#
#  Create the object.
#
my $ao = Authen::OATH->new();

#
#  This is the secret we're going to use for authentication.
#
my $e = 'my little secret!';

#
#  Encode the secret and pad it appropriately.
#
my $secret = encode_base32( $e );
$secret .= "="  while( ( length($secret) % 8 ) != 0 );

# get the expected value
my $expected = $ao->totp( $e );
print "Expected 2 factor code is : " . $expected . "\n";

print "The encoded secret is: $secret\n";

If you run this you'll receive output which looks like this:

shelob ~/x $ ./demo.pl
Expected 2 factor code is : 460745
The encoded secret is: nv4sa3djor2gyzjaonswg4tfoqqq====

This has taken our secret, and encoded it in base-32 so that it can be input to any tools we'll need in the future. It has also shown us the currently valid two-factor input "460745", which will expire within 30 seconds.

The next step is configure an actual two-factor device. If you have a mobile phone running Android you could install the Google Authenticator application. If you're sticking to Linux devices you might instead prefer to install the oathtool package - To keep things simple we'll do that:

apt-get install oathtool

Now we'll update our sample code:

#!/usr/bin/perl

use strict;
use warnings;

use Authen::OATH;
use Convert::Base32;

#
# Create the helper object.
#
my $ao = Authen::OATH->new();

#
# Encode our secret.
#
my $secret  = "This is our Debian GNU/Linux secret";
my $encoded = encode_base32( $secret );

# Pad it because some tools are strict.
$encoded .= "="  while( ( length($encoded) % 8 ) != 0 );

#
#  If we got an argument test it
#
my $code = shift;
if ( $code )
{
    my $expected = $ao->totp( $secret );

    if ( $code == $expected )
    {
        print "You passed\n";
        # here you can do more
    }
    else
    {
        print "You failed\n";
        exit(1);
    }
}
else
{
    print "Setup your device, the secret is: $encoded\n";
}

If you run this code with no arguments it will show the encoded secret - so you can add a new account to your Google authenticator, or generate the expected via the oathtool tool we previously installed. Here is what the output looks like:

$ perl demo2.pl
Setup your device, the secret is: krugs4zanfzsa33voiqeizlcnfqw4ichjzks6tdjnz2xqidtmvrxezlu

We can pass the (encoded) secret like so:

 $ oathtool --totp -b krugs4zanfzsa33voiqeizlcnfqw4ichjzks6tdjnz2xqidtmvrxezlu
272737

If you wait for more than 30 seconds you'll see the generated code has changed, as expected. You can then test the code like so:

$ oathtool --totp -b krugs4zanfzsa33voiqeizlcnfqw4ichjzks6tdjnz2xqidtmvrxezlu
368618
$ perl demo2.pl 368618
You passed

And that is how two factor authentication works. If you configured your phone with the encoded secret you'd always have the magic numbers to authenticate with in your code. If you had access to any Linux system you could generate the token / magic-number via the oathtool command, proving you knew the secret.

To ease the addition of secrets for other people you might wish to explore the Auth::GoogleAuthenticator module, which will let you generate your secret as a QR-code:


my $auth = Auth::GoogleAuthenticator->new(
                                          secret => 'This is our Debian GNU/Linux secret
                                         );

my $img = $auth->registration_qr_code( "http://example.com/" );
open( my $out, ">", "foo.jpg" );
binmode( $out );
print $out $img;
close( $out );

 

 


Re: Implementing two factor authentication with perl
Posted by Anonymous (2607:0xx:0xx:0xxx:0xxx:0xxx:xx) on Wed 9 Aug 2017 at 20:58

If you prefer python, check out OneTimePass: https://github.com/tadeck/onetimepass

[ Parent | Reply to this comment ]