[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/phpseclib/phpseclib/phpseclib/Crypt/ -> Rijndael.php (source)

   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  }