From 1c1024dade63180dfb0dae96d26f9dbd7c62bb8c Mon Sep 17 00:00:00 2001 From: Alexandre Dulaunoy Date: Sun, 6 Jun 2010 19:24:09 +0200 Subject: [PATCH] First version of paper token - an application to make paper-based HOTP tokens. --- README.md | 41 +++++++++++++ examples/test.pdf | Bin 0 -> 12521 bytes paper-token.pl | 152 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 README.md create mode 100644 examples/test.pdf create mode 100644 paper-token.pl diff --git a/README.md b/README.md new file mode 100644 index 0000000..68b67fc --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +paper token +=========== + +paper token is a PDF generator to create paper-based OTP token. + +perl requirements +----------------- + +* Authen::HOTP +* PDF::API2 +* PDF::Table +* Getopt::Compact + +how to use it +============= + +perl paper-token.pl --output test.pdf --counter 0 --end 200 --secret 3132333435363738393031323334353637383930 --digits 6 + +OpenOTP server installation +=========================== + +* For more information - http://www.foo.be/cgi-bin/wiki.pl/SettingOOTP + +LICENSE +======= + +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 +along with this program. If not, see . + diff --git a/examples/test.pdf b/examples/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..08b1430369efe594f238f6fbfbd293176ab3266a GIT binary patch literal 12521 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 literal 0 HcmV?d00001 diff --git a/paper-token.pl b/paper-token.pl new file mode 100644 index 0000000..ad45444 --- /dev/null +++ b/paper-token.pl @@ -0,0 +1,152 @@ +#!/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.foo.be/paper-token/', + 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.foo.be/paper-token/ at " . $when; + +$pdf->info( + 'Author' => "Alexandre Dulaunoy - http://www.foo.be/", + 'Creator' => "Paper Token - http://www.foo.be/paper-token/", + 'Producer' => "PDF::API2", + 'Title' => $tokeninfo, +); + +$fnt = $pdf->corefont('Helvetica-Bold'); +$fntlow = $pdf->corefont('Helvetica'); + +$gfx->textlabel( 10, 750, $fnt, 11, $tokeninfo ); +$gfx->textlabel( 10, 739, $fntlow, 11, $tokenhowto ); +$gfx->textlabel( 10, 728, $fntlow, 11, $tokenadv ); + +$pdftable->table( + $pdf, + $page, + @tokentable, + -x => 1, + -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(); +