#!/usr/bin/env perl # # poly1305aes.pl - a sample implementation of Poly1305 in Perl # version 0.10 - 2005-01-26 # by Toby Betts # # Public domain. # # See for more information. # # Requires the Crypt::Rijndael module for AES encryption. # use Math::BigInt; use Crypt::Rijndael; use strict; use warnings; sub aes { my ($k,$n) = @_; my $cipher = new Crypt::Rijndael(pack('H*',$k), Crypt::Rijndael::MODE_CBC); return (unpack('C*',$cipher->encrypt(pack('H*',$n)))); } sub poly1305aes_sample { my ($k,$r,$n,$m,$l) = @_; my $rinteger = new Math::BigInt("0x".unpack('H*',pack('C*',reverse(unpack('C*',pack('H*',$r)))))); my $h = new Math::BigInt(); $h->bzero(); my $p = new Math::BigInt('1361129467683753853853498429727072845819'); my $j = 0; while (0 < $l) { my $c = new Math::BigInt(); $c->bzero(); my @reverse_m; for ($j = 0; (16 > $j) && ($j < $l); $j++) { push(@reverse_m,shift(@$m)); } $c->badd("0x1" . unpack('H*',pack('C*',reverse(@reverse_m)))); $l -= $j; $h->badd($c); $h->bmul($rinteger); $h->bmod($p); } my @aesarray = &aes($k,$n); my $reverse_aes = new Math::BigInt("0x" . unpack('H*',pack('C*',reverse(@aesarray)))); $h->badd($reverse_aes); my @out; for ($j = 0; $j < 16; $j++) { my $t = new Math::BigInt(); $t = $h->copy(); push(@out,$t->bmod(256)); $h->brsft(8); } return unpack('H*',pack('C*',@out)); } my %test = ( 'key'=>['ec074c835580741701425b623235add6', '75deaa25c09f208e1dc4ce6b5cad3fbf', '6acb5f61a7176dd320c5c1eb2edcdc74', 'e1a5668a4d5b66a5f68cc5424ed5982d'] , 'nonce'=>['fb447350c4e868c52ac3275cf9d4327e', '61ee09218d29b0aaed7e154a2c5509cc', 'ae212a55399729595dea458bc621ff0e', '9ae831e743978d3a23527c7128149e3a'] , 'r'=>['851fc40c3467ac0be05cc20404f3f700', 'a0f3080000f46400d0c7e9076c834403', '48443d0bb0d21109c89a100b5ce2c208', '12976a08c4426d0ce8a82407c4f48207'] , 'msg'=>['f3f6', '', '663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136', 'ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9'] , 'result'=>['f4c633c3044fc145f84f335cb81953de', 'dd3fab2251f11ac759f0887129cc2ee7', '0ee1c16bb73f0f4fd19881753c01cdbe', '5154ad0d2cb26e01274fc51148491f1b'] ); for (my $i = 0; $i < scalar @{ $test{'key'} }; $i++) { my $k = $test{'key'}[$i]; my $n = $test{'nonce'}[$i]; my $r = $test{'r'}[$i]; my @m = unpack('C*',pack('H*',$test{'msg'}[$i])); my $result = $test{'result'}[$i]; my $out = poly1305aes_sample($k,$r,$n,\@m,scalar @m); print $i . ": expected=$result\n actual=$out ["; if ($out eq $result) { print "OK"; } else { print "FAILED"; } print "]\n"; }