#!/usr/bin/perl -w # # paper token is a software to generate paper-based OTP # # Copyright (C) 2010 Alexandre Dulaunoy, http://www.foo.be/ # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License use Authen::HOTP qw(hotp); use PDF::API2; use PDF::Table; use Data::Dumper; use Getopt::Compact; # default value is the test vector from RFC 4226 my $secret = "3132333435363738393031323334353637383930"; # starting counter my $counter = 0; # ending counter my $end = 500; my $digits = 6; my @tokentable = []; # window value (shown on one line and window of accepted token) my $window = 14; my $when = localtime(); my $opt = new Getopt::Compact( name => 'paper token - http://www.quuxlabs.com/?p=431', modes => '', version => '0.1', struct => [ [ [qw(s secret)], qq(secret of the token in hex format - default is RFC 4226 test vector), ':s' ], [ [qw(o output)], qq(output filename), ':s' ], [ [qw(c counter)], qq(starting counter - default is 0), ':i' ], [ [qw(e end)], qq(ending counter - default is 500), ':i' ], [ [qw(w window)], qq(window of authentication (one line) - default is 14), ':i' ], [ [qw(d digits)], qq(digits showed per OTP value - default is 6 - dec31.6), ':i' ], ] ); my $opts = $opt->opts; if ( !( defined( $opts->{output} ) ) ) { print $opt->usage; exit(); } if ( defined( $opts->{counter} ) ) { $counter = $opts->{counter}; } if ( defined( $opts->{end} ) ) { $end = $opts->{end}; } if ( defined( $opts->{window} ) ) { $window = $opts->{window}; } if ( defined( $opts->{secret} ) ) { $secret = $opts->{secret}; } my $sn = substr( $secret, 0, 10 ); if ( defined( $opts->{digits} ) ) { $digits = $opts->{digits}; } for ( $count = $counter ; $count < $counter + $end ; $count = $count + $window ) { my @tj; for ( $j = $count ; $j < $count + $window ; $j = $j + 1 ) { my $pass = hotp( $secret, $j, $digits ); push( @tj, "$pass" ); } @val = ["@tj"]; push( @{ $tokentable[0] }, @val ); } my $pdftable = new PDF::Table; my $pdf = new PDF::API2( -file => $opts->{output} ); my $page = $pdf->page; my $gfx = $page->gfx; my $tokeninfo = "Paper token for HOTP token S/N : " . $sn; my $tokenhowto = "How to use? Read from left to right and when you use a token, strikethrough the used value."; my $tokenadv = "Generated by paper token (http://www.quuxlabs.com/?p=431) at " . $when; $pdf->info( 'Author' => "Alexandre Dulaunoy - http://www.foo.be/", 'Creator' => "Paper Token - http://www.quuxlabs.com/?p=431", 'Producer' => "PDF::API2", 'Title' => $tokeninfo, ); $fnt = $pdf->corefont('Helvetica-Bold'); $fntlow = $pdf->corefont('Helvetica'); $gfx->textlabel( 20, 750, $fnt, 11, $tokeninfo ); $gfx->textlabel( 20, 739, $fntlow, 11, $tokenhowto ); $gfx->textlabel( 20, 728, $fntlow, 11, $tokenadv ); $pdftable->table( $pdf, $page, @tokentable, -x => 20, -w => 40, -start_y => 700, -next_y => 700, -start_h => 700, -next_h => 700, -w => 600, -padding => 2, -padding_right => 1, -background_color_odd => "lightgray", -background_color_even => "gray", font => $pdf->corefont( "Helvetica", -encoding => "utf8" ), font_size => 11, border => 0 ); $pdf->save();