source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/AES.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

  • Property svn:executable set to *
File size: 18.6 KB
Line 
1#------------------------------------------------------------------------------
2# File: AES.pm
3#
4# Description: AES encryption with cipher-block chaining
5#
6# Revisions: 2010/10/14 - P. Harvey Created
7#
8# References: 1) http://www.hoozi.com/Articles/AESEncryption.htm
9# 2) http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
10# 3) http://www.faqs.org/rfcs/rfc3602.html
11#------------------------------------------------------------------------------
12
13package Image::ExifTool::AES;
14
15use strict;
16use vars qw($VERSION @ISA @EXPORT_OK);
17require Exporter;
18
19$VERSION = '1.01';
20@ISA = qw(Exporter);
21@EXPORT_OK = qw(Crypt);
22
23my $seeded; # flag set if we already seeded random number generator
24my $nr; # number of rounds in AES cipher
25my @cbc; # cipher-block chaining bytes
26
27# arrays (all unsigned character) to hold intermediate results during encryption
28my @state = ([],[],[],[]); # the 2-dimensional state array
29my @RoundKey; # round keys
30
31my @sbox = (
32 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
33 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
34 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
35 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
36 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
37 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
38 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
39 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
40 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
41 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
42 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
43 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
44 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
45 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
46 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
47 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
48);
49
50# reverse sbox
51my @rsbox = (
52 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
53 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
54 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
55 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
56 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
57 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
58 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
59 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
60 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
61 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
62 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
63 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
64 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
65 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
66 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
67 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
68);
69
70# the round constant word array, $rcon[i], contains the values given by
71# x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
72# Note that i starts at 1, not 0).
73my @rcon = (
74 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
75 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
76 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
77 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
78 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
79 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
80 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
81 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
82 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
83 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
84 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
85 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
86 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
87 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
88 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
89 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,
90);
91
92#------------------------------------------------------------------------------
93# This function produces 4*($nr+1) round keys.
94# The round keys are used in each round to encrypt the states.
95# Inputs: 0) key string (must be 16, 24 or 32 bytes long)
96sub KeyExpansion($)
97{
98 my $key = shift;
99 my @key = unpack 'C*', $key; # convert the key into a byte array
100 my $nk = int(length($key) / 4); # number of 32-bit words in the key
101 $nr = $nk + 6; # number of rounds
102
103 # temporary variables (all unsigned characters)
104 my ($i,@temp);
105
106 # The first round key is the key itself.
107 for ($i=0; $i<$nk; ++$i) {
108 @RoundKey[$i*4..$i*4+3] = @key[$i*4..$i*4+3];
109 }
110 # All other round keys are found from the previous round keys.
111 while ($i < (4 * ($nr+1))) {
112
113 @temp[0..3] = @RoundKey[($i-1)*4..($i-1)*4+3];
114
115 if ($i % $nk == 0) {
116 # rotate the 4 bytes in a word to the left once
117 # [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
118 @temp[0..3] = @temp[1,2,3,0];
119
120 # take a four-byte input word and apply the S-box
121 # to each of the four bytes to produce an output word.
122 @temp[0..3] = @sbox[@temp[0..3]];
123
124 $temp[0] = $temp[0] ^ $rcon[$i/$nk];
125
126 } elsif ($nk > 6 && $i % $nk == 4) {
127
128 @temp[0..3] = @sbox[@temp[0..3]];
129 }
130 $RoundKey[$i*4+0] = $RoundKey[($i-$nk)*4+0] ^ $temp[0];
131 $RoundKey[$i*4+1] = $RoundKey[($i-$nk)*4+1] ^ $temp[1];
132 $RoundKey[$i*4+2] = $RoundKey[($i-$nk)*4+2] ^ $temp[2];
133 $RoundKey[$i*4+3] = $RoundKey[($i-$nk)*4+3] ^ $temp[3];
134 ++$i;
135 }
136}
137
138#------------------------------------------------------------------------------
139# This function adds the round key to state.
140# The round key is added to the state by an XOR function.
141sub AddRoundKey($)
142{
143 my $round = shift;
144 my ($i,$j);
145 for ($i=0; $i<4; ++$i) {
146 my $k = $round*16 + $i*4;
147 for ($j=0; $j<4; ++$j) {
148 $state[$j][$i] ^= $RoundKey[$k + $j];
149 }
150 }
151}
152
153#------------------------------------------------------------------------------
154# Substitute the values in the state matrix with values in an S-box
155sub SubBytes()
156{
157 my $i;
158 for ($i=0; $i<4; ++$i) {
159 @{$state[$i]}[0..3] = @sbox[@{$state[$i]}[0..3]];
160 }
161}
162
163sub InvSubBytes()
164{
165 my $i;
166 for ($i=0; $i<4; ++$i) {
167 @{$state[$i]}[0..3] = @rsbox[@{$state[$i]}[0..3]];
168 }
169}
170
171#------------------------------------------------------------------------------
172# Shift the rows in the state to the left.
173# Each row is shifted with different offset.
174# Offset = Row number. So the first row is not shifted.
175sub ShiftRows()
176{
177 # rotate first row 1 columns to left
178 @{$state[1]}[0,1,2,3] = @{$state[1]}[1,2,3,0];
179
180 # rotate second row 2 columns to left
181 @{$state[2]}[0,1,2,3] = @{$state[2]}[2,3,0,1];
182
183 # rotate third row 3 columns to left
184 @{$state[3]}[0,1,2,3] = @{$state[3]}[3,0,1,2];
185}
186
187sub InvShiftRows()
188{
189 # rotate first row 1 columns to right
190 @{$state[1]}[0,1,2,3] = @{$state[1]}[3,0,1,2];
191
192 # rotate second row 2 columns to right
193 @{$state[2]}[0,1,2,3] = @{$state[2]}[2,3,0,1];
194
195 # rotate third row 3 columns to right
196 @{$state[3]}[0,1,2,3] = @{$state[3]}[1,2,3,0];
197}
198
199#------------------------------------------------------------------------------
200# Find the product of {02} and the argument to xtime modulo 0x1b
201# Note: returns an integer which may need to be trimmed to 8 bits
202sub xtime($)
203{
204 return ($_[0]<<1) ^ ((($_[0]>>7) & 1) * 0x1b);
205}
206
207#------------------------------------------------------------------------------
208# Multiply numbers in the field GF(2^8)
209sub Mult($$)
210{
211 my ($x, $y) = @_;
212 return (($y & 1) * $x) ^
213 (($y>>1 & 1) * xtime($x)) ^
214 (($y>>2 & 1) * xtime(xtime($x))) ^
215 (($y>>3 & 1) * xtime(xtime(xtime($x)))) ^
216 (($y>>4 & 1) * xtime(xtime(xtime(xtime($x)))));
217}
218
219#------------------------------------------------------------------------------
220# Mix the columns of the state matrix
221sub MixColumns()
222{
223 my ($i,$t0,$t1,$t2);
224 for ($i=0; $i<4; ++$i) {
225 $t0 = $state[0][$i];
226 $t2 = $state[0][$i] ^ $state[1][$i] ^ $state[2][$i] ^ $state[3][$i];
227 $t1 = $state[0][$i] ^ $state[1][$i] ; $t1 = xtime($t1) & 0xff; $state[0][$i] ^= $t1 ^ $t2 ;
228 $t1 = $state[1][$i] ^ $state[2][$i] ; $t1 = xtime($t1) & 0xff; $state[1][$i] ^= $t1 ^ $t2 ;
229 $t1 = $state[2][$i] ^ $state[3][$i] ; $t1 = xtime($t1) & 0xff; $state[2][$i] ^= $t1 ^ $t2 ;
230 $t1 = $state[3][$i] ^ $t0 ; $t1 = xtime($t1) & 0xff; $state[3][$i] ^= $t1 ^ $t2 ;
231 }
232}
233
234sub InvMixColumns()
235{
236 my $i;
237 for ($i=0; $i<4; ++$i) {
238 my $a = $state[0][$i];
239 my $b = $state[1][$i];
240 my $c = $state[2][$i];
241 my $d = $state[3][$i];
242 $state[0][$i] = (Mult($a,0x0e) ^ Mult($b,0x0b) ^ Mult($c,0x0d) ^ Mult($d,0x09)) & 0xff;
243 $state[1][$i] = (Mult($a,0x09) ^ Mult($b,0x0e) ^ Mult($c,0x0b) ^ Mult($d,0x0d)) & 0xff;
244 $state[2][$i] = (Mult($a,0x0d) ^ Mult($b,0x09) ^ Mult($c,0x0e) ^ Mult($d,0x0b)) & 0xff;
245 $state[3][$i] = (Mult($a,0x0b) ^ Mult($b,0x0d) ^ Mult($c,0x09) ^ Mult($d,0x0e)) & 0xff;
246 }
247}
248
249#------------------------------------------------------------------------------
250# Encrypt (Cipher) or decrypt (InvCipher) a block of data with CBC
251# Inputs: 0) string to cipher (must be 16 bytes long)
252# Returns: cipher'd string
253sub Cipher($)
254{
255 my @in = unpack 'C*', $_[0]; # unpack input plaintext
256 my ($i, $j, $round);
257
258 # copy the input PlainText to state array and apply the CBC
259 for ($i=0; $i<4; ++$i) {
260 for ($j=0; $j<4; ++$j) {
261 my $k = $i*4 + $j;
262 $state[$j][$i] = $in[$k] ^ $cbc[$k];
263 }
264 }
265
266 # add the First round key to the state before starting the rounds
267 AddRoundKey(0);
268
269 # there will be $nr rounds; the first $nr-1 rounds are identical
270 for ($round=1; ; ++$round) {
271 SubBytes();
272 ShiftRows();
273 if ($round < $nr) {
274 MixColumns();
275 AddRoundKey($round);
276 } else {
277 # MixColumns() is not used in the last round
278 AddRoundKey($nr);
279 last;
280 }
281 }
282
283 # the encryption process is over
284 # copy the state array to output array (and save for CBC)
285 for ($i=0; $i<4; ++$i) {
286 for ($j=0; $j<4; ++$j) {
287 $cbc[$i*4+$j] = $state[$j][$i];
288 }
289 }
290 return pack 'C*', @cbc; # return packed ciphertext
291}
292
293sub InvCipher($)
294{
295 my @in = unpack 'C*', $_[0]; # unpack input ciphertext
296 my (@out, $i, $j, $round);
297
298 # copy the input CipherText to state array
299 for ($i=0; $i<4; ++$i) {
300 for ($j=0; $j<4; ++$j) {
301 $state[$j][$i] = $in[$i*4 + $j];
302 }
303 }
304
305 # add the First round key to the state before starting the rounds
306 AddRoundKey($nr);
307
308 # there will be $nr rounds; the first $nr-1 rounds are identical
309 for ($round=$nr-1; ; --$round) {
310 InvShiftRows();
311 InvSubBytes();
312 AddRoundKey($round);
313 # InvMixColumns() is not used in the last round
314 last if $round <= 0;
315 InvMixColumns();
316 }
317
318 # copy the state array to output array and reverse the CBC
319 for ($i=0; $i<4; ++$i) {
320 for ($j=0; $j<4; ++$j) {
321 my $k = $i*4 + $j;
322 $out[$k] = $state[$j][$i] ^ $cbc[$k];
323 }
324 }
325 @cbc = @in; # update CBC for next block
326 return pack 'C*', @out; # return packed plaintext
327}
328
329#------------------------------------------------------------------------------
330# Encrypt/Decrypt using AES-CBC algorithm (with fixed 16-byte blocks)
331# Inputs: 0) data reference (with leading 16-byte initialization vector when decrypting)
332# 1) encryption key (16, 24 or 32 bytes for AES-128, AES-192 or AES-256)
333# 2) encrypt flag (false for decryption, true with length 16 bytes to
334# encrypt using this as the CBC IV, or true with other length to
335# encrypt with a randomly-generated IV)
336# 3) flag to disable padding
337# Returns: error string, or undef on success
338# Notes: encrypts/decrypts data in place
339sub Crypt($$;$$)
340{
341 my ($dataPt, $key, $encrypt, $noPad) = @_;
342
343 # validate key length
344 my $keyLen = length $key;
345 unless ($keyLen == 16 or $keyLen == 24 or $keyLen == 32) {
346 return "Invalid AES key length ($keyLen)";
347 }
348 my $partLen = length($$dataPt) % 16;
349 my ($pos, $i);
350 if ($encrypt) {
351 if (length($encrypt) == 16) {
352 @cbc = unpack 'C*', $encrypt;
353 } else {
354 # generate a random 16-byte CBC initialization vector
355 unless ($seeded) {
356 srand(time() & ($$ + ($$<<15)));
357 $seeded = 1;
358 }
359 for ($i=0; $i<16; ++$i) {
360 $cbc[$i] = int(rand(256));
361 }
362 $encrypt = pack 'C*', @cbc;
363 }
364 $$dataPt = $encrypt . $$dataPt; # add IV to the start of the data
365 # add required padding so we can recover the
366 # original string length after decryption
367 # (padding bytes have value set to padding length)
368 my $padLen = 16 - $partLen;
369 $$dataPt .= (chr($padLen)) x $padLen unless $padLen == 16 and $noPad;
370 $pos = 16; # start encrypting at byte 16 (after the IV)
371 } elsif ($partLen) {
372 return 'Invalid AES ciphertext length';
373 } elsif (length $$dataPt >= 32) {
374 # take the CBC initialization vector from the start of the data
375 @cbc = unpack 'C16', $$dataPt;
376 $$dataPt = substr($$dataPt, 16);
377 $pos = 0; # start decrypting from byte 0 (now that IV is removed)
378 } else {
379 $$dataPt = ''; # empty text
380 return undef;
381 }
382 # the KeyExpansion routine must be called before encryption
383 KeyExpansion($key);
384
385 # loop through the data and convert in blocks
386 my $dataLen = length $$dataPt;
387 my $last = $dataLen - 16;
388 my $func = $encrypt ? \&Cipher : \&InvCipher;
389 while ($pos <= $last) {
390 # cipher this block
391 substr($$dataPt, $pos, 16) = &$func(substr($$dataPt, $pos, 16));
392 $pos += 16;
393 }
394 unless ($encrypt or $noPad) {
395 # remove padding if necessary (padding byte value gives length of padding)
396 my $padLen = ord(substr($$dataPt, -1, 1));
397 return 'AES decryption error (invalid pad byte)' if $padLen > 16;
398 $$dataPt = substr($$dataPt, 0, $dataLen - $padLen);
399 }
400 return undef;
401}
402
4031; # end
404
405
406__END__
407
408=head1 NAME
409
410Image::ExifTool::AES - AES encryption with cipher-block chaining
411
412=head1 SYNOPSIS
413
414 use Image::ExifTool::AES qw(Crypt);
415
416 $err = Crypt(\$plaintext, $key, 1); # encryption
417
418 $err = Crypt(\$ciphertext, $key); # decryption
419
420=head1 DESCRIPTION
421
422This module contains an implementation of the AES encryption/decryption
423algorithms with cipher-block chaining (CBC) and RFC 2898 PKCS #5 padding.
424This is the AESV2 and AESV3 encryption mode used in PDF documents.
425
426=head1 EXPORTS
427
428Exports nothing by default, but L</Crypt> may be exported.
429
430=head1 METHODS
431
432=head2 Crypt
433
434Implement AES encryption/decryption with cipher-block chaining.
435
436=over 4
437
438=item Inputs:
439
4400) Scalar reference for data to encrypt/decrypt.
441
4421) Encryption key string (must have length 16, 24 or 32).
443
4442) [optional] Encrypt flag (false to decrypt).
445
4463) [optional] Flag to avoid removing padding after decrypting, or to avoid
447adding 16 bytes of padding before encrypting when data length is already a
448multiple of 16 bytes.
449
450=item Returns:
451
452On success, the return value is undefined and the data is encrypted or
453decrypted as specified. Otherwise returns an error string and the data is
454left in an indeterminate state.
455
456=item Notes:
457
458The length of the encryption key dictates the AES mode, with lengths of 16,
45924 and 32 bytes resulting in AES-128, AES-192 and AES-256.
460
461When encrypting, the input data may be any length and will be padded to an
462even 16-byte block size using the specified padding technique. If the
463encrypt flag has length 16, it is used as the initialization vector for
464the cipher-block chaining, otherwise a random IV is generated. Upon
465successful return the data will be encrypted, with the first 16 bytes of
466the data being the CBC IV.
467
468When decrypting, the input data begins with the 16-byte CBC initialization
469vector.
470
471=back
472
473=head1 BUGS
474
475This code is blindingly slow. But in truth, slowing down processing is the
476main purpose of encryption, so this really can't be considered a bug.
477
478=head1 AUTHOR
479
480Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
481
482This library is free software; you can redistribute it and/or modify it
483under the same terms as Perl itself.
484
485=head1 REFERENCES
486
487=over 4
488
489=item L<http://www.hoozi.com/Articles/AESEncryption.htm>
490
491=item L<http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf>
492
493=item L<http://www.faqs.org/rfcs/rfc3602.html>
494
495=back
496
497=head1 SEE ALSO
498
499L<Image::ExifTool(3pm)|Image::ExifTool>
500
501=cut
Note: See TracBrowser for help on using the repository browser.