PluginProbe
Contact Forms by Cimatti / trunk
Contact Forms by Cimatti vtrunk
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 trunk, at phpseclib-crypt/Rijndael.php

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