[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
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 55 namespace 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 */ 64 class 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] & intval(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] & intval(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; 469 470 if (!isset($rcon)) { 471 $rcon = array(0, 472 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 473 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 474 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000, 475 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000, 476 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000, 477 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 478 ); 479 $rcon = array_map('intval', $rcon); 480 } 481 482 if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { 483 // already expanded 484 return; 485 } 486 $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size); 487 488 $this->Nk = $this->key_length >> 2; 489 // see Rijndael-ammended.pdf#page=44 490 $this->Nr = max($this->Nk, $this->Nb) + 6; 491 492 // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44, 493 // "Table 8: Shift offsets in Shiftrow for the alternative block lengths" 494 // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14, 495 // "Table 2: Shift offsets for different block lengths" 496 switch ($this->Nb) { 497 case 4: 498 case 5: 499 case 6: 500 $this->c = array(0, 1, 2, 3); 501 break; 502 case 7: 503 $this->c = array(0, 1, 2, 4); 504 break; 505 case 8: 506 $this->c = array(0, 1, 3, 4); 507 } 508 509 $w = array_values(unpack('N*words', $this->key)); 510 511 $length = $this->Nb * ($this->Nr + 1); 512 for ($i = $this->Nk; $i < $length; $i++) { 513 $temp = $w[$i - 1]; 514 if ($i % $this->Nk == 0) { 515 // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent". 516 // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine, 517 // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and' 518 // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is. 519 $temp = (($temp << 8) & intval(0xFFFFFF00)) | (($temp >> 24) & 0x000000FF); // rotWord 520 $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk]; 521 } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { 522 $temp = $this->_subWord($temp); 523 } 524 $w[$i] = $w[$i - $this->Nk] ^ $temp; 525 } 526 527 // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns 528 // and generate the inverse key schedule. more specifically, 529 // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3), 530 // "The key expansion for the Inverse Cipher is defined as follows: 531 // 1. Apply the Key Expansion. 532 // 2. Apply InvMixColumn to all Round Keys except the first and the last one." 533 // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher" 534 list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables(); 535 $temp = $this->w = $this->dw = array(); 536 for ($i = $row = $col = 0; $i < $length; $i++, $col++) { 537 if ($col == $this->Nb) { 538 if ($row == 0) { 539 $this->dw[0] = $this->w[0]; 540 } else { 541 // subWord + invMixColumn + invSubWord = invMixColumn 542 $j = 0; 543 while ($j < $this->Nb) { 544 $dw = $this->_subWord($this->w[$row][$j]); 545 $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^ 546 $dt1[$dw >> 16 & 0x000000FF] ^ 547 $dt2[$dw >> 8 & 0x000000FF] ^ 548 $dt3[$dw & 0x000000FF]; 549 $j++; 550 } 551 $this->dw[$row] = $temp; 552 } 553 554 $col = 0; 555 $row++; 556 } 557 $this->w[$row][$col] = $w[$i]; 558 } 559 560 $this->dw[$row] = $this->w[$row]; 561 562 // Converting to 1-dim key arrays (both ascending) 563 $this->dw = array_reverse($this->dw); 564 $w = array_pop($this->w); 565 $dw = array_pop($this->dw); 566 foreach ($this->w as $r => $wr) { 567 foreach ($wr as $c => $wc) { 568 $w[] = $wc; 569 $dw[] = $this->dw[$r][$c]; 570 } 571 } 572 $this->w = $w; 573 $this->dw = $dw; 574 } 575 576 /** 577 * Performs S-Box substitutions 578 * 579 * @access private 580 * @param int $word 581 */ 582 function _subWord($word) 583 { 584 static $sbox; 585 if (empty($sbox)) { 586 list(, , , , $sbox) = $this->_getTables(); 587 } 588 589 return $sbox[$word & 0x000000FF] | 590 ($sbox[$word >> 8 & 0x000000FF] << 8) | 591 ($sbox[$word >> 16 & 0x000000FF] << 16) | 592 ($sbox[$word >> 24 & 0x000000FF] << 24); 593 } 594 595 /** 596 * Provides the mixColumns and sboxes tables 597 * 598 * @see self::_encryptBlock() 599 * @see self::_setupInlineCrypt() 600 * @see self::_subWord() 601 * @access private 602 * @return array &$tables 603 */ 604 function &_getTables() 605 { 606 static $tables; 607 if (empty($tables)) { 608 // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1), 609 // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so 610 // those are the names we'll use. 611 $t3 = array_map('intval', array( 612 // with array_map('intval', ...) we ensure we have only int's and not 613 // some slower floats converted by php automatically on high values 614 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, 615 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 616 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, 617 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, 618 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 619 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, 620 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, 621 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 622 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, 623 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, 624 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 625 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, 626 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, 627 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 628 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, 629 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, 630 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 631 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, 632 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, 633 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 634 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, 635 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, 636 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 637 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, 638 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, 639 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 640 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, 641 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, 642 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 643 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, 644 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, 645 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C 646 )); 647 648 foreach ($t3 as $t3i) { 649 $t0[] = (($t3i << 24) & intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF); 650 $t1[] = (($t3i << 16) & intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF); 651 $t2[] = (($t3i << 8) & intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF); 652 } 653 654 $tables = array( 655 // The Precomputed mixColumns tables t0 - t3 656 $t0, 657 $t1, 658 $t2, 659 $t3, 660 // The SubByte S-Box 661 array( 662 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 663 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 664 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 665 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 666 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 667 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 668 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 669 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 670 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 671 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 672 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 673 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 674 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 675 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 676 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 677 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 678 ) 679 ); 680 } 681 return $tables; 682 } 683 684 /** 685 * Provides the inverse mixColumns and inverse sboxes tables 686 * 687 * @see self::_decryptBlock() 688 * @see self::_setupInlineCrypt() 689 * @see self::_setupKey() 690 * @access private 691 * @return array &$tables 692 */ 693 function &_getInvTables() 694 { 695 static $tables; 696 if (empty($tables)) { 697 $dt3 = array_map('intval', array( 698 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, 699 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 700 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, 701 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, 702 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 703 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, 704 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, 705 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 706 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, 707 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, 708 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 709 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, 710 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, 711 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 712 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, 713 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, 714 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 715 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, 716 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, 717 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 718 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, 719 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, 720 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 721 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, 722 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, 723 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 724 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, 725 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, 726 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 727 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, 728 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, 729 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 730 )); 731 732 foreach ($dt3 as $dt3i) { 733 $dt0[] = (($dt3i << 24) & intval(0xFF000000)) | (($dt3i >> 8) & 0x00FFFFFF); 734 $dt1[] = (($dt3i << 16) & intval(0xFFFF0000)) | (($dt3i >> 16) & 0x0000FFFF); 735 $dt2[] = (($dt3i << 8) & intval(0xFFFFFF00)) | (($dt3i >> 24) & 0x000000FF); 736 }; 737 738 $tables = array( 739 // The Precomputed inverse mixColumns tables dt0 - dt3 740 $dt0, 741 $dt1, 742 $dt2, 743 $dt3, 744 // The inverse SubByte S-Box 745 array( 746 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 747 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 748 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 749 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 750 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 751 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 752 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 753 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 754 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 755 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 756 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 757 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 758 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 759 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 760 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 761 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D 762 ) 763 ); 764 } 765 return $tables; 766 } 767 768 /** 769 * Setup the performance-optimized function for de/encrypt() 770 * 771 * @see \phpseclib\Crypt\Base::_setupInlineCrypt() 772 * @access private 773 */ 774 function _setupInlineCrypt() 775 { 776 // Note: _setupInlineCrypt() will be called only if $this->changed === true 777 // So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt(). 778 // However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible. 779 780 $lambda_functions =& self::_getLambdaFunctions(); 781 782 // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. 783 // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit) 784 // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. 785 $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); 786 787 // Generation of a uniqe hash for our generated code 788 $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}"; 789 if ($gen_hi_opt_code) { 790 $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); 791 } 792 793 if (!isset($lambda_functions[$code_hash])) { 794 switch (true) { 795 case $gen_hi_opt_code: 796 // The hi-optimized $lambda_functions will use the key-words hardcoded for better performance. 797 $w = $this->w; 798 $dw = $this->dw; 799 $init_encrypt = ''; 800 $init_decrypt = ''; 801 break; 802 default: 803 for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) { 804 $w[] = '$w[' . $i . ']'; 805 $dw[] = '$dw[' . $i . ']'; 806 } 807 $init_encrypt = '$w = $self->w;'; 808 $init_decrypt = '$dw = $self->dw;'; 809 } 810 811 $Nr = $this->Nr; 812 $Nb = $this->Nb; 813 $c = $this->c; 814 815 // Generating encrypt code: 816 $init_encrypt.= ' 817 static $tables; 818 if (empty($tables)) { 819 $tables = &$self->_getTables(); 820 } 821 $t0 = $tables[0]; 822 $t1 = $tables[1]; 823 $t2 = $tables[2]; 824 $t3 = $tables[3]; 825 $sbox = $tables[4]; 826 '; 827 828 $s = 'e'; 829 $e = 's'; 830 $wc = $Nb - 1; 831 832 // Preround: addRoundKey 833 $encrypt_block = '$in = unpack("N*", $in);'."\n"; 834 for ($i = 0; $i < $Nb; ++$i) { 835 $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n"; 836 } 837 838 // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey 839 for ($round = 1; $round < $Nr; ++$round) { 840 list($s, $e) = array($e, $s); 841 for ($i = 0; $i < $Nb; ++$i) { 842 $encrypt_block.= 843 '$'.$e.$i.' = 844 $t0[($'.$s.$i .' >> 24) & 0xff] ^ 845 $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^ 846 $t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^ 847 $t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^ 848 '.$w[++$wc].";\n"; 849 } 850 } 851 852 // Finalround: subWord + shiftRows + addRoundKey 853 for ($i = 0; $i < $Nb; ++$i) { 854 $encrypt_block.= 855 '$'.$e.$i.' = 856 $sbox[ $'.$e.$i.' & 0xff] | 857 ($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) | 858 ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) | 859 ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; 860 } 861 $encrypt_block .= '$in = pack("N*"'."\n"; 862 for ($i = 0; $i < $Nb; ++$i) { 863 $encrypt_block.= ', 864 ($'.$e.$i .' & '.((int)0xFF000000).') ^ 865 ($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^ 866 ($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^ 867 ($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^ 868 '.$w[$i]."\n"; 869 } 870 $encrypt_block .= ');'; 871 872 // Generating decrypt code: 873 $init_decrypt.= ' 874 static $invtables; 875 if (empty($invtables)) { 876 $invtables = &$self->_getInvTables(); 877 } 878 $dt0 = $invtables[0]; 879 $dt1 = $invtables[1]; 880 $dt2 = $invtables[2]; 881 $dt3 = $invtables[3]; 882 $isbox = $invtables[4]; 883 '; 884 885 $s = 'e'; 886 $e = 's'; 887 $wc = $Nb - 1; 888 889 // Preround: addRoundKey 890 $decrypt_block = '$in = unpack("N*", $in);'."\n"; 891 for ($i = 0; $i < $Nb; ++$i) { 892 $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n"; 893 } 894 895 // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey 896 for ($round = 1; $round < $Nr; ++$round) { 897 list($s, $e) = array($e, $s); 898 for ($i = 0; $i < $Nb; ++$i) { 899 $decrypt_block.= 900 '$'.$e.$i.' = 901 $dt0[($'.$s.$i .' >> 24) & 0xff] ^ 902 $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^ 903 $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^ 904 $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^ 905 '.$dw[++$wc].";\n"; 906 } 907 } 908 909 // Finalround: subWord + shiftRows + addRoundKey 910 for ($i = 0; $i < $Nb; ++$i) { 911 $decrypt_block.= 912 '$'.$e.$i.' = 913 $isbox[ $'.$e.$i.' & 0xff] | 914 ($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) | 915 ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) | 916 ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; 917 } 918 $decrypt_block .= '$in = pack("N*"'."\n"; 919 for ($i = 0; $i < $Nb; ++$i) { 920 $decrypt_block.= ', 921 ($'.$e.$i. ' & '.((int)0xFF000000).') ^ 922 ($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^ 923 ($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^ 924 ($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^ 925 '.$dw[$i]."\n"; 926 } 927 $decrypt_block .= ');'; 928 929 $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( 930 array( 931 'init_crypt' => '', 932 'init_encrypt' => $init_encrypt, 933 'init_decrypt' => $init_decrypt, 934 'encrypt_block' => $encrypt_block, 935 'decrypt_block' => $decrypt_block 936 ) 937 ); 938 } 939 $this->inline_crypt = $lambda_functions[$code_hash]; 940 } 941 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body