File Coverage

blib/lib/Auth/Yubikey_Decrypter.pm
Criterion Covered Total %
statement 9 56 16.0
branch 0 8 0.0
condition n/a
subroutine 3 6 50.0
pod 3 3 100.0
total 15 73 20.5


line stmt bran cond sub pod time code
1             package Auth::Yubikey_Decrypter;
2              
3 1     1   20460 use warnings;
  1         3  
  1         36  
4 1     1   6 use strict;
  1         2  
  1         56  
5             require Crypt::Rijndael;
6              
7             =head1 NAME
8              
9             Auth::Yubikey_Decrypter - Decrypting the output from the yubikey token
10              
11             =head1 VERSION
12              
13             Version 0.07
14              
15             =cut
16              
17 1     1   8 use vars qw($VERSION);
  1         6  
  1         814  
18             $VERSION = '0.07';
19              
20             =head1 SYNOPSIS
21              
22             The decryption module does only one thing - decrypt the AES encrypted OTP from the Yubikey. To this, it
23             requires the OTP, and the AES key.
24              
25             Please note - this module does not perform authentication - it is a required component to decrypt the token first before authentication can be performed.
26              
27             #!/usr/bin/perl
28              
29             use strict;
30             use Auth::Yubikey_Decrypter;
31              
32             my $fulltoken = "dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh";
33             my $aeskey = "ecde18dbe76fbd0c33330f1c354871db";
34              
35             my ($publicID,$secretid_hex,$counter_dec,$timestamp_dec,$session_use_dec,$random_dec,$crc_dec,$crc_ok) =
36             Auth::Yubikey_Decrypter::yubikey_decrypt($fulltoken,$aeskey);
37              
38             print "publicID : $publicID\n";
39             print "Secret id : $secretid_hex\n";
40             print "Counter : $counter_dec\n";
41             print "Timestamp : $timestamp_dec\n";
42             print "Session : $session_use_dec\n";
43             print "Random : $random_dec\n";
44             print "crc : $crc_dec\n";
45             print "crc ok? : $crc_ok\n";
46              
47             =head1 FUNCTIONS
48              
49             =head2 yubikey_decrypt
50              
51             Input : token aeskey
52              
53             Token - received by the Yubikey
54             aeskey - either the modhex or hex AES key for your Yubikey (contact Yubico if you don't have the AES key)
55              
56             Output :
57              
58             $publicID
59             $secretid_hex
60             $counter_dec
61             $timestamp_dec
62             $session_use_dec
63             $random_dec
64             $crc_dec
65             $crc_ok
66              
67             =cut
68              
69             sub yubikey_decrypt
70             {
71 0     0 1   my $fulltoken = $_[0];
72 0           my $aeskey = $_[1];
73 0           my $aeskey_bin;
74              
75             # Let's sanitize the inut, just in case
76 0           $aeskey =~ s/[^A-Z0-9]//gi;
77 0           $fulltoken =~ s/[^A-Z0-9]//gi;
78              
79             # Determine what mode the AES key is in
80 0 0         if($aeskey =~ /^[a-f0-9]+$/i)
    0          
81             {
82 0           $aeskey_bin = pack "H*", $aeskey;
83             }
84             elsif($aeskey =~ /^[cbdefghijklnrtuv]+$/i)
85             {
86 0           $aeskey_bin = &yubikey_modhex_decode($aeskey);
87             }
88             else
89             {
90 0           die "A weird AES key was supplied. Please provide only hex or modhex.";
91             }
92              
93             # strip out the actual token
94 0           my $publicID = substr($fulltoken,0,length($fulltoken)-32);
95 0           my $token = substr($fulltoken,length($fulltoken)-32);
96              
97             # decode the token from modhex down to binary
98 0           my $token_bin = &yubikey_modhex_decode($token);
99              
100             # Decrypt the token using it's key
101              
102 0           my $cipher = Crypt::Rijndael->new( $aeskey_bin );
103 0           my $token_decoded_bin = $cipher->decrypt($token_bin);
104              
105 0           my $token_decoded_hex = unpack "H*", $token_decoded_bin;
106              
107             # get all the values from the decoded token
108 0           my $secretid_hex = substr($token_decoded_hex,0,12);
109 0           my $counter_dec = ord(substr($token_decoded_bin,7,1))*256+ord(substr($token_decoded_bin,6,1));
110 0           my $timestamp_dec = ord(substr($token_decoded_bin,10,1))*65536+ord(substr($token_decoded_bin,9,1))*256+ord(substr($token_decoded_bin,8,1));
111 0           my $session_use_dec = ord(substr($token_decoded_bin,11,1));
112 0           my $random_dec = ord(substr($token_decoded_bin,13,1))*256+ord(substr($token_decoded_bin,12,1));
113 0           my $crc_dec = ord(substr($token_decoded_bin,15,1))*256+ord(substr($token_decoded_bin,14,1));
114 0           my $crc_ok = &yubikey_crc_check($token_decoded_bin);
115              
116 0           return ($publicID,$secretid_hex,$counter_dec,$timestamp_dec,$session_use_dec,$random_dec,$crc_dec,$crc_ok);
117             }
118              
119             =head2 yubikey_modhex_decode
120              
121             Input : the modhex code
122             Output : decoded modhex code in hex
123              
124             =cut
125              
126             sub yubikey_modhex_decode
127             {
128 0     0 1   my $mstring = $_[0];
129 0           my $cset="cbdefghijklnrtuv";
130 0           my $decoded="";
131 0           my $hbyte=0;
132 0           my $pos;
133 0           for (my $i=0; $i
134             {
135 0           $pos=index($cset,substr($mstring,$i,1));
136 0 0         if ($i/2 != int($i/2))
137             {
138 0           $decoded .= chr($hbyte+$pos);
139 0           $hbyte=0;
140             }
141             else
142             {
143 0           $hbyte=$pos*16;
144             }
145             }
146 0           return $decoded;
147             }
148              
149             =head2 yubikey_crc_check
150              
151             Performs a crc check on the decoded data
152              
153             =cut
154              
155             sub yubikey_crc_check
156             {
157 0     0 1   my $buffer = $_[0];
158 0           my $m_crc=0xffff;
159 0           my $j;
160 0           for(my $bpos=0; $bpos<16; $bpos++)
161             {
162 0           $m_crc ^= ord(substr($buffer,$bpos,1)) & 0xff;
163 0           for (my $i=0; $i<8; $i++)
164             {
165 0           $j=$m_crc & 1;
166 0           $m_crc >>= 1;
167 0 0         if ($j)
168             {
169 0           $m_crc ^= 0x8408;
170             }
171             }
172             }
173 0           return $m_crc==0xf0b8;
174              
175 0           return 0;
176             }
177              
178             =head1 REQUIRES
179              
180             Perl 5, L
181              
182             Order your Yubikey from L
183              
184             =head1 BUGS
185              
186             Please report any bugs or feature requests to C, or through
187             the web interface at L. I will be notified, and then you'll
188             automatically be notified of progress on your bug as I make changes.
189              
190             =head1 SUPPORT
191              
192             You can find documentation for this module with the perldoc command.
193              
194             perldoc Auth::Yubikey_Decrypter
195              
196             You can also look for information at:
197              
198             =over 4
199              
200             =item * RT: CPAN's request tracker
201              
202             L
203              
204             =item * AnnoCPAN: Annotated CPAN documentation
205              
206             L
207              
208             =item * CPAN Ratings
209              
210             L
211              
212             =item * Search CPAN
213              
214             L
215              
216             =back
217              
218             =head1 AUTHOR
219              
220             Phil Massyn, C<< >>
221              
222             =head1 ACKNOWLEDGEMENTS
223              
224             Based a lot on PHP code by : PHP yubikey decryptor v0.1 by Alex Skov Jensen
225             Thanks to almut from L for code guidance
226             Thanks to Mark Foobar L for reporting the -32 bug on line 91 and 92.
227              
228             =head1 COPYRIGHT & LICENSE
229              
230             Copyright 2008 Phil Massyn, all rights reserved.
231              
232             This program is free software; you can redistribute it and/or modify it
233             under the same terms as Perl itself.
234              
235             =cut
236              
237             1; # End of Auth::Yubikey_Decrypter