PluginProbe
Contact Forms by Cimatti / 1.2
Contact Forms by Cimatti v1.2
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
contact-forms / phpseclib-crypt / AES.php

AES.php in Contact Forms by Cimatti 1.2, at phpseclib-crypt/AES.php

612 lines 23.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4 /**
5 * Pure-PHP implementation of AES.
6 *
7 * Uses mcrypt, if available, and an internal implementation, otherwise.
8 *
9 * PHP versions 4 and 5
10 *
11 * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12 * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
13 * it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()}
14 * is called, again, at which point, it'll be recalculated.
15 *
16 * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
17 * make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
18 * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
19 *
20 * Here's a short example of how to use this library:
21 * <code>
22 * <?php
23 * include('Crypt/AES.php');
24 *
25 * $aes = new Crypt_AES();
26 *
27 * $aes->setKey('abcdefghijklmnop');
28 *
29 * $size = 10 * 1024;
30 * $plaintext = '';
31 * for ($i = 0; $i < $size; $i++) {
32 * $plaintext.= 'a';
33 * }
34 *
35 * echo $aes->decrypt($aes->encrypt($plaintext));
36 * ?>
37 * </code>
38 *
39 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
40 * of this software and associated documentation files (the "Software"), to deal
41 * in the Software without restriction, including without limitation the rights
42 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43 * copies of the Software, and to permit persons to whom the Software is
44 * furnished to do so, subject to the following conditions:
45 *
46 * The above copyright notice and this permission notice shall be included in
47 * all copies or substantial portions of the Software.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55 * THE SOFTWARE.
56 *
57 * @category Crypt
58 * @package Crypt_AES
59 * @author Jim Wigginton <terrafrost@php.net>
60 * @copyright MMVIII Jim Wigginton
61 * @license http://www.opensource.org/licenses/mit-license.html MIT License
62 * @version $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
63 * @link http://phpseclib.sourceforge.net
64 */
65
66 /**
67 * Include Crypt_Rijndael
68 */
69 if (!class_exists('Crypt_Rijndael')) {
70 require_once 'Rijndael.php';
71 }
72
73 /**#@+
74 * @access public
75 * @see Crypt_AES::encrypt()
76 * @see Crypt_AES::decrypt()
77 */
78 /**
79 * Encrypt / decrypt using the Counter mode.
80 *
81 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
82 *
83 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
84 */
85 define('CRYPT_AES_MODE_CTR', -1);
86 /**
87 * Encrypt / decrypt using the Electronic Code Book mode.
88 *
89 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
90 */
91 define('CRYPT_AES_MODE_ECB', 1);
92 /**
93 * Encrypt / decrypt using the Code Book Chaining mode.
94 *
95 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
96 */
97 define('CRYPT_AES_MODE_CBC', 2);
98 /**
99 * Encrypt / decrypt using the Cipher Feedback mode.
100 *
101 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
102 */
103 define('CRYPT_AES_MODE_CFB', 3);
104 /**
105 * Encrypt / decrypt using the Cipher Feedback mode.
106 *
107 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
108 */
109 define('CRYPT_AES_MODE_OFB', 4);
110 /**#@-*/
111
112 /**#@+
113 * @access private
114 * @see Crypt_AES::Crypt_AES()
115 */
116 /**
117 * Toggles the internal implementation
118 */
119 define('CRYPT_AES_MODE_INTERNAL', 1);
120 /**
121 * Toggles the mcrypt implementation
122 */
123 define('CRYPT_AES_MODE_MCRYPT', 2);
124 /**#@-*/
125
126 /**
127 * Pure-PHP implementation of AES.
128 *
129 * @author Jim Wigginton <terrafrost@php.net>
130 * @version 0.1.0
131 * @access public
132 * @package Crypt_AES
133 */
134 class Crypt_AES extends Crypt_Rijndael {
135 /**
136 * mcrypt resource for encryption
137 *
138 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
139 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
140 *
141 * @see Crypt_AES::encrypt()
142 * @var String
143 * @access private
144 */
145 var $enmcrypt;
146
147 /**
148 * mcrypt resource for decryption
149 *
150 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
151 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
152 *
153 * @see Crypt_AES::decrypt()
154 * @var String
155 * @access private
156 */
157 var $demcrypt;
158
159 /**
160 * mcrypt resource for CFB mode
161 *
162 * @see Crypt_AES::encrypt()
163 * @see Crypt_AES::decrypt()
164 * @var String
165 * @access private
166 */
167 var $ecb;
168
169 /**
170 * Default Constructor.
171 *
172 * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
173 * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
174 *
175 * @param optional Integer $mode
176 * @return Crypt_AES
177 * @access public
178 */
179 function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
180 {
181 if ( !defined('CRYPT_AES_MODE') ) {
182 switch (true) {
183 case extension_loaded('mcrypt') && in_array('rijndael-128', mcrypt_list_algorithms()):
184 define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
185 break;
186 default:
187 define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
188 }
189 }
190
191 switch ( CRYPT_AES_MODE ) {
192 case CRYPT_AES_MODE_MCRYPT:
193 switch ($mode) {
194 case CRYPT_AES_MODE_ECB:
195 $this->paddable = true;
196 $this->mode = MCRYPT_MODE_ECB;
197 break;
198 case CRYPT_AES_MODE_CTR:
199 // ctr doesn't have a constant associated with it even though it appears to be fairly widely
200 // supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
201 // include a compatibility layer. the layer has been implemented but, for now, is commented out.
202 $this->mode = 'ctr';
203 //$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
204 break;
205 case CRYPT_AES_MODE_CFB:
206 $this->mode = 'ncfb';
207 break;
208 case CRYPT_AES_MODE_OFB:
209 $this->mode = MCRYPT_MODE_NOFB;
210 break;
211 case CRYPT_AES_MODE_CBC:
212 default:
213 $this->paddable = true;
214 $this->mode = MCRYPT_MODE_CBC;
215 }
216
217 $this->debuffer = $this->enbuffer = '';
218
219 break;
220 default:
221 switch ($mode) {
222 case CRYPT_AES_MODE_ECB:
223 $this->paddable = true;
224 $this->mode = CRYPT_RIJNDAEL_MODE_ECB;
225 break;
226 case CRYPT_AES_MODE_CTR:
227 $this->mode = CRYPT_RIJNDAEL_MODE_CTR;
228 break;
229 case CRYPT_AES_MODE_CFB:
230 $this->mode = CRYPT_RIJNDAEL_MODE_CFB;
231 break;
232 case CRYPT_AES_MODE_OFB:
233 $this->mode = CRYPT_RIJNDAEL_MODE_OFB;
234 break;
235 case CRYPT_AES_MODE_CBC:
236 default:
237 $this->paddable = true;
238 $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
239 }
240 }
241
242 if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
243 parent::Crypt_Rijndael($this->mode);
244 }
245 }
246
247 /**
248 * Dummy function
249 *
250 * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
251 *
252 * @access public
253 * @param Integer $length
254 */
255 function setBlockLength($length)
256 {
257 return;
258 }
259
260
261 /**
262 * Sets the initialization vector. (optional)
263 *
264 * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
265 * to be all zero's.
266 *
267 * @access public
268 * @param String $iv
269 */
270 function setIV($iv)
271 {
272 parent::setIV($iv);
273 if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
274 $this->changed = true;
275 }
276 }
277
278 /**
279 * Encrypts a message.
280 *
281 * $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
282 * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
283 * URL:
284 *
285 * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
286 *
287 * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
288 * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
289 * length.
290 *
291 * @see Crypt_AES::decrypt()
292 * @access public
293 * @param String $plaintext
294 */
295 function encrypt($plaintext)
296 {
297 if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
298 $changed = $this->changed;
299 $this->_mcryptSetup();
300 /*
301 if ($this->mode == CRYPT_AES_MODE_CTR) {
302 $iv = $this->encryptIV;
303 $xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($plaintext), $iv));
304 $ciphertext = $plaintext ^ $xor;
305 if ($this->continuousBuffer) {
306 $this->encryptIV = $iv;
307 }
308 return $ciphertext;
309 }
310 */
311 // re: http://phpseclib.sourceforge.net/cfb-demo.phps
312 // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
313 // rewritten CFB implementation the above outputs the same thing twice.
314 if ($this->mode == 'ncfb') {
315 if ($changed) {
316 $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
317 mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
318 }
319
320 if (strlen($this->enbuffer)) {
321 $ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer));
322 $this->enbuffer.= $ciphertext;
323 if (strlen($this->enbuffer) == 16) {
324 $this->encryptIV = $this->enbuffer;
325 $this->enbuffer = '';
326 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
327 }
328 $plaintext = substr($plaintext, strlen($ciphertext));
329 } else {
330 $ciphertext = '';
331 }
332
333 $last_pos = strlen($plaintext) & 0xFFFFFFF0;
334 $ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : '';
335
336 if (strlen($plaintext) & 0xF) {
337 if (strlen($ciphertext)) {
338 $this->encryptIV = substr($ciphertext, -16);
339 }
340 $this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV);
341 $this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV;
342 $ciphertext.= $this->enbuffer;
343 }
344
345 return $ciphertext;
346 }
347
348 if ($this->paddable) {
349 $plaintext = $this->_pad($plaintext);
350 }
351
352 $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
353
354 if (!$this->continuousBuffer) {
355 mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
356 }
357
358 return $ciphertext;
359 }
360
361 return parent::encrypt($plaintext);
362 }
363
364 /**
365 * Decrypts a message.
366 *
367 * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
368 *
369 * @see Crypt_AES::encrypt()
370 * @access public
371 * @param String $ciphertext
372 */
373 function decrypt($ciphertext)
374 {
375 if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
376 $changed = $this->changed;
377 $this->_mcryptSetup();
378 /*
379 if ($this->mode == CRYPT_AES_MODE_CTR) {
380 $iv = $this->decryptIV;
381 $xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($ciphertext), $iv));
382 $plaintext = $ciphertext ^ $xor;
383 if ($this->continuousBuffer) {
384 $this->decryptIV = $iv;
385 }
386 return $plaintext;
387 }
388 */
389 if ($this->mode == 'ncfb') {
390 if ($changed) {
391 $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
392 mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
393 }
394
395 if (strlen($this->debuffer)) {
396 $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer));
397
398 $this->debuffer.= substr($ciphertext, 0, strlen($plaintext));
399 if (strlen($this->debuffer) == 16) {
400 $this->decryptIV = $this->debuffer;
401 $this->debuffer = '';
402 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
403 }
404 $ciphertext = substr($ciphertext, strlen($plaintext));
405 } else {
406 $plaintext = '';
407 }
408
409 $last_pos = strlen($ciphertext) & 0xFFFFFFF0;
410 $plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : '';
411
412 if (strlen($ciphertext) & 0xF) {
413 if (strlen($plaintext)) {
414 $this->decryptIV = substr($ciphertext, $last_pos - 16, 16);
415 }
416 $this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV);
417 $this->debuffer = substr($ciphertext, $last_pos);
418 $plaintext.= $this->debuffer ^ $this->decryptIV;
419 }
420
421 return $plaintext;
422 }
423
424 if ($this->paddable) {
425 // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
426 // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
427 $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
428 }
429
430 $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
431
432 if (!$this->continuousBuffer) {
433 mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
434 }
435
436 return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
437 }
438
439 return parent::decrypt($ciphertext);
440 }
441
442 /**
443 * Setup mcrypt
444 *
445 * Validates all the variables.
446 *
447 * @access private
448 */
449 function _mcryptSetup()
450 {
451 if (!$this->changed) {
452 return;
453 }
454
455 if (!$this->explicit_key_length) {
456 // this just copied from Crypt_Rijndael::_setup()
457 $length = strlen($this->key) >> 2;
458 if ($length > 8) {
459 $length = 8;
460 } else if ($length < 4) {
461 $length = 4;
462 }
463 $this->Nk = $length;
464 $this->key_size = $length << 2;
465 }
466
467 switch ($this->Nk) {
468 case 4: // 128
469 $this->key_size = 16;
470 break;
471 case 5: // 160
472 case 6: // 192
473 $this->key_size = 24;
474 break;
475 case 7: // 224
476 case 8: // 256
477 $this->key_size = 32;
478 }
479
480 $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
481 $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
482
483 if (!isset($this->enmcrypt)) {
484 $mode = $this->mode;
485 //$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
486
487 $this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
488 $this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
489 } // else should mcrypt_generic_deinit be called?
490
491 mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
492 mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
493
494 $this->changed = false;
495 }
496
497 /**
498 * Encrypts a block
499 *
500 * Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
501 *
502 * @see Crypt_Rijndael::_encryptBlock()
503 * @access private
504 * @param String $in
505 * @return String
506 */
507 function _encryptBlock($in)
508 {
509 $state = unpack('N*word', $in);
510
511 $Nr = $this->Nr;
512 $w = $this->w;
513 $t0 = $this->t0;
514 $t1 = $this->t1;
515 $t2 = $this->t2;
516 $t3 = $this->t3;
517
518 // addRoundKey and reindex $state
519 $state = array(
520 $state['word1'] ^ $w[0][0],
521 $state['word2'] ^ $w[0][1],
522 $state['word3'] ^ $w[0][2],
523 $state['word4'] ^ $w[0][3]
524 );
525
526 // shiftRows + subWord + mixColumns + addRoundKey
527 // we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields
528 // only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
529 for ($round = 1; $round < $this->Nr; $round++) {
530 $state = array(
531 $t0[$state[0] & 0xFF000000] ^ $t1[$state[1] & 0x00FF0000] ^ $t2[$state[2] & 0x0000FF00] ^ $t3[$state[3] & 0x000000FF] ^ $w[$round][0],
532 $t0[$state[1] & 0xFF000000] ^ $t1[$state[2] & 0x00FF0000] ^ $t2[$state[3] & 0x0000FF00] ^ $t3[$state[0] & 0x000000FF] ^ $w[$round][1],
533 $t0[$state[2] & 0xFF000000] ^ $t1[$state[3] & 0x00FF0000] ^ $t2[$state[0] & 0x0000FF00] ^ $t3[$state[1] & 0x000000FF] ^ $w[$round][2],
534 $t0[$state[3] & 0xFF000000] ^ $t1[$state[0] & 0x00FF0000] ^ $t2[$state[1] & 0x0000FF00] ^ $t3[$state[2] & 0x000000FF] ^ $w[$round][3]
535 );
536
537 }
538
539 // subWord
540 $state = array(
541 $this->_subWord($state[0]),
542 $this->_subWord($state[1]),
543 $this->_subWord($state[2]),
544 $this->_subWord($state[3])
545 );
546
547 // shiftRows + addRoundKey
548 $state = array(
549 ($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0],
550 ($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1],
551 ($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2],
552 ($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3]
553 );
554
555 return pack('N*', $state[0], $state[1], $state[2], $state[3]);
556 }
557
558 /**
559 * Decrypts a block
560 *
561 * Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
562 *
563 * @see Crypt_Rijndael::_decryptBlock()
564 * @access private
565 * @param String $in
566 * @return String
567 */
568 function _decryptBlock($in)
569 {
570 $state = unpack('N*word', $in);
571
572 $Nr = $this->Nr;
573 $dw = $this->dw;
574 $dt0 = $this->dt0;
575 $dt1 = $this->dt1;
576 $dt2 = $this->dt2;
577 $dt3 = $this->dt3;
578
579 // addRoundKey and reindex $state
580 $state = array(
581 $state['word1'] ^ $dw[$this->Nr][0],
582 $state['word2'] ^ $dw[$this->Nr][1],
583 $state['word3'] ^ $dw[$this->Nr][2],
584 $state['word4'] ^ $dw[$this->Nr][3]
585 );
586
587
588 // invShiftRows + invSubBytes + invMixColumns + addRoundKey
589 for ($round = $this->Nr - 1; $round > 0; $round--) {
590 $state = array(
591 $dt0[$state[0] & 0xFF000000] ^ $dt1[$state[3] & 0x00FF0000] ^ $dt2[$state[2] & 0x0000FF00] ^ $dt3[$state[1] & 0x000000FF] ^ $dw[$round][0],
592 $dt0[$state[1] & 0xFF000000] ^ $dt1[$state[0] & 0x00FF0000] ^ $dt2[$state[3] & 0x0000FF00] ^ $dt3[$state[2] & 0x000000FF] ^ $dw[$round][1],
593 $dt0[$state[2] & 0xFF000000] ^ $dt1[$state[1] & 0x00FF0000] ^ $dt2[$state[0] & 0x0000FF00] ^ $dt3[$state[3] & 0x000000FF] ^ $dw[$round][2],
594 $dt0[$state[3] & 0xFF000000] ^ $dt1[$state[2] & 0x00FF0000] ^ $dt2[$state[1] & 0x0000FF00] ^ $dt3[$state[0] & 0x000000FF] ^ $dw[$round][3]
595 );
596 }
597
598 // invShiftRows + invSubWord + addRoundKey
599 $state = array(
600 $this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $dw[0][0],
601 $this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $dw[0][1],
602 $this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $dw[0][2],
603 $this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $dw[0][3]
604 );
605
606 return pack('N*', $state[0], $state[1], $state[2], $state[3]);
607 }
608 }
609
610 // vim: ts=4:sw=4:et:
611 // vim6: fdl=1:
612