File Coverage

blib/lib/Crypt/AES/CTR.pm
Criterion Covered Total %
statement 235 241 97.5
branch 23 30 76.6
condition 20 53 37.7
subroutine 22 23 95.6
pod 4 4 100.0
total 304 351 86.6


line stmt bran cond sub pod time code
1             ##################################################################################################
2             # This is an unofficial port of Chris Veness' AES implementation #
3             # (c) Chris Veness 2005-2011. Right of free use is #
4             # granted for all commercial or non-commercial use under CC-BY 3.0 licence. No warranty of #
5             # any form is offered. More info at http://www.movable-type.co.uk/scripts/aes.html #
6             ##################################################################################################
7             package Crypt::AES::CTR;
8            
9 2     2   20856 use 5.006;
  2         7  
  2         85  
10 2     2   19 use strict;
  2         5  
  2         75  
11 2     2   11 use warnings FATAL => 'all';
  2         17  
  2         100  
12 2     2   1892 use Encode;
  2         170054  
  2         214  
13 2     2   2019 use POSIX;
  2         16033  
  2         20  
14 2     2   11571 use MIME::Base64;
  2         1665  
  2         141  
15 2     2   1801 use Time::HiRes;
  2         4131  
  2         12  
16 2     2   3526 use Math::BigInt;
  2         54684  
  2         16  
17            
18 2     2   34688 use vars qw(@ISA @EXPORT_OK $VERSION $sBox $rCon $padding);
  2         4  
  2         5723  
19            
20             require Exporter;
21             @ISA = qw(Exporter);
22             @EXPORT_OK = qw(encrypt decrypt);
23            
24            
25             =head1 NAME
26            
27             Crypt::AES::CTR - This is a port of Chris Veness' AES implementation.
28            
29             =head1 VERSION
30            
31             Version 0.03
32            
33             =cut
34            
35             $VERSION = '0.03';
36            
37             $padding="\n";
38            
39             # sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [§5.1.1]
40             $sBox=[
41             0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
42             0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
43             0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
44             0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
45             0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
46             0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
47             0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
48             0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
49             0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
50             0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
51             0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
52             0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
53             0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
54             0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
55             0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
56             0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
57             ];
58            
59             # rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
60             $rCon=[
61            
62             [(0x00, 0x00, 0x00, 0x00)],
63             [(0x01, 0x00, 0x00, 0x00)],
64             [(0x02, 0x00, 0x00, 0x00)],
65             [(0x04, 0x00, 0x00, 0x00)],
66             [(0x08, 0x00, 0x00, 0x00)],
67             [(0x10, 0x00, 0x00, 0x00)],
68             [(0x20, 0x00, 0x00, 0x00)],
69             [(0x40, 0x00, 0x00, 0x00)],
70             [(0x80, 0x00, 0x00, 0x00)],
71             [(0x1b, 0x00, 0x00, 0x00)],
72             [(0x36, 0x00, 0x00, 0x00)]
73            
74             ];
75            
76            
77            
78            
79             =head1 SYNOPSIS
80            
81             This module encrypts and decrypts AES strings using CTR and Chris Veness' AES implementation. It is compatible with PHP encrypting and decrypting.
82            
83             use Crypt::AES::CTR;
84            
85             my $plaintext 'string';
86             my $ciphertext = Crypt::AES::CTR::encrypt($plaintext,'password',256);
87             $plaintext = Crypt::AES::CTR::decrypt($ciphertext,'password',256);
88            
89            
90             =head1 SUBROUTINES/METHODS
91            
92             =head2 encrypt($plaintext, $key, $nbits)
93            
94             Encrypt a text using AES encryption in Counter mode of operation
95            
96             Unicode multi-byte character safe
97            
98             $plaintext - plaintext Source text to be encrypted
99             $key - The password to use to generate a key
100             $nbits - Number of bits to be used in the key (128, 192, or 256)
101            
102             returns encrypted text string
103            
104             =cut
105            
106            
107             sub encrypt {
108 2     2 1 820 my ($self,$plaintext,$password,$nBits,$keySchedule,$pad);
109            
110 2 100       9 if (ref($_[0]) eq 'Crypt::AES::CTR') { #check for oo
111 1         2 $self=shift;
112 1         3 $plaintext=shift;
113 1   33     6 $password=shift||$self->{password};
114 1   33     6 $nBits=shift||$self->{nbits};
115 1 50 33     9 $keySchedule=$self->{keyschedule} if ($password eq $self->{password} and $nBits eq $self->{nbits});
116 1         2 $pad=$self->{padding};
117             } else {
118 1         2 $plaintext=shift;
119 1         2 $password=shift;
120 1   50     5 $nBits=shift||0;
121 1         2 $pad=$padding;
122             }
123            
124            
125 2         4 my $blockSize = 16; # block size fixed at 16 bytes / 128 bits (Nb=4) for AES
126 2 50 33     20 if (!($nBits==128 or $nBits==192 or $nBits==256)) { return ''; } # standard allows 128/192/256 bit keys
  0   33     0  
127 2         11 $plaintext = Encode::encode_utf8($plaintext);
128 2 100       17 $keySchedule=_key($password,$nBits) if !defined($keySchedule);
129            
130             # initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A §B.2): [0-1] = millisec,
131             # [2-3] = random, [4-7] = seconds, together giving full sub-millisec uniqueness up to Feb 2106
132 2         10 my @counterBlock = (('') x $blockSize);
133            
134 2         47 my $nonce = sprintf('%.3f',Time::HiRes::time());
135 2         9 my ($nonceSec,$nonceMs) = split/\./, $nonce;
136 2         67 my $nonceRnd = floor(rand(0.99999999)*0xffff);
137            
138 2         8 for (my $i=0; $i<2; $i++) { $counterBlock[$i] = _urs($nonceMs , $i*8) & 0xff;}
  4         11  
139 2         8 for (my $i=0; $i<2; $i++) { $counterBlock[$i+2] = _urs($nonceRnd , $i*8) & 0xff;}
  4         9  
140 2         6 for (my $i=0; $i<4; $i++) { $counterBlock[$i+4] = _urs($nonceSec , $i*8) & 0xff;}
  8         15  
141            
142             # and convert it to a string to go on the front of the ciphertext
143 2         4 my $ctrTxt = '';
144 2         7 for (my $i=0; $i<8; $i++) { $ctrTxt .= chr($counterBlock[$i]); }
  16         39  
145            
146             # generate key schedule - an expansion of the key into distinct Key Rounds for each round
147 2         17 my $blockCount = ceil(length($plaintext)/$blockSize);
148 2         5 my @ciphertxt = ('') x $blockCount; # ciphertext as array of strings
149            
150 2         7 for (my $b=0; $b<$blockCount; $b++) {
151             # set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
152             # done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
153 2         8 for (my $c=0; $c<4; $c++) { $counterBlock[15-$c] = _urs($b , $c*8) & 0xff; }
  8         16  
154 2         7 for (my $c=0; $c<4; $c++) {
155             # $counterBlock[15-$c-4] = _urs($b/0x100000000 , $c*8);
156 8         37 my $x = Math::BigInt->new($b);
157 8         823 $x->bdiv('0x100000000');
158 8         2093 $counterBlock[15-$c-4] = _urs($x , $c*8);
159             }
160 2         7 my $cipherCntr = _cipher(\@counterBlock, $keySchedule,0); # -- encrypt counter block --
161             # block size is reduced on final block
162 2 50       11 my $blockLength = $b<$blockCount-1 ? $blockSize : (length($plaintext)-1)%$blockSize+1;
163 2         8 my @cipherChar = (('') x $blockLength);
164            
165 2         7 for (my $i=0; $i<$blockLength; $i++) { # -- xor plaintext with ciphered counter char-by-char --
166 22         44 $cipherChar[$i] = $cipherCntr->[$i] ^ ord(substr($plaintext, $b*$blockSize+$i, 1));
167 22         72 $cipherChar[$i] = chr($cipherChar[$i]);
168             }
169 2         18 $ciphertxt[$b] = join('',@cipherChar);
170            
171             }
172 2         7 my $ciphertext = $ctrTxt . join('',@ciphertxt);
173 2         1052 $ciphertext = MIME::Base64::encode_base64($ciphertext,$pad); #// encode in base64
174            
175            
176 2         80 return $ciphertext;
177             }
178            
179            
180             =head2 decrypt($ciphertext, $key, $nbits)
181            
182             Decrypt a text encrypted by AES in counter mode of operation
183            
184             $ciphertext - Source text to be decrypted
185             $key - The password to use to generate a key
186             $nbits - Number of bits to be used in the key (128, 192, or 256)
187            
188             returns decrypted text
189            
190             =cut
191            
192             sub decrypt {
193 2     2 1 4521 my ($self,$ciphertext,$password,$nBits,$keySchedule);
194            
195 2 100       12 if (ref($_[0]) eq 'Crypt::AES::CTR') { #check for oo
196 1         2 $self=shift;
197 1         2 $ciphertext=shift;
198 1   33     7 $password=shift||$self->{password};
199 1   33     6 $nBits=shift||$self->{nbits};
200 1 50 33     11 $keySchedule=$self->{keyschedule} if ($password eq $self->{password} and $nBits eq $self->{nbits});
201             } else {
202 1         2 $ciphertext=shift;
203 1         2 $password=shift;
204 1   50     6 $nBits=shift||0;
205             }
206            
207 2         4 my $blockSize = 16; # block size fixed at 16 bytes / 128 bits (Nb=4) for AES
208 2 50 33     21 if (!($nBits==128 || $nBits==192 || $nBits==256)){
      33        
209 0         0 return ''; # standard allows 128/192/256 bit keys
210             }
211 2         10 $ciphertext = MIME::Base64::decode_base64($ciphertext);
212 2 100       8 $keySchedule=_key($password,$nBits) if !defined($keySchedule);
213            
214             # recover nonce from 1st element of ciphertext
215 2         5 my @counterBlock = ();#array
216 2         5 my $ctrTxt = substr($ciphertext, 0, 8);
217 2         6 for (my $i=0; $i<8; $i++){
218 16         33 $counterBlock[$i] = ord(substr($ctrTxt,$i,1));
219             }
220            
221            
222             # separate ciphertext into blocks (skipping past initial 8 bytes)
223 2         9 my $nBlocks = ceil((length($ciphertext)-8) / $blockSize);
224 2         7 my @ct = ('') x $nBlocks;#array
225 2         5 for ($b=0; $b<$nBlocks; $b++){
226 2         9 $ct[$b] = substr($ciphertext, 8+$b*$blockSize, 16);
227             }
228 2         3 my @ciphertext = @ct; # ciphertext is now array of block-length strings
229            
230             # plaintext will get generated block-by-block into array of block-length strings
231 2         4 my @plaintxt = ('') x $#ciphertext;#array
232            
233 2         7 for (my $b=0; $b<$nBlocks; $b++) {
234             # set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
235 2         17 for (my $c=0; $c<4; $c++){
236 8         16 $counterBlock[15-$c] = _urs($b, $c*8) & 0xff;
237             }
238 2         12 for (my $c=0; $c<4; $c++){
239             #$counterBlock[15-$c-4] = _urs(($b+1)/0x100000000-1, $c*8) & 0xff;
240 8         807 my $x = Math::BigInt->new(($b+1));
241 8         241 $x->bdiv('0x100000000');
242 8         1885 $counterBlock[15-$c-4] = _urs($x, $c*8) & 0xff;
243             }
244 2         258 my $cipherCntr = _cipher(\@counterBlock, $keySchedule); # encrypt counter block
245 2         8 my @plaintxtByte = ('') x length($ciphertext[$b]);#array
246 2         7 for (my $i=0; $i
247             # -- xor plaintext with ciphered counter byte-by-byte --
248 22         33 $plaintxtByte[$i] = $cipherCntr->[$i] ^ ord(substr($ciphertext[$b],$i,1));
249 22         49 $plaintxtByte[$i] = chr($plaintxtByte[$i]);
250             }
251 2         16 $plaintxt[$b] = join('', @plaintxtByte); #php implode
252             }
253            
254             # join array of blocks into single plaintext string
255 2         6 my $plaintext = join('',@plaintxt);
256 2         13 $plaintext = Encode::decode_utf8($plaintext); #decode from UTF8 back to Unicode multi-byte chars
257 2         134 return $plaintext;
258             }
259            
260             =head2 aes_padding($padding)
261            
262             Override default padding(\n) for base64 encodes
263            
264             =cut
265            
266 0     0 1 0 sub aes_padding { $padding=shift; }
267            
268             =head1 OO-INTERFACE
269            
270             =head2 new
271            
272             my $crypt = Crypt::AES::CTR->new( key=>$key, nbits=>$nbits , padding => $padding );
273            
274             #Unicode multi-byte character safe
275            
276             #$key - The password to use to generate a key
277             #$nbits - Number of bits to be used in the key (128, 192, or 256)
278             #$padding - What to use as padding for base64 encodes, default is \n (optional)
279            
280             #returns blessed reference
281            
282             $crypt->encrypt($plaintext); # use cached $key and $nbits from new declaration
283             $crypt->encrypt($plaintext, $key, $nbits); #override $key and $nbits
284            
285             # see documentation above for encrypt function
286            
287             $crypt->decrypt($plaintext); # use cached $key and $nbits from new declaration
288             $crypt->decrypt($plaintext, $key, $nbits); #override $key and $nbits
289            
290             # see documentation above for decrypt function
291            
292             =cut
293            
294             # 00-style interface
295             sub new {
296 1     1 1 849 my $class = shift;
297 1         2 my $self = {};
298 1         5 my %new = @_;
299 1   50     7 bless($self, ($class||'Crypt::AES::CTR') );
300 1         10 $self->{password}=$new{key};
301 1   50     6 $self->{nbits}=$new{nbits}||0;
302 1 50 33     21 if (!($self->{nbits}==128 || $self->{nbits}==192 || $self->{nbits}==256)){
      33        
303 0         0 return ''; # standard allows 128/192/256 bit keys
304             }
305 1   33     6 $self->{padding}=$new{padding}||$padding;
306 1         5 $self->{keyschedule}=_key($self->{password},$self->{nbits});
307 1         7 return $self;
308             }
309            
310             # Unsigned right shift function, since Perl has neither >>> operator nor unsigned ints
311             #
312             # @param a number to be shifted (32-bit integer)
313             # @param b number of bits to shift a to the right (0..31)
314             # @return a right-shifted and zero-filled by b bits
315             #
316             sub _urs {
317 48     48   67 my($xa, $b) = @_;
318 48         83 $xa &= 0xffffffff; $b &= 0x1f; # (bounds check)
  48         2533  
319 48 50 33     117 if ($xa&0x80000000 && $b>0) { # if left-most bit set
320 0         0 $xa = ($xa>>1) & 0x7fffffff; # right-shift one bit & clear left-most bit
321 0         0 $xa = $xa >> ($b-1); # remaining right-shifts
322             } else { # otherwise
323 48         3132 $xa = ($xa>>$b); # use normal right-shift
324             }
325 48         2333 return $xa;
326             }
327            
328             # Handle key and keyschedule
329             sub _key {
330 3     3   6 my $password = shift;
331 3         4 my $nBits = shift;
332 3         13 $password = Encode::encode_utf8($password);
333            
334             # use AES itself to encrypt password to get cipher key (using plain password as source for key
335             # expansion) - gives us well encrypted key (though hashed key might be preferred for prod'n use)
336 3         23 my $nBytes = $nBits/8; # no bytes in key (16/24/32)
337 3         18 my @pwBytes = ('') x $nBytes;
338 3         12 for (my $i=0; $i<$nBytes; $i++) { # use 1st 16/24/32 chars of password for key
339 96 100       259 $pwBytes[$i] = ($i>=length($password)) ? 0:ord(substr($password,$i,1));
340             }
341            
342 3         12 my $key = _cipher(\@pwBytes, _keyExpansion(\@pwBytes)); # gives us 16-byte key
343            
344             #$key = [ @{$key},splice($key,0, $nBytes-16) ]; # expand key to 16/24/32 bytes long
345 3         43 $key = [ @{$key}, map{ $key->[$_] } (0..($nBytes-16-1)) ]; # expand key to 16/24/32 bytes long
  3         16  
  48         88  
346            
347             # generate key schedule - an expansion of the key into distinct Key Rounds for each round
348 3         15 my $keySchedule = _keyExpansion($key);
349            
350 3         26 return $keySchedule;
351             }
352            
353             # AES Cipher function: encrypt 'input' with Rijndael algorithm
354             #
355             # @param input message as byte-array (16 bytes)
356             # @param w key schedule as 2D byte-array (Nr+1 x Nb bytes) -
357             # generated from the cipher key by keyExpansion()
358             # @return ciphertext as byte-array (16 bytes)
359             #
360             sub _cipher { # main cipher function [§5.1]
361 7     7   13 my $input = shift;
362 7         10 my $w = shift;
363            
364 7         8 my $Nb = 4; # block size (in words): no of columns in state (fixed at 4 for AES)
365 7         14 my $Nr = scalar(@{$w})/$Nb - 1; # no of rounds: 10/12/14 for 128/192/256-bit keys
  7         20  
366            
367 7         18 my $state = [[],[],[],[]]; # initialise 4xNb byte-array 'state' with input [§3.4]
368 7         20 for(my $i=0; $i<4*$Nb; $i++){
369 112         448 $state->[$i%4][floor($i/4)] = $input->[$i];
370             }
371            
372 7         15 $state = _addRoundKey($state, $w, 0, $Nb);
373 7         19 for(my $round=1; $round<$Nr; $round++) { # apply Nr rounds
374 91         144 $state = _subBytes($state, $Nb);
375 91         162 $state = _shiftRows($state, $Nb);
376 91         163 $state = _mixColumns($state, $Nb);
377 91         163 $state = _addRoundKey($state, $w, $round, $Nb);
378             }
379 7         13 $state = _subBytes($state, $Nb);
380 7         14 $state = _shiftRows($state, $Nb);
381 7         24 $state = _addRoundKey($state, $w, $Nr, $Nb);
382 7         60 my @output = ('') x (4*$Nb); # convert state to 1-d array before returning [§3.4]
383 7         23 for (my $i=0; $i<4*$Nb; $i++){
384 112         411 $output[$i] = $state->[$i%4][floor($i/4)];
385             }
386            
387 7         36 return \@output;
388             }
389            
390             # Key expansion for Rijndael cipher(): performs key expansion on cipher key
391             # to generate a key schedule
392             #
393             # @param key cipher key byte-array (16 bytes)
394             # @return key schedule as 2D byte-array (Nr+1 x Nb bytes)
395             #
396            
397             sub _keyExpansion { # generate Key Schedule from Cipher Key [§5.2]
398 6     6   10 my $key = shift;
399 6         8 my $Nb = 4; # block size (in words): no of columns in state (fixed at 4 for AES)
400 6         8 my $Nk = scalar(@{$key})/4; # key length (in words): 4/6/8 for 128/192/256-bit keys
  6         37  
401 6         10 my $Nr = $Nk + 6; # no of rounds: 10/12/14 for 128/192/256-bit keys
402            
403 6         63 my @w = ('') x ($Nb*($Nr+1));#array
404 6         19 for(my $i=0; $i<$Nb*($Nr+1); $i++){
405 360         770 $w[$i] = 0;
406             }
407 6         14 my @temp = ('0') x 4;#array
408 6         17 for(my $i=0; $i<$Nk; $i++) {
409 48         123 my $r = [$key->[4*$i], $key->[4*$i+1], $key->[4*$i+2], $key->[4*$i+3]];
410 48         119 $w[$i] = $r;
411             }
412            
413            
414 6         20 for (my $i=$Nk; $i<($Nb*($Nr+1)); $i++) {
415 312         706 $w[$i] = [(('0') x 4)];#array
416            
417 312         610 for (my $t=0; $t<4; $t++){
418 1248         2549 $temp[$t] = $w[$i-1][$t];
419             }
420 312 100 66     1225 if($i % $Nk == 0){
    100          
421 42         78 my $temp1 = _rotWord(\@temp);
422 42         69 my $temp2 = _subWord($temp1);
423 42         91 @temp = @$temp2;
424            
425            
426 42         89 for (my $t=0; $t<4; $t++){
427 168         404 $temp[$t] ^= $rCon->[$i/$Nk][$t];
428             }
429            
430             } elsif ($Nk > 6 and ($i % $Nk) == 4) {
431            
432 36         55 my $temp2 = _subWord(\@temp);
433 36         95 @temp = @$temp2;
434            
435            
436             }
437 312         580 for (my $t=0; $t<4; $t++){
438 1248         3480 $w[$i][$t] = $w[$i-$Nk][$t] ^ $temp[$t];
439             }
440            
441             }
442            
443 6         20 return \@w;
444             }
445            
446            
447            
448            
449             # ---- remaining routines are private, not called externally ----
450            
451             sub _subBytes { # apply SBox to state S [§5.1.1]
452 98     98   110 my $s = shift;
453 98         119 my $Nb = shift;
454            
455 98         199 for (my $r=0; $r<4; $r++) {
456 392         868 for (my $c=0; $c<$Nb; $c++){
457 1568         7070 $s->[$r][$c] = $sBox->[$s->[$r][$c]];
458             }
459             }
460 98         169 return $s;
461             }
462            
463             sub _shiftRows { # shift row r of state S left by r bytes [§5.1.2]
464 98     98   107 my $s = shift;
465 98         102 my $Nb = shift;
466            
467 98         380 my @t = ('') x 4;#array
468 98         209 for (my $r=1; $r<4; $r++) {
469 294         522 for(my $c=0; $c<4; $c++){
470 1176         3161 $t[$c] = $s->[$r][($c+$r)%$Nb]; # shift into temp copy
471             }
472 294         709 for(my $c=0; $c<4; $c++){
473 1176         3305 $s->[$r][$c] = $t[$c]; # and copy back
474             }
475             }# note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
476 98         389 return $s; # see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
477             }
478            
479             sub _mixColumns { # combine bytes of each col of state S [§5.1.3]
480 91     91   105 my $s = shift;
481 91         103 my $Nb = shift;
482            
483 91         184 for(my $c=0; $c<4; $c++) {
484 364         885 my @a = ('') x 4; # 'a' is a copy of the current column from 's'
485 364         806 my @b = ('') x 4; # 'b' is a•{02} in GF(2^8)
486 364         716 for(my $i=0; $i<4; $i++) {
487 1456         2333 $a[$i] = $s->[$i][$c];
488 1456 100       4945 $b[$i] = $s->[$i][$c]&0x80 ? $s->[$i][$c]<<1 ^ 0x011b : $s->[$i][$c]<<1;
489            
490             }
491             # a[n] ^ b[n] is a•{03} in GF(2^8) #MYFIXED $xb
492 364         1215 $s->[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; # 2*a0 + 3*a1 + a2 + a3
493 364         565 $s->[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; # a0 * 2*a1 + 3*a2 + a3
494 364         497 $s->[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; # a0 + a1 + 2*a2 + 3*a3
495 364         1351 $s->[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; # 3*a0 + a1 + a2 + 2*a3
496            
497            
498            
499             }
500 91         149 return $s;
501             }
502            
503             sub _addRoundKey { # xor Round Key into state S [§5.1.4]
504 105     105   161 my($state, $w, $rnd, $Nb) = @_;
505            
506 105         207 for (my $r=0; $r<4; $r++) {
507 420         756 for (my $c=0; $c<$Nb; $c++){
508 1680         6985 $state->[$r][$c] ^= $w->[$rnd*4+$c][$r];
509             }
510             }
511            
512 105         303 return $state;
513             }
514            
515            
516             sub _subWord { # apply SBox to 4-byte word w
517 78     78   84 my $w = shift;
518 78         162 for(my $i=0; $i<4; $i++){
519 312         651 $w->[$i] = $sBox->[$w->[$i]];
520             }
521 78         111 return $w;
522             }
523            
524             sub _rotWord { # rotate 4-byte word w left by one byte
525 42     42   51 my $w = shift;
526            
527 42         55 my $tmp = $w->[0];
528 42         104 for(my $i=0; $i<3; $i++){
529 126         266 $w->[$i] = $w->[$i+1];
530             }
531 42         47 $w->[3] = $tmp;
532 42         72 return $w;
533             }
534            
535            
536            
537            
538            
539            
540             =head1 AUTHOR
541            
542             KnowZero
543            
544             =head1 BUGS
545            
546             Please report any bugs or feature requests to C, or through
547             the web interface at L. I will be notified, and then you'll
548             automatically be notified of progress on your bug as I make changes.
549            
550            
551            
552            
553             =head1 SUPPORT
554            
555             You can find documentation for this module with the perldoc command.
556            
557             perldoc Crypt::AES::CTR
558            
559            
560             You can also look for information at:
561            
562             =over 4
563            
564             =item * RT: CPAN's request tracker (report bugs here)
565            
566             L
567            
568             =item * AnnoCPAN: Annotated CPAN documentation
569            
570             L
571            
572             =item * CPAN Ratings
573            
574             L
575            
576             =item * Search CPAN
577            
578             L
579            
580             =back
581            
582            
583             =head1 ACKNOWLEDGEMENTS
584            
585            
586             =head1 LICENSE AND COPYRIGHT
587            
588             This is an unofficial port of Chris Veness' AES implementation
589             Copyright (C) Chris Veness 2005-2011. Right of free use is granted for all commercial or non-commercial use under CC-BY 3.0 licence. No warranty of any form is offered.
590            
591             Released under the
592             L
593             Creative Commons Attribution 3.0 Unported License
594            
595             For more information:
596             L
597            
598             =cut
599            
600             1; # End of Crypt::AES::CTR