[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

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


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer