PluginProbe
Contact Forms by Cimatti / 1.9.2
Contact Forms by Cimatti v1.9.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 / Rijndael.php

Rijndael.php in Contact Forms by Cimatti 1.9.2, at phpseclib-crypt/Rijndael.php

1,051 lines 45.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Pure-PHP implementation of Rijndael.
5 *
6 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
7 *
8 * PHP versions 4 and 5
9 *
10 * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
11 * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12 * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
13 * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
14 * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
15 *
16 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
17 * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
18 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
19 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224. Indeed, 160 and 224
20 * are first defined as valid key / block lengths in
21 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
22 * Extensions: Other block and Cipher Key lengths.
23 * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
24 *
25 * {@internal The variable names are the same as those in
26 * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
27 *
28 * Here's a short example of how to use this library:
29 * <code>
30 * <?php
31 * include 'Crypt/Rijndael.php';
32 *
33 * $rijndael = new Crypt_Rijndael();
34 *
35 * $rijndael->setKey('abcdefghijklmnop');
36 *
37 * $size = 10 * 1024;
38 * $plaintext = '';
39 * for ($i = 0; $i < $size; $i++) {
40 * $plaintext.= 'a';
41 * }
42 *
43 * echo $rijndael->decrypt($rijndael->encrypt($plaintext));
44 * ?>
45 * </code>
46 *
47 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
48 * of this software and associated documentation files (the "Software"), to deal
49 * in the Software without restriction, including without limitation the rights
50 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
51 * copies of the Software, and to permit persons to whom the Software is
52 * furnished to do so, subject to the following conditions:
53 *
54 * The above copyright notice and this permission notice shall be included in
55 * all copies or substantial portions of the Software.
56 *
57 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
61 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63 * THE SOFTWARE.
64 *
65 * @category Crypt
66 * @package Crypt_Rijndael
67 * @author Jim Wigginton <terrafrost@php.net>
68 * @copyright 2008 Jim Wigginton
69 * @license http://www.opensource.org/licenses/mit-license.html MIT License
70 * @link http://phpseclib.sourceforge.net
71 */
72
73 /**
74 * Include Crypt_Base
75 *
76 * Base cipher class
77 */
78 if (!class_exists('Crypt_Base')) {
79 include_once 'Base.php';
80 }
81
82 /**#@+
83 * @access public
84 * @see self::encrypt()
85 * @see self::decrypt()
86 */
87 /**
88 * Encrypt / decrypt using the Counter mode.
89 *
90 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
91 *
92 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
93 */
94 define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR);
95 /**
96 * Encrypt / decrypt using the Electronic Code Book mode.
97 *
98 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
99 */
100 define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB);
101 /**
102 * Encrypt / decrypt using the Code Book Chaining mode.
103 *
104 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
105 */
106 define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC);
107 /**
108 * Encrypt / decrypt using the Cipher Feedback mode.
109 *
110 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
111 */
112 define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB);
113 /**
114 * Encrypt / decrypt using the Cipher Feedback mode.
115 *
116 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
117 */
118 define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
119 /**#@-*/
120
121 /**
122 * Pure-PHP implementation of Rijndael.
123 *
124 * @package Crypt_Rijndael
125 * @author Jim Wigginton <terrafrost@php.net>
126 * @access public
127 */
128 class Crypt_Rijndael extends Crypt_Base
129 {
130 /**
131 * The namespace used by the cipher for its constants.
132 *
133 * @see Crypt_Base::const_namespace
134 * @var string
135 * @access private
136 */
137 var $const_namespace = 'RIJNDAEL';
138
139 /**
140 * The mcrypt specific name of the cipher
141 *
142 * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
143 * Crypt_Rijndael determines automatically whether mcrypt is useable
144 * or not for the current $block_size/$key_length.
145 * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
146 *
147 * @see Crypt_Base::cipher_name_mcrypt
148 * @see Crypt_Base::engine
149 * @see self::isValidEngine()
150 * @var string
151 * @access private
152 */
153 var $cipher_name_mcrypt = 'rijndael-128';
154
155 /**
156 * The default salt used by setPassword()
157 *
158 * @see Crypt_Base::password_default_salt
159 * @see Crypt_Base::setPassword()
160 * @var string
161 * @access private
162 */
163 var $password_default_salt = 'phpseclib';
164
165 /**
166 * The Key Schedule
167 *
168 * @see self::_setup()
169 * @var array
170 * @access private
171 */
172 var $w;
173
174 /**
175 * The Inverse Key Schedule
176 *
177 * @see self::_setup()
178 * @var array
179 * @access private
180 */
181 var $dw;
182
183 /**
184 * The Block Length divided by 32
185 *
186 * @see self::setBlockLength()
187 * @var int
188 * @access private
189 * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
190 * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
191 * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
192 * of that, we'll just precompute it once.
193 */
194 var $Nb = 4;
195
196 /**
197 * The Key Length (in bytes)
198 *
199 * @see self::setKeyLength()
200 * @var int
201 * @access private
202 * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
203 * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
204 * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
205 * of that, we'll just precompute it once.
206 */
207 var $key_length = 16;
208
209 /**
210 * The Key Length divided by 32
211 *
212 * @see self::setKeyLength()
213 * @var int
214 * @access private
215 * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
216 */
217 var $Nk = 4;
218
219 /**
220 * The Number of Rounds
221 *
222 * @var int
223 * @access private
224 * @internal The max value is 14, the min value is 10.
225 */
226 var $Nr;
227
228 /**
229 * Shift offsets
230 *
231 * @var array
232 * @access private
233 */
234 var $c;
235
236 /**
237 * Holds the last used key- and block_size information
238 *
239 * @var array
240 * @access private
241 */
242 var $kl;
243
244 /**
245 * Sets the key.
246 *
247 * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
248 * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
249 * up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
250 * excess bits.
251 *
252 * If the key is not explicitly set, it'll be assumed to be all null bytes.
253 *
254 * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
255 *
256 * @see Crypt_Base:setKey()
257 * @see self::setKeyLength()
258 * @access public
259 * @param string $key
260 */
261 function setKey($key)
262 {
263 if (!$this->explicit_key_length) {
264 $length = strlen($key);
265 switch (true) {
266 case $length <= 16:
267 $this->key_size = 16;
268 break;
269 case $length <= 20:
270 $this->key_size = 20;
271 break;
272 case $length <= 24:
273 $this->key_size = 24;
274 break;
275 case $length <= 28:
276 $this->key_size = 28;
277 break;
278 default:
279 $this->key_size = 32;
280 }
281 }
282 parent::setKey($key);
283 }
284
285 /**
286 * Sets the key length
287 *
288 * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
289 * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
290 *
291 * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
292 * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
293 * 192/256 bits as, for example, mcrypt will do.
294 *
295 * That said, if you want be compatible with other Rijndael and AES implementations,
296 * you should not setKeyLength(160) or setKeyLength(224).
297 *
298 * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
299 * the mcrypt php extension, even if available.
300 * This results then in slower encryption.
301 *
302 * @access public
303 * @param int $length
304 */
305 function setKeyLength($length)
306 {
307 switch (true) {
308 case $length <= 128:
309 $this->key_length = 16;
310 break;
311 case $length <= 160:
312 $this->key_length = 20;
313 break;
314 case $length <= 192:
315 $this->key_length = 24;
316 break;
317 case $length <= 224:
318 $this->key_length = 28;
319 break;
320 default:
321 $this->key_length = 32;
322 }
323
324 parent::setKeyLength($length);
325 }
326
327 /**
328 * Sets the block length
329 *
330 * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
331 * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
332 *
333 * @access public
334 * @param int $length
335 */
336 function setBlockLength($length)
337 {
338 $length >>= 5;
339 if ($length > 8) {
340 $length = 8;
341 } elseif ($length < 4) {
342 $length = 4;
343 }
344 $this->Nb = $length;
345 $this->block_size = $length << 2;
346 $this->changed = true;
347 $this->_setEngine();
348 }
349
350 /**
351 * Test for engine validity
352 *
353 * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
354 *
355 * @see Crypt_Base::Crypt_Base()
356 * @param int $engine
357 * @access public
358 * @return bool
359 */
360 function isValidEngine($engine)
361 {
362 switch ($engine) {
363 case CRYPT_ENGINE_OPENSSL:
364 if ($this->block_size != 16) {
365 return false;
366 }
367 $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
368 $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
369 break;
370 case CRYPT_ENGINE_MCRYPT:
371 $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
372 if ($this->key_length % 8) { // is it a 160/224-bit key?
373 // mcrypt is not usable for them, only for 128/192/256-bit keys
374 return false;
375 }
376 }
377
378 return parent::isValidEngine($engine);
379 }
380
381 /**
382 * Encrypts a block
383 *
384 * @access private
385 * @param string $in
386 * @return string
387 */
388 function _encryptBlock($in)
389 {
390 static $tables;
391 if (empty($tables)) {
392 $tables = &$this->_getTables();
393 }
394 $t0 = $tables[0];
395 $t1 = $tables[1];
396 $t2 = $tables[2];
397 $t3 = $tables[3];
398 $sbox = $tables[4];
399
400 $state = array();
401 $words = unpack('N*', $in);
402
403 $c = $this->c;
404 $w = $this->w;
405 $Nb = $this->Nb;
406 $Nr = $this->Nr;
407
408 // addRoundKey
409 $wc = $Nb - 1;
410 foreach ($words as $word) {
411 $state[] = $word ^ $w[++$wc];
412 }
413
414 // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
415 // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
416 // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
417 // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
418 // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
419 // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
420
421 // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
422 $temp = array();
423 for ($round = 1; $round < $Nr; ++$round) {
424 $i = 0; // $c[0] == 0
425 $j = $c[1];
426 $k = $c[2];
427 $l = $c[3];
428
429 while ($i < $Nb) {
430 $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
431 $t1[$state[$j] >> 16 & 0x000000FF] ^
432 $t2[$state[$k] >> 8 & 0x000000FF] ^
433 $t3[$state[$l] & 0x000000FF] ^
434 $w[++$wc];
435 ++$i;
436 $j = ($j + 1) % $Nb;
437 $k = ($k + 1) % $Nb;
438 $l = ($l + 1) % $Nb;
439 }
440 $state = $temp;
441 }
442
443 // subWord
444 for ($i = 0; $i < $Nb; ++$i) {
445 $state[$i] = $sbox[$state[$i] & 0x000000FF] |
446 ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) |
447 ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
448 ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
449 }
450
451 // shiftRows + addRoundKey
452 $i = 0; // $c[0] == 0
453 $j = $c[1];
454 $k = $c[2];
455 $l = $c[3];
456 while ($i < $Nb) {
457 $temp[$i] = ($state[$i] & 0xFF000000) ^
458 ($state[$j] & 0x00FF0000) ^
459 ($state[$k] & 0x0000FF00) ^
460 ($state[$l] & 0x000000FF) ^
461 $w[$i];
462 ++$i;
463 $j = ($j + 1) % $Nb;
464 $k = ($k + 1) % $Nb;
465 $l = ($l + 1) % $Nb;
466 }
467
468 switch ($Nb) {
469 case 8:
470 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
471 case 7:
472 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
473 case 6:
474 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
475 case 5:
476 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
477 default:
478 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
479 }
480 }
481
482 /**
483 * Decrypts a block
484 *
485 * @access private
486 * @param string $in
487 * @return string
488 */
489 function _decryptBlock($in)
490 {
491 static $invtables;
492 if (empty($invtables)) {
493 $invtables = &$this->_getInvTables();
494 }
495 $dt0 = $invtables[0];
496 $dt1 = $invtables[1];
497 $dt2 = $invtables[2];
498 $dt3 = $invtables[3];
499 $isbox = $invtables[4];
500
501 $state = array();
502 $words = unpack('N*', $in);
503
504 $c = $this->c;
505 $dw = $this->dw;
506 $Nb = $this->Nb;
507 $Nr = $this->Nr;
508
509 // addRoundKey
510 $wc = $Nb - 1;
511 foreach ($words as $word) {
512 $state[] = $word ^ $dw[++$wc];
513 }
514
515 $temp = array();
516 for ($round = $Nr - 1; $round > 0; --$round) {
517 $i = 0; // $c[0] == 0
518 $j = $Nb - $c[1];
519 $k = $Nb - $c[2];
520 $l = $Nb - $c[3];
521
522 while ($i < $Nb) {
523 $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
524 $dt1[$state[$j] >> 16 & 0x000000FF] ^
525 $dt2[$state[$k] >> 8 & 0x000000FF] ^
526 $dt3[$state[$l] & 0x000000FF] ^
527 $dw[++$wc];
528 ++$i;
529 $j = ($j + 1) % $Nb;
530 $k = ($k + 1) % $Nb;
531 $l = ($l + 1) % $Nb;
532 }
533 $state = $temp;
534 }
535
536 // invShiftRows + invSubWord + addRoundKey
537 $i = 0; // $c[0] == 0
538 $j = $Nb - $c[1];
539 $k = $Nb - $c[2];
540 $l = $Nb - $c[3];
541
542 while ($i < $Nb) {
543 $word = ($state[$i] & 0xFF000000) |
544 ($state[$j] & 0x00FF0000) |
545 ($state[$k] & 0x0000FF00) |
546 ($state[$l] & 0x000000FF);
547
548 $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] |
549 ($isbox[$word >> 8 & 0x000000FF] << 8) |
550 ($isbox[$word >> 16 & 0x000000FF] << 16) |
551 ($isbox[$word >> 24 & 0x000000FF] << 24));
552 ++$i;
553 $j = ($j + 1) % $Nb;
554 $k = ($k + 1) % $Nb;
555 $l = ($l + 1) % $Nb;
556 }
557
558 switch ($Nb) {
559 case 8:
560 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
561 case 7:
562 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
563 case 6:
564 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
565 case 5:
566 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
567 default:
568 return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
569 }
570 }
571
572 /**
573 * Setup the key (expansion)
574 *
575 * @see Crypt_Base::_setupKey()
576 * @access private
577 */
578 function _setupKey()
579 {
580 // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
581 // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
582 static $rcon = array(0,
583 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
584 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
585 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
586 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
587 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
588 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
589 );
590
591 if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
592 // already expanded
593 return;
594 }
595 $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
596
597 $this->Nk = $this->key_length >> 2;
598 // see Rijndael-ammended.pdf#page=44
599 $this->Nr = max($this->Nk, $this->Nb) + 6;
600
601 // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
602 // "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
603 // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
604 // "Table 2: Shift offsets for different block lengths"
605 switch ($this->Nb) {
606 case 4:
607 case 5:
608 case 6:
609 $this->c = array(0, 1, 2, 3);
610 break;
611 case 7:
612 $this->c = array(0, 1, 2, 4);
613 break;
614 case 8:
615 $this->c = array(0, 1, 3, 4);
616 }
617
618 $w = array_values(unpack('N*words', $this->key));
619
620 $length = $this->Nb * ($this->Nr + 1);
621 for ($i = $this->Nk; $i < $length; $i++) {
622 $temp = $w[$i - 1];
623 if ($i % $this->Nk == 0) {
624 // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
625 // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
626 // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
627 // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
628 $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
629 $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
630 } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
631 $temp = $this->_subWord($temp);
632 }
633 $w[$i] = $w[$i - $this->Nk] ^ $temp;
634 }
635
636 // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
637 // and generate the inverse key schedule. more specifically,
638 // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
639 // "The key expansion for the Inverse Cipher is defined as follows:
640 // 1. Apply the Key Expansion.
641 // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
642 // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
643 list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
644 $temp = $this->w = $this->dw = array();
645 for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
646 if ($col == $this->Nb) {
647 if ($row == 0) {
648 $this->dw[0] = $this->w[0];
649 } else {
650 // subWord + invMixColumn + invSubWord = invMixColumn
651 $j = 0;
652 while ($j < $this->Nb) {
653 $dw = $this->_subWord($this->w[$row][$j]);
654 $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
655 $dt1[$dw >> 16 & 0x000000FF] ^
656 $dt2[$dw >> 8 & 0x000000FF] ^
657 $dt3[$dw & 0x000000FF];
658 $j++;
659 }
660 $this->dw[$row] = $temp;
661 }
662
663 $col = 0;
664 $row++;
665 }
666 $this->w[$row][$col] = $w[$i];
667 }
668
669 $this->dw[$row] = $this->w[$row];
670
671 // Converting to 1-dim key arrays (both ascending)
672 $this->dw = array_reverse($this->dw);
673 $w = array_pop($this->w);
674 $dw = array_pop($this->dw);
675 foreach ($this->w as $r => $wr) {
676 foreach ($wr as $c => $wc) {
677 $w[] = $wc;
678 $dw[] = $this->dw[$r][$c];
679 }
680 }
681 $this->w = $w;
682 $this->dw = $dw;
683 }
684
685 /**
686 * Performs S-Box substitutions
687 *
688 * @access private
689 * @param int $word
690 */
691 function _subWord($word)
692 {
693 static $sbox;
694 if (empty($sbox)) {
695 list(, , , , $sbox) = $this->_getTables();
696 }
697
698 return $sbox[$word & 0x000000FF] |
699 ($sbox[$word >> 8 & 0x000000FF] << 8) |
700 ($sbox[$word >> 16 & 0x000000FF] << 16) |
701 ($sbox[$word >> 24 & 0x000000FF] << 24);
702 }
703
704 /**
705 * Provides the mixColumns and sboxes tables
706 *
707 * @see Crypt_Rijndael:_encryptBlock()
708 * @see Crypt_Rijndael:_setupInlineCrypt()
709 * @see Crypt_Rijndael:_subWord()
710 * @access private
711 * @return array &$tables
712 */
713 function &_getTables()
714 {
715 static $tables;
716 if (empty($tables)) {
717 // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
718 // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
719 // those are the names we'll use.
720 $t3 = array_map('intval', array(
721 // with array_map('intval', ...) we ensure we have only int's and not
722 // some slower floats converted by php automatically on high values
723 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
724 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
725 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
726 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
727 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
728 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
729 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
730 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
731 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
732 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
733 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
734 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
735 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
736 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
737 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
738 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
739 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
740 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
741 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
742 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
743 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
744 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
745 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
746 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
747 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
748 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
749 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
750 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
751 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
752 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
753 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
754 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
755 ));
756
757 foreach ($t3 as $t3i) {
758 $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF);
759 $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
760 $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
761 }
762
763 $tables = array(
764 // The Precomputed mixColumns tables t0 - t3
765 $t0,
766 $t1,
767 $t2,
768 $t3,
769 // The SubByte S-Box
770 array(
771 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
772 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
773 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
774 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
775 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
776 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
777 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
778 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
779 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
780 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
781 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
782 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
783 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
784 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
785 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
786 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
787 )
788 );
789 }
790 return $tables;
791 }
792
793 /**
794 * Provides the inverse mixColumns and inverse sboxes tables
795 *
796 * @see Crypt_Rijndael:_decryptBlock()
797 * @see Crypt_Rijndael:_setupInlineCrypt()
798 * @see Crypt_Rijndael:_setupKey()
799 * @access private
800 * @return array &$tables
801 */
802 function &_getInvTables()
803 {
804 static $tables;
805 if (empty($tables)) {
806 $dt3 = array_map('intval', array(
807 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
808 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
809 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
810 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
811 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
812 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
813 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
814 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
815 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
816 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
817 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
818 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
819 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
820 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
821 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
822 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
823 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
824 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
825 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
826 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
827 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
828 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
829 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
830 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
831 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
832 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
833 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
834 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
835 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
836 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
837 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
838 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
839 ));
840
841 foreach ($dt3 as $dt3i) {
842 $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
843 $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
844 $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
845 };
846
847 $tables = array(
848 // The Precomputed inverse mixColumns tables dt0 - dt3
849 $dt0,
850 $dt1,
851 $dt2,
852 $dt3,
853 // The inverse SubByte S-Box
854 array(
855 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
856 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
857 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
858 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
859 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
860 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
861 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
862 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
863 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
864 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
865 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
866 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
867 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
868 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
869 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
870 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
871 )
872 );
873 }
874 return $tables;
875 }
876
877 /**
878 * Setup the performance-optimized function for de/encrypt()
879 *
880 * @see Crypt_Base::_setupInlineCrypt()
881 * @access private
882 */
883 function _setupInlineCrypt()
884 {
885 // Note: _setupInlineCrypt() will be called only if $this->changed === true
886 // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
887 // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
888
889 $lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();
890
891 // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
892 // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
893 // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
894 $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
895
896 // Generation of a uniqe hash for our generated code
897 $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
898 if ($gen_hi_opt_code) {
899 $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
900 }
901
902 if (!isset($lambda_functions[$code_hash])) {
903 switch (true) {
904 case $gen_hi_opt_code:
905 // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
906 $w = $this->w;
907 $dw = $this->dw;
908 $init_encrypt = '';
909 $init_decrypt = '';
910 break;
911 default:
912 for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
913 $w[] = '$w[' . $i . ']';
914 $dw[] = '$dw[' . $i . ']';
915 }
916 $init_encrypt = '$w = $self->w;';
917 $init_decrypt = '$dw = $self->dw;';
918 }
919
920 $Nr = $this->Nr;
921 $Nb = $this->Nb;
922 $c = $this->c;
923
924 // Generating encrypt code:
925 $init_encrypt.= '
926 static $tables;
927 if (empty($tables)) {
928 $tables = &$self->_getTables();
929 }
930 $t0 = $tables[0];
931 $t1 = $tables[1];
932 $t2 = $tables[2];
933 $t3 = $tables[3];
934 $sbox = $tables[4];
935 ';
936
937 $s = 'e';
938 $e = 's';
939 $wc = $Nb - 1;
940
941 // Preround: addRoundKey
942 $encrypt_block = '$in = unpack("N*", $in);'."\n";
943 for ($i = 0; $i < $Nb; ++$i) {
944 $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
945 }
946
947 // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
948 for ($round = 1; $round < $Nr; ++$round) {
949 list($s, $e) = array($e, $s);
950 for ($i = 0; $i < $Nb; ++$i) {
951 $encrypt_block.=
952 '$'.$e.$i.' =
953 $t0[($'.$s.$i .' >> 24) & 0xff] ^
954 $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
955 $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^
956 $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^
957 '.$w[++$wc].";\n";
958 }
959 }
960
961 // Finalround: subWord + shiftRows + addRoundKey
962 for ($i = 0; $i < $Nb; ++$i) {
963 $encrypt_block.=
964 '$'.$e.$i.' =
965 $sbox[ $'.$e.$i.' & 0xff] |
966 ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
967 ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
968 ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
969 }
970 $encrypt_block .= '$in = pack("N*"'."\n";
971 for ($i = 0; $i < $Nb; ++$i) {
972 $encrypt_block.= ',
973 ($'.$e.$i .' & '.((int)0xFF000000).') ^
974 ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
975 ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
976 ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
977 '.$w[$i]."\n";
978 }
979 $encrypt_block .= ');';
980
981 // Generating decrypt code:
982 $init_decrypt.= '
983 static $invtables;
984 if (empty($invtables)) {
985 $invtables = &$self->_getInvTables();
986 }
987 $dt0 = $invtables[0];
988 $dt1 = $invtables[1];
989 $dt2 = $invtables[2];
990 $dt3 = $invtables[3];
991 $isbox = $invtables[4];
992 ';
993
994 $s = 'e';
995 $e = 's';
996 $wc = $Nb - 1;
997
998 // Preround: addRoundKey
999 $decrypt_block = '$in = unpack("N*", $in);'."\n";
1000 for ($i = 0; $i < $Nb; ++$i) {
1001 $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
1002 }
1003
1004 // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
1005 for ($round = 1; $round < $Nr; ++$round) {
1006 list($s, $e) = array($e, $s);
1007 for ($i = 0; $i < $Nb; ++$i) {
1008 $decrypt_block.=
1009 '$'.$e.$i.' =
1010 $dt0[($'.$s.$i .' >> 24) & 0xff] ^
1011 $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
1012 $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^
1013 $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^
1014 '.$dw[++$wc].";\n";
1015 }
1016 }
1017
1018 // Finalround: subWord + shiftRows + addRoundKey
1019 for ($i = 0; $i < $Nb; ++$i) {
1020 $decrypt_block.=
1021 '$'.$e.$i.' =
1022 $isbox[ $'.$e.$i.' & 0xff] |
1023 ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
1024 ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
1025 ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
1026 }
1027 $decrypt_block .= '$in = pack("N*"'."\n";
1028 for ($i = 0; $i < $Nb; ++$i) {
1029 $decrypt_block.= ',
1030 ($'.$e.$i. ' & '.((int)0xFF000000).') ^
1031 ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
1032 ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
1033 ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
1034 '.$dw[$i]."\n";
1035 }
1036 $decrypt_block .= ');';
1037
1038 $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
1039 array(
1040 'init_crypt' => '',
1041 'init_encrypt' => $init_encrypt,
1042 'init_decrypt' => $init_decrypt,
1043 'encrypt_block' => $encrypt_block,
1044 'decrypt_block' => $decrypt_block
1045 )
1046 );
1047 }
1048 $this->inline_crypt = $lambda_functions[$code_hash];
1049 }
1050 }
1051