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