[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

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

   1  <?php
   2  
   3  /**
   4   * Base Class for all \phpseclib\Crypt\* cipher classes
   5   *
   6   * PHP version 5
   7   *
   8   * Internally for phpseclib developers:
   9   *  If you plan to add a new cipher class, please note following rules:
  10   *
  11   *  - The new \phpseclib\Crypt\* cipher class should extend \phpseclib\Crypt\Base
  12   *
  13   *  - Following methods are then required to be overridden/overloaded:
  14   *
  15   *    - _encryptBlock()
  16   *
  17   *    - _decryptBlock()
  18   *
  19   *    - _setupKey()
  20   *
  21   *  - All other methods are optional to be overridden/overloaded
  22   *
  23   *  - Look at the source code of the current ciphers how they extend \phpseclib\Crypt\Base
  24   *    and take one of them as a start up for the new cipher class.
  25   *
  26   *  - Please read all the other comments/notes/hints here also for each class var/method
  27   *
  28   * @category  Crypt
  29   * @package   Base
  30   * @author    Jim Wigginton <terrafrost@php.net>
  31   * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
  32   * @copyright 2007 Jim Wigginton
  33   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  34   * @link      http://phpseclib.sourceforge.net
  35   */
  36  
  37  namespace phpseclib\Crypt;
  38  
  39  /**
  40   * Base Class for all \phpseclib\Crypt\* cipher classes
  41   *
  42   * @package Base
  43   * @author  Jim Wigginton <terrafrost@php.net>
  44   * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
  45   */
  46  abstract class Base
  47  {
  48      /**#@+
  49       * @access public
  50       * @see \phpseclib\Crypt\Base::encrypt()
  51       * @see \phpseclib\Crypt\Base::decrypt()
  52       */
  53      /**
  54       * Encrypt / decrypt using the Counter mode.
  55       *
  56       * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
  57       *
  58       * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
  59       */
  60      const MODE_CTR = -1;
  61      /**
  62       * Encrypt / decrypt using the Electronic Code Book mode.
  63       *
  64       * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
  65       */
  66      const MODE_ECB = 1;
  67      /**
  68       * Encrypt / decrypt using the Code Book Chaining mode.
  69       *
  70       * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
  71       */
  72      const MODE_CBC = 2;
  73      /**
  74       * Encrypt / decrypt using the Cipher Feedback mode.
  75       *
  76       * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
  77       */
  78      const MODE_CFB = 3;
  79      /**
  80       * Encrypt / decrypt using the Cipher Feedback mode (8bit)
  81       */
  82      const MODE_CFB8 = 38;
  83      /**
  84       * Encrypt / decrypt using the Output Feedback mode.
  85       *
  86       * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
  87       */
  88      const MODE_OFB = 4;
  89      /**
  90       * Encrypt / decrypt using streaming mode.
  91       */
  92      const MODE_STREAM = 5;
  93      /**#@-*/
  94  
  95      /**
  96       * Whirlpool available flag
  97       *
  98       * @see \phpseclib\Crypt\Base::_hashInlineCryptFunction()
  99       * @var bool
 100       * @access private
 101       */
 102      static $WHIRLPOOL_AVAILABLE;
 103  
 104      /**#@+
 105       * @access private
 106       * @see \phpseclib\Crypt\Base::__construct()
 107       */
 108      /**
 109       * Base value for the internal implementation $engine switch
 110       */
 111      const ENGINE_INTERNAL = 1;
 112      /**
 113       * Base value for the mcrypt implementation $engine switch
 114       */
 115      const ENGINE_MCRYPT = 2;
 116      /**
 117       * Base value for the mcrypt implementation $engine switch
 118       */
 119      const ENGINE_OPENSSL = 3;
 120      /**#@-*/
 121  
 122      /**
 123       * The Encryption Mode
 124       *
 125       * @see self::__construct()
 126       * @var int
 127       * @access private
 128       */
 129      var $mode;
 130  
 131      /**
 132       * The Block Length of the block cipher
 133       *
 134       * @var int
 135       * @access private
 136       */
 137      var $block_size = 16;
 138  
 139      /**
 140       * The Key
 141       *
 142       * @see self::setKey()
 143       * @var string
 144       * @access private
 145       */
 146      var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 147  
 148      /**
 149       * The Initialization Vector
 150       *
 151       * @see self::setIV()
 152       * @var string
 153       * @access private
 154       */
 155      var $iv;
 156  
 157      /**
 158       * A "sliding" Initialization Vector
 159       *
 160       * @see self::enableContinuousBuffer()
 161       * @see self::_clearBuffers()
 162       * @var string
 163       * @access private
 164       */
 165      var $encryptIV;
 166  
 167      /**
 168       * A "sliding" Initialization Vector
 169       *
 170       * @see self::enableContinuousBuffer()
 171       * @see self::_clearBuffers()
 172       * @var string
 173       * @access private
 174       */
 175      var $decryptIV;
 176  
 177      /**
 178       * Continuous Buffer status
 179       *
 180       * @see self::enableContinuousBuffer()
 181       * @var bool
 182       * @access private
 183       */
 184      var $continuousBuffer = false;
 185  
 186      /**
 187       * Encryption buffer for CTR, OFB and CFB modes
 188       *
 189       * @see self::encrypt()
 190       * @see self::_clearBuffers()
 191       * @var array
 192       * @access private
 193       */
 194      var $enbuffer;
 195  
 196      /**
 197       * Decryption buffer for CTR, OFB and CFB modes
 198       *
 199       * @see self::decrypt()
 200       * @see self::_clearBuffers()
 201       * @var array
 202       * @access private
 203       */
 204      var $debuffer;
 205  
 206      /**
 207       * mcrypt resource for encryption
 208       *
 209       * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
 210       * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
 211       *
 212       * @see self::encrypt()
 213       * @var resource
 214       * @access private
 215       */
 216      var $enmcrypt;
 217  
 218      /**
 219       * mcrypt resource for decryption
 220       *
 221       * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
 222       * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
 223       *
 224       * @see self::decrypt()
 225       * @var resource
 226       * @access private
 227       */
 228      var $demcrypt;
 229  
 230      /**
 231       * Does the enmcrypt resource need to be (re)initialized?
 232       *
 233       * @see \phpseclib\Crypt\Twofish::setKey()
 234       * @see \phpseclib\Crypt\Twofish::setIV()
 235       * @var bool
 236       * @access private
 237       */
 238      var $enchanged = true;
 239  
 240      /**
 241       * Does the demcrypt resource need to be (re)initialized?
 242       *
 243       * @see \phpseclib\Crypt\Twofish::setKey()
 244       * @see \phpseclib\Crypt\Twofish::setIV()
 245       * @var bool
 246       * @access private
 247       */
 248      var $dechanged = true;
 249  
 250      /**
 251       * mcrypt resource for CFB mode
 252       *
 253       * mcrypt's CFB mode, in (and only in) buffered context,
 254       * is broken, so phpseclib implements the CFB mode by it self,
 255       * even when the mcrypt php extension is available.
 256       *
 257       * In order to do the CFB-mode work (fast) phpseclib
 258       * use a separate ECB-mode mcrypt resource.
 259       *
 260       * @link http://phpseclib.sourceforge.net/cfb-demo.phps
 261       * @see self::encrypt()
 262       * @see self::decrypt()
 263       * @see self::_setupMcrypt()
 264       * @var resource
 265       * @access private
 266       */
 267      var $ecb;
 268  
 269      /**
 270       * Optimizing value while CFB-encrypting
 271       *
 272       * Only relevant if $continuousBuffer enabled
 273       * and $engine == self::ENGINE_MCRYPT
 274       *
 275       * It's faster to re-init $enmcrypt if
 276       * $buffer bytes > $cfb_init_len than
 277       * using the $ecb resource furthermore.
 278       *
 279       * This value depends of the chosen cipher
 280       * and the time it would be needed for it's
 281       * initialization [by mcrypt_generic_init()]
 282       * which, typically, depends on the complexity
 283       * on its internaly Key-expanding algorithm.
 284       *
 285       * @see self::encrypt()
 286       * @var int
 287       * @access private
 288       */
 289      var $cfb_init_len = 600;
 290  
 291      /**
 292       * Does internal cipher state need to be (re)initialized?
 293       *
 294       * @see self::setKey()
 295       * @see self::setIV()
 296       * @see self::disableContinuousBuffer()
 297       * @var bool
 298       * @access private
 299       */
 300      var $changed = true;
 301  
 302      /**
 303       * Padding status
 304       *
 305       * @see self::enablePadding()
 306       * @var bool
 307       * @access private
 308       */
 309      var $padding = true;
 310  
 311      /**
 312       * Is the mode one that is paddable?
 313       *
 314       * @see self::__construct()
 315       * @var bool
 316       * @access private
 317       */
 318      var $paddable = false;
 319  
 320      /**
 321       * Holds which crypt engine internaly should be use,
 322       * which will be determined automatically on __construct()
 323       *
 324       * Currently available $engines are:
 325       * - self::ENGINE_OPENSSL  (very fast, php-extension: openssl, extension_loaded('openssl') required)
 326       * - self::ENGINE_MCRYPT   (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
 327       * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
 328       *
 329       * @see self::_setEngine()
 330       * @see self::encrypt()
 331       * @see self::decrypt()
 332       * @var int
 333       * @access private
 334       */
 335      var $engine;
 336  
 337      /**
 338       * Holds the preferred crypt engine
 339       *
 340       * @see self::_setEngine()
 341       * @see self::setPreferredEngine()
 342       * @var int
 343       * @access private
 344       */
 345      var $preferredEngine;
 346  
 347      /**
 348       * The mcrypt specific name of the cipher
 349       *
 350       * Only used if $engine == self::ENGINE_MCRYPT
 351       *
 352       * @link http://www.php.net/mcrypt_module_open
 353       * @link http://www.php.net/mcrypt_list_algorithms
 354       * @see self::_setupMcrypt()
 355       * @var string
 356       * @access private
 357       */
 358      var $cipher_name_mcrypt;
 359  
 360      /**
 361       * The openssl specific name of the cipher
 362       *
 363       * Only used if $engine == self::ENGINE_OPENSSL
 364       *
 365       * @link http://www.php.net/openssl-get-cipher-methods
 366       * @var string
 367       * @access private
 368       */
 369      var $cipher_name_openssl;
 370  
 371      /**
 372       * The openssl specific name of the cipher in ECB mode
 373       *
 374       * If OpenSSL does not support the mode we're trying to use (CTR)
 375       * it can still be emulated with ECB mode.
 376       *
 377       * @link http://www.php.net/openssl-get-cipher-methods
 378       * @var string
 379       * @access private
 380       */
 381      var $cipher_name_openssl_ecb;
 382  
 383      /**
 384       * The default salt used by setPassword()
 385       *
 386       * @see self::setPassword()
 387       * @var string
 388       * @access private
 389       */
 390      var $password_default_salt = 'phpseclib/salt';
 391  
 392      /**
 393       * The name of the performance-optimized callback function
 394       *
 395       * Used by encrypt() / decrypt()
 396       * only if $engine == self::ENGINE_INTERNAL
 397       *
 398       * @see self::encrypt()
 399       * @see self::decrypt()
 400       * @see self::_setupInlineCrypt()
 401       * @see self::$use_inline_crypt
 402       * @var Callback
 403       * @access private
 404       */
 405      var $inline_crypt;
 406  
 407      /**
 408       * Holds whether performance-optimized $inline_crypt() can/should be used.
 409       *
 410       * @see self::encrypt()
 411       * @see self::decrypt()
 412       * @see self::inline_crypt
 413       * @var mixed
 414       * @access private
 415       */
 416      var $use_inline_crypt = true;
 417  
 418      /**
 419       * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
 420       *
 421       * @see self::_openssl_ctr_process()
 422       * @var bool
 423       * @access private
 424       */
 425      var $openssl_emulate_ctr = false;
 426  
 427      /**
 428       * Determines what options are passed to openssl_encrypt/decrypt
 429       *
 430       * @see self::isValidEngine()
 431       * @var mixed
 432       * @access private
 433       */
 434      var $openssl_options;
 435  
 436      /**
 437       * Has the key length explicitly been set or should it be derived from the key, itself?
 438       *
 439       * @see self::setKeyLength()
 440       * @var bool
 441       * @access private
 442       */
 443      var $explicit_key_length = false;
 444  
 445      /**
 446       * Don't truncate / null pad key
 447       *
 448       * @see self::_clearBuffers()
 449       * @var bool
 450       * @access private
 451       */
 452      var $skip_key_adjustment = false;
 453  
 454      /**
 455       * Default Constructor.
 456       *
 457       * Determines whether or not the mcrypt extension should be used.
 458       *
 459       * $mode could be:
 460       *
 461       * - self::MODE_ECB
 462       *
 463       * - self::MODE_CBC
 464       *
 465       * - self::MODE_CTR
 466       *
 467       * - self::MODE_CFB
 468       *
 469       * - self::MODE_OFB
 470       *
 471       * If not explicitly set, self::MODE_CBC will be used.
 472       *
 473       * @param int $mode
 474       * @access public
 475       */
 476      function __construct($mode = self::MODE_CBC)
 477      {
 478          // $mode dependent settings
 479          switch ($mode) {
 480              case self::MODE_ECB:
 481                  $this->paddable = true;
 482                  $this->mode = self::MODE_ECB;
 483                  break;
 484              case self::MODE_CTR:
 485              case self::MODE_CFB:
 486              case self::MODE_CFB8:
 487              case self::MODE_OFB:
 488              case self::MODE_STREAM:
 489                  $this->mode = $mode;
 490                  break;
 491              case self::MODE_CBC:
 492              default:
 493                  $this->paddable = true;
 494                  $this->mode = self::MODE_CBC;
 495          }
 496  
 497          $this->_setEngine();
 498      }
 499  
 500      /**
 501       * Sets the initialization vector. (optional)
 502       *
 503       * SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used.  If not explicitly set, it'll be assumed
 504       * to be all zero's.
 505       *
 506       * @access public
 507       * @param string $iv
 508       * @internal Can be overwritten by a sub class, but does not have to be
 509       */
 510      function setIV($iv)
 511      {
 512          if ($this->mode == self::MODE_ECB) {
 513              return;
 514          }
 515  
 516          $this->iv = $iv;
 517          $this->changed = true;
 518      }
 519  
 520      /**
 521       * Sets the key length.
 522       *
 523       * Keys with explicitly set lengths need to be treated accordingly
 524       *
 525       * @access public
 526       * @param int $length
 527       */
 528      function setKeyLength($length)
 529      {
 530          $this->explicit_key_length = true;
 531          $this->changed = true;
 532          $this->_setEngine();
 533      }
 534  
 535      /**
 536       * Returns the current key length in bits
 537       *
 538       * @access public
 539       * @return int
 540       */
 541      function getKeyLength()
 542      {
 543          return $this->key_length << 3;
 544      }
 545  
 546      /**
 547       * Returns the current block length in bits
 548       *
 549       * @access public
 550       * @return int
 551       */
 552      function getBlockLength()
 553      {
 554          return $this->block_size << 3;
 555      }
 556  
 557      /**
 558       * Sets the key.
 559       *
 560       * The min/max length(s) of the key depends on the cipher which is used.
 561       * If the key not fits the length(s) of the cipher it will paded with null bytes
 562       * up to the closest valid key length.  If the key is more than max length,
 563       * we trim the excess bits.
 564       *
 565       * If the key is not explicitly set, it'll be assumed to be all null bytes.
 566       *
 567       * @access public
 568       * @param string $key
 569       * @internal Could, but not must, extend by the child Crypt_* class
 570       */
 571      function setKey($key)
 572      {
 573          if (!$this->explicit_key_length) {
 574              $this->setKeyLength(strlen($key) << 3);
 575              $this->explicit_key_length = false;
 576          }
 577  
 578          $this->key = $key;
 579          $this->changed = true;
 580          $this->_setEngine();
 581      }
 582  
 583      /**
 584       * Sets the password.
 585       *
 586       * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
 587       *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
 588       *         $hash, $salt, $count, $dkLen
 589       *
 590       *         Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
 591       *
 592       * @see Crypt/Hash.php
 593       * @param string $password
 594       * @param string $method
 595       * @return bool
 596       * @access public
 597       * @internal Could, but not must, extend by the child Crypt_* class
 598       */
 599      function setPassword($password, $method = 'pbkdf2')
 600      {
 601          $key = '';
 602  
 603          switch ($method) {
 604              default: // 'pbkdf2' or 'pbkdf1'
 605                  $func_args = func_get_args();
 606  
 607                  // Hash function
 608                  $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
 609  
 610                  // WPA and WPA2 use the SSID as the salt
 611                  $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
 612  
 613                  // RFC2898#section-4.2 uses 1,000 iterations by default
 614                  // WPA and WPA2 use 4,096.
 615                  $count = isset($func_args[4]) ? $func_args[4] : 1000;
 616  
 617                  // Keylength
 618                  if (isset($func_args[5])) {
 619                      $dkLen = $func_args[5];
 620                  } else {
 621                      $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
 622                  }
 623  
 624                  switch (true) {
 625                      case $method == 'pbkdf1':
 626                          $hashObj = new Hash();
 627                          $hashObj->setHash($hash);
 628                          if ($dkLen > $hashObj->getLength()) {
 629                              user_error('Derived key too long');
 630                              return false;
 631                          }
 632                          $t = $password . $salt;
 633                          for ($i = 0; $i < $count; ++$i) {
 634                              $t = $hashObj->hash($t);
 635                          }
 636                          $key = substr($t, 0, $dkLen);
 637  
 638                          $this->setKey(substr($key, 0, $dkLen >> 1));
 639                          $this->setIV(substr($key, $dkLen >> 1));
 640  
 641                          return true;
 642                      // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
 643                      case !function_exists('hash_pbkdf2'):
 644                      case !function_exists('hash_algos'):
 645                      case !in_array($hash, hash_algos()):
 646                          $i = 1;
 647                          $hmac = new Hash();
 648                          $hmac->setHash($hash);
 649                          $hmac->setKey($password);
 650                          while (strlen($key) < $dkLen) {
 651                              $f = $u = $hmac->hash($salt . pack('N', $i++));
 652                              for ($j = 2; $j <= $count; ++$j) {
 653                                  $u = $hmac->hash($u);
 654                                  $f^= $u;
 655                              }
 656                              $key.= $f;
 657                          }
 658                          $key = substr($key, 0, $dkLen);
 659                          break;
 660                      default:
 661                          $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
 662                  }
 663          }
 664  
 665          $this->setKey($key);
 666  
 667          return true;
 668      }
 669  
 670      /**
 671       * Encrypts a message.
 672       *
 673       * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
 674       * implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
 675       * necessary are discussed in the following
 676       * URL:
 677       *
 678       * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
 679       *
 680       * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
 681       * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
 682       * length.
 683       *
 684       * @see self::decrypt()
 685       * @access public
 686       * @param string $plaintext
 687       * @return string $ciphertext
 688       * @internal Could, but not must, extend by the child Crypt_* class
 689       */
 690      function encrypt($plaintext)
 691      {
 692          if ($this->paddable) {
 693              $plaintext = $this->_pad($plaintext);
 694          }
 695  
 696          if ($this->engine === self::ENGINE_OPENSSL) {
 697              if ($this->changed) {
 698                  $this->_clearBuffers();
 699                  $this->changed = false;
 700              }
 701              switch ($this->mode) {
 702                  case self::MODE_STREAM:
 703                      return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
 704                  case self::MODE_ECB:
 705                      $result = @openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
 706                      return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
 707                  case self::MODE_CBC:
 708                      $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
 709                      if (!defined('OPENSSL_RAW_DATA')) {
 710                          $result = substr($result, 0, -$this->block_size);
 711                      }
 712                      if ($this->continuousBuffer) {
 713                          $this->encryptIV = substr($result, -$this->block_size);
 714                      }
 715                      return $result;
 716                  case self::MODE_CTR:
 717                      return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
 718                  case self::MODE_CFB:
 719                      // cfb loosely routines inspired by openssl's:
 720                      // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
 721                      $ciphertext = '';
 722                      if ($this->continuousBuffer) {
 723                          $iv = &$this->encryptIV;
 724                          $pos = &$this->enbuffer['pos'];
 725                      } else {
 726                          $iv = $this->encryptIV;
 727                          $pos = 0;
 728                      }
 729                      $len = strlen($plaintext);
 730                      $i = 0;
 731                      if ($pos) {
 732                          $orig_pos = $pos;
 733                          $max = $this->block_size - $pos;
 734                          if ($len >= $max) {
 735                              $i = $max;
 736                              $len-= $max;
 737                              $pos = 0;
 738                          } else {
 739                              $i = $len;
 740                              $pos+= $len;
 741                              $len = 0;
 742                          }
 743                          // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
 744                          $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
 745                          $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
 746                          $plaintext = substr($plaintext, $i);
 747                      }
 748  
 749                      $overflow = $len % $this->block_size;
 750  
 751                      if ($overflow) {
 752                          $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
 753                          $iv = $this->_string_pop($ciphertext, $this->block_size);
 754  
 755                          $size = $len - $overflow;
 756                          $block = $iv ^ substr($plaintext, -$overflow);
 757                          $iv = substr_replace($iv, $block, 0, $overflow);
 758                          $ciphertext.= $block;
 759                          $pos = $overflow;
 760                      } elseif ($len) {
 761                          $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
 762                          $iv = substr($ciphertext, -$this->block_size);
 763                      }
 764  
 765                      return $ciphertext;
 766                  case self::MODE_CFB8:
 767                      $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
 768                      if ($this->continuousBuffer) {
 769                          if (($len = strlen($ciphertext)) >= $this->block_size) {
 770                              $this->encryptIV = substr($ciphertext, -$this->block_size);
 771                          } else {
 772                              $this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
 773                          }
 774                      }
 775                      return $ciphertext;
 776                  case self::MODE_OFB:
 777                      return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
 778              }
 779          }
 780  
 781          if ($this->engine === self::ENGINE_MCRYPT) {
 782              set_error_handler(array($this, 'do_nothing'));
 783  
 784              if ($this->changed) {
 785                  $this->_setupMcrypt();
 786                  $this->changed = false;
 787              }
 788              if ($this->enchanged) {
 789                  mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
 790                  $this->enchanged = false;
 791              }
 792  
 793              // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
 794              // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
 795              // rewritten CFB implementation the above outputs the same thing twice.
 796              if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
 797                  $block_size = $this->block_size;
 798                  $iv = &$this->encryptIV;
 799                  $pos = &$this->enbuffer['pos'];
 800                  $len = strlen($plaintext);
 801                  $ciphertext = '';
 802                  $i = 0;
 803                  if ($pos) {
 804                      $orig_pos = $pos;
 805                      $max = $block_size - $pos;
 806                      if ($len >= $max) {
 807                          $i = $max;
 808                          $len-= $max;
 809                          $pos = 0;
 810                      } else {
 811                          $i = $len;
 812                          $pos+= $len;
 813                          $len = 0;
 814                      }
 815                      $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
 816                      $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
 817                      $this->enbuffer['enmcrypt_init'] = true;
 818                  }
 819                  if ($len >= $block_size) {
 820                      if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
 821                          if ($this->enbuffer['enmcrypt_init'] === true) {
 822                              mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
 823                              $this->enbuffer['enmcrypt_init'] = false;
 824                          }
 825                          $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
 826                          $iv = substr($ciphertext, -$block_size);
 827                          $len%= $block_size;
 828                      } else {
 829                          while ($len >= $block_size) {
 830                              $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
 831                              $ciphertext.= $iv;
 832                              $len-= $block_size;
 833                              $i+= $block_size;
 834                          }
 835                      }
 836                  }
 837  
 838                  if ($len) {
 839                      $iv = mcrypt_generic($this->ecb, $iv);
 840                      $block = $iv ^ substr($plaintext, -$len);
 841                      $iv = substr_replace($iv, $block, 0, $len);
 842                      $ciphertext.= $block;
 843                      $pos = $len;
 844                  }
 845  
 846                  restore_error_handler();
 847  
 848                  return $ciphertext;
 849              }
 850  
 851              $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
 852  
 853              if (!$this->continuousBuffer) {
 854                  mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
 855              }
 856  
 857              restore_error_handler();
 858  
 859              return $ciphertext;
 860          }
 861  
 862          if ($this->changed) {
 863              $this->_setup();
 864              $this->changed = false;
 865          }
 866          if ($this->use_inline_crypt) {
 867              $inline = $this->inline_crypt;
 868              return $inline('encrypt', $this, $plaintext);
 869          }
 870  
 871          $buffer = &$this->enbuffer;
 872          $block_size = $this->block_size;
 873          $ciphertext = '';
 874          switch ($this->mode) {
 875              case self::MODE_ECB:
 876                  for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 877                      $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
 878                  }
 879                  break;
 880              case self::MODE_CBC:
 881                  $xor = $this->encryptIV;
 882                  for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 883                      $block = substr($plaintext, $i, $block_size);
 884                      $block = $this->_encryptBlock($block ^ $xor);
 885                      $xor = $block;
 886                      $ciphertext.= $block;
 887                  }
 888                  if ($this->continuousBuffer) {
 889                      $this->encryptIV = $xor;
 890                  }
 891                  break;
 892              case self::MODE_CTR:
 893                  $xor = $this->encryptIV;
 894                  if (strlen($buffer['ciphertext'])) {
 895                      for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 896                          $block = substr($plaintext, $i, $block_size);
 897                          if (strlen($block) > strlen($buffer['ciphertext'])) {
 898                              $buffer['ciphertext'].= $this->_encryptBlock($xor);
 899                          }
 900                          $this->_increment_str($xor);
 901                          $key = $this->_string_shift($buffer['ciphertext'], $block_size);
 902                          $ciphertext.= $block ^ $key;
 903                      }
 904                  } else {
 905                      for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 906                          $block = substr($plaintext, $i, $block_size);
 907                          $key = $this->_encryptBlock($xor);
 908                          $this->_increment_str($xor);
 909                          $ciphertext.= $block ^ $key;
 910                      }
 911                  }
 912                  if ($this->continuousBuffer) {
 913                      $this->encryptIV = $xor;
 914                      if ($start = strlen($plaintext) % $block_size) {
 915                          $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
 916                      }
 917                  }
 918                  break;
 919              case self::MODE_CFB:
 920                  // cfb loosely routines inspired by openssl's:
 921                  // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
 922                  if ($this->continuousBuffer) {
 923                      $iv = &$this->encryptIV;
 924                      $pos = &$buffer['pos'];
 925                  } else {
 926                      $iv = $this->encryptIV;
 927                      $pos = 0;
 928                  }
 929                  $len = strlen($plaintext);
 930                  $i = 0;
 931                  if ($pos) {
 932                      $orig_pos = $pos;
 933                      $max = $block_size - $pos;
 934                      if ($len >= $max) {
 935                          $i = $max;
 936                          $len-= $max;
 937                          $pos = 0;
 938                      } else {
 939                          $i = $len;
 940                          $pos+= $len;
 941                          $len = 0;
 942                      }
 943                      // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
 944                      $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
 945                      $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
 946                  }
 947                  while ($len >= $block_size) {
 948                      $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
 949                      $ciphertext.= $iv;
 950                      $len-= $block_size;
 951                      $i+= $block_size;
 952                  }
 953                  if ($len) {
 954                      $iv = $this->_encryptBlock($iv);
 955                      $block = $iv ^ substr($plaintext, $i);
 956                      $iv = substr_replace($iv, $block, 0, $len);
 957                      $ciphertext.= $block;
 958                      $pos = $len;
 959                  }
 960                  break;
 961              case self::MODE_CFB8:
 962                  $ciphertext = '';
 963                  $len = strlen($plaintext);
 964                  $iv = $this->encryptIV;
 965  
 966                  for ($i = 0; $i < $len; ++$i) {
 967                      $ciphertext .= ($c = $plaintext[$i] ^ $this->_encryptBlock($iv));
 968                      $iv = substr($iv, 1) . $c;
 969                  }
 970  
 971                  if ($this->continuousBuffer) {
 972                      if ($len >= $block_size) {
 973                          $this->encryptIV = substr($ciphertext, -$block_size);
 974                      } else {
 975                          $this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len);
 976                      }
 977                  }
 978                  break;
 979              case self::MODE_OFB:
 980                  $xor = $this->encryptIV;
 981                  if (strlen($buffer['xor'])) {
 982                      for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 983                          $block = substr($plaintext, $i, $block_size);
 984                          if (strlen($block) > strlen($buffer['xor'])) {
 985                              $xor = $this->_encryptBlock($xor);
 986                              $buffer['xor'].= $xor;
 987                          }
 988                          $key = $this->_string_shift($buffer['xor'], $block_size);
 989                          $ciphertext.= $block ^ $key;
 990                      }
 991                  } else {
 992                      for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
 993                          $xor = $this->_encryptBlock($xor);
 994                          $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
 995                      }
 996                      $key = $xor;
 997                  }
 998                  if ($this->continuousBuffer) {
 999                      $this->encryptIV = $xor;
1000                      if ($start = strlen($plaintext) % $block_size) {
1001                          $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1002                      }
1003                  }
1004                  break;
1005              case self::MODE_STREAM:
1006                  $ciphertext = $this->_encryptBlock($plaintext);
1007                  break;
1008          }
1009  
1010          return $ciphertext;
1011      }
1012  
1013      /**
1014       * Decrypts a message.
1015       *
1016       * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
1017       * it is.
1018       *
1019       * @see self::encrypt()
1020       * @access public
1021       * @param string $ciphertext
1022       * @return string $plaintext
1023       * @internal Could, but not must, extend by the child Crypt_* class
1024       */
1025      function decrypt($ciphertext)
1026      {
1027          if ($this->paddable) {
1028              // we pad with chr(0) since that's what mcrypt_generic does.  to quote from {@link http://www.php.net/function.mcrypt-generic}:
1029              // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
1030              $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
1031          }
1032  
1033          if ($this->engine === self::ENGINE_OPENSSL) {
1034              if ($this->changed) {
1035                  $this->_clearBuffers();
1036                  $this->changed = false;
1037              }
1038              switch ($this->mode) {
1039                  case self::MODE_STREAM:
1040                      $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1041                      break;
1042                  case self::MODE_ECB:
1043                      if (!defined('OPENSSL_RAW_DATA')) {
1044                          $ciphertext.= @openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
1045                      }
1046                      $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1047                      break;
1048                  case self::MODE_CBC:
1049                      if (!defined('OPENSSL_RAW_DATA')) {
1050                          $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
1051                          $ciphertext.= substr(@openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
1052                          $offset = 2 * $this->block_size;
1053                      } else {
1054                          $offset = $this->block_size;
1055                      }
1056                      $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
1057                      if ($this->continuousBuffer) {
1058                          $this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
1059                      }
1060                      break;
1061                  case self::MODE_CTR:
1062                      $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
1063                      break;
1064                  case self::MODE_CFB:
1065                      // cfb loosely routines inspired by openssl's:
1066                      // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1067                      $plaintext = '';
1068                      if ($this->continuousBuffer) {
1069                          $iv = &$this->decryptIV;
1070                          $pos = &$this->buffer['pos'];
1071                      } else {
1072                          $iv = $this->decryptIV;
1073                          $pos = 0;
1074                      }
1075                      $len = strlen($ciphertext);
1076                      $i = 0;
1077                      if ($pos) {
1078                          $orig_pos = $pos;
1079                          $max = $this->block_size - $pos;
1080                          if ($len >= $max) {
1081                              $i = $max;
1082                              $len-= $max;
1083                              $pos = 0;
1084                          } else {
1085                              $i = $len;
1086                              $pos+= $len;
1087                              $len = 0;
1088                          }
1089                          // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
1090                          $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1091                          $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1092                          $ciphertext = substr($ciphertext, $i);
1093                      }
1094                      $overflow = $len % $this->block_size;
1095                      if ($overflow) {
1096                          $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1097                          if ($len - $overflow) {
1098                              $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
1099                          }
1100                          $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1101                          $plaintext.= $iv ^ substr($ciphertext, -$overflow);
1102                          $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
1103                          $pos = $overflow;
1104                      } elseif ($len) {
1105                          $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1106                          $iv = substr($ciphertext, -$this->block_size);
1107                      }
1108                      break;
1109                  case self::MODE_CFB8:
1110                      $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
1111                      if ($this->continuousBuffer) {
1112                          if (($len = strlen($ciphertext)) >= $this->block_size) {
1113                              $this->decryptIV = substr($ciphertext, -$this->block_size);
1114                          } else {
1115                              $this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
1116                          }
1117                      }
1118                      break;
1119                  case self::MODE_OFB:
1120                      $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
1121              }
1122  
1123              return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1124          }
1125  
1126          if ($this->engine === self::ENGINE_MCRYPT) {
1127              set_error_handler(array($this, 'do_nothing'));
1128              $block_size = $this->block_size;
1129              if ($this->changed) {
1130                  $this->_setupMcrypt();
1131                  $this->changed = false;
1132              }
1133              if ($this->dechanged) {
1134                  mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1135                  $this->dechanged = false;
1136              }
1137  
1138              if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
1139                  $iv = &$this->decryptIV;
1140                  $pos = &$this->debuffer['pos'];
1141                  $len = strlen($ciphertext);
1142                  $plaintext = '';
1143                  $i = 0;
1144                  if ($pos) {
1145                      $orig_pos = $pos;
1146                      $max = $block_size - $pos;
1147                      if ($len >= $max) {
1148                          $i = $max;
1149                          $len-= $max;
1150                          $pos = 0;
1151                      } else {
1152                          $i = $len;
1153                          $pos+= $len;
1154                          $len = 0;
1155                      }
1156                      // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1157                      $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1158                      $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1159                  }
1160                  if ($len >= $block_size) {
1161                      $cb = substr($ciphertext, $i, $len - $len % $block_size);
1162                      $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
1163                      $iv = substr($cb, -$block_size);
1164                      $len%= $block_size;
1165                  }
1166                  if ($len) {
1167                      $iv = mcrypt_generic($this->ecb, $iv);
1168                      $plaintext.= $iv ^ substr($ciphertext, -$len);
1169                      $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
1170                      $pos = $len;
1171                  }
1172  
1173                  restore_error_handler();
1174  
1175                  return $plaintext;
1176              }
1177  
1178              $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
1179  
1180              if (!$this->continuousBuffer) {
1181                  mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1182              }
1183  
1184              restore_error_handler();
1185  
1186              return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1187          }
1188  
1189          if ($this->changed) {
1190              $this->_setup();
1191              $this->changed = false;
1192          }
1193          if ($this->use_inline_crypt) {
1194              $inline = $this->inline_crypt;
1195              return $inline('decrypt', $this, $ciphertext);
1196          }
1197  
1198          $block_size = $this->block_size;
1199  
1200          $buffer = &$this->debuffer;
1201          $plaintext = '';
1202          switch ($this->mode) {
1203              case self::MODE_ECB:
1204                  for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1205                      $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
1206                  }
1207                  break;
1208              case self::MODE_CBC:
1209                  $xor = $this->decryptIV;
1210                  for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1211                      $block = substr($ciphertext, $i, $block_size);
1212                      $plaintext.= $this->_decryptBlock($block) ^ $xor;
1213                      $xor = $block;
1214                  }
1215                  if ($this->continuousBuffer) {
1216                      $this->decryptIV = $xor;
1217                  }
1218                  break;
1219              case self::MODE_CTR:
1220                  $xor = $this->decryptIV;
1221                  if (strlen($buffer['ciphertext'])) {
1222                      for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1223                          $block = substr($ciphertext, $i, $block_size);
1224                          if (strlen($block) > strlen($buffer['ciphertext'])) {
1225                              $buffer['ciphertext'].= $this->_encryptBlock($xor);
1226                              $this->_increment_str($xor);
1227                          }
1228                          $key = $this->_string_shift($buffer['ciphertext'], $block_size);
1229                          $plaintext.= $block ^ $key;
1230                      }
1231                  } else {
1232                      for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1233                          $block = substr($ciphertext, $i, $block_size);
1234                          $key = $this->_encryptBlock($xor);
1235                          $this->_increment_str($xor);
1236                          $plaintext.= $block ^ $key;
1237                      }
1238                  }
1239                  if ($this->continuousBuffer) {
1240                      $this->decryptIV = $xor;
1241                      if ($start = strlen($ciphertext) % $block_size) {
1242                          $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1243                      }
1244                  }
1245                  break;
1246              case self::MODE_CFB:
1247                  if ($this->continuousBuffer) {
1248                      $iv = &$this->decryptIV;
1249                      $pos = &$buffer['pos'];
1250                  } else {
1251                      $iv = $this->decryptIV;
1252                      $pos = 0;
1253                  }
1254                  $len = strlen($ciphertext);
1255                  $i = 0;
1256                  if ($pos) {
1257                      $orig_pos = $pos;
1258                      $max = $block_size - $pos;
1259                      if ($len >= $max) {
1260                          $i = $max;
1261                          $len-= $max;
1262                          $pos = 0;
1263                      } else {
1264                          $i = $len;
1265                          $pos+= $len;
1266                          $len = 0;
1267                      }
1268                      // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1269                      $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1270                      $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1271                  }
1272                  while ($len >= $block_size) {
1273                      $iv = $this->_encryptBlock($iv);
1274                      $cb = substr($ciphertext, $i, $block_size);
1275                      $plaintext.= $iv ^ $cb;
1276                      $iv = $cb;
1277                      $len-= $block_size;
1278                      $i+= $block_size;
1279                  }
1280                  if ($len) {
1281                      $iv = $this->_encryptBlock($iv);
1282                      $plaintext.= $iv ^ substr($ciphertext, $i);
1283                      $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1284                      $pos = $len;
1285                  }
1286                  break;
1287              case self::MODE_CFB8:
1288                  $plaintext = '';
1289                  $len = strlen($ciphertext);
1290                  $iv = $this->decryptIV;
1291  
1292                  for ($i = 0; $i < $len; ++$i) {
1293                      $plaintext .= $ciphertext[$i] ^ $this->_encryptBlock($iv);
1294                      $iv = substr($iv, 1) . $ciphertext[$i];
1295                  }
1296  
1297                  if ($this->continuousBuffer) {
1298                      if ($len >= $block_size) {
1299                          $this->decryptIV = substr($ciphertext, -$block_size);
1300                      } else {
1301                          $this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len);
1302                      }
1303                  }
1304                  break;
1305              case self::MODE_OFB:
1306                  $xor = $this->decryptIV;
1307                  if (strlen($buffer['xor'])) {
1308                      for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1309                          $block = substr($ciphertext, $i, $block_size);
1310                          if (strlen($block) > strlen($buffer['xor'])) {
1311                              $xor = $this->_encryptBlock($xor);
1312                              $buffer['xor'].= $xor;
1313                          }
1314                          $key = $this->_string_shift($buffer['xor'], $block_size);
1315                          $plaintext.= $block ^ $key;
1316                      }
1317                  } else {
1318                      for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1319                          $xor = $this->_encryptBlock($xor);
1320                          $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
1321                      }
1322                      $key = $xor;
1323                  }
1324                  if ($this->continuousBuffer) {
1325                      $this->decryptIV = $xor;
1326                      if ($start = strlen($ciphertext) % $block_size) {
1327                          $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1328                      }
1329                  }
1330                  break;
1331              case self::MODE_STREAM:
1332                  $plaintext = $this->_decryptBlock($ciphertext);
1333                  break;
1334          }
1335          return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1336      }
1337  
1338      /**
1339       * OpenSSL CTR Processor
1340       *
1341       * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1342       * for CTR is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
1343       * and Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
1344       * function will emulate CTR with ECB when necessary.
1345       *
1346       * @see self::encrypt()
1347       * @see self::decrypt()
1348       * @param string $plaintext
1349       * @param string $encryptIV
1350       * @param array $buffer
1351       * @return string
1352       * @access private
1353       */
1354      function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
1355      {
1356          $ciphertext = '';
1357  
1358          $block_size = $this->block_size;
1359          $key = $this->key;
1360  
1361          if ($this->openssl_emulate_ctr) {
1362              $xor = $encryptIV;
1363              if (strlen($buffer['ciphertext'])) {
1364                  for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1365                      $block = substr($plaintext, $i, $block_size);
1366                      if (strlen($block) > strlen($buffer['ciphertext'])) {
1367                          $result = @openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1368                          $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
1369                          $buffer['ciphertext'].= $result;
1370                      }
1371                      $this->_increment_str($xor);
1372                      $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
1373                      $ciphertext.= $block ^ $otp;
1374                  }
1375              } else {
1376                  for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1377                      $block = substr($plaintext, $i, $block_size);
1378                      $otp = @openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1379                      $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
1380                      $this->_increment_str($xor);
1381                      $ciphertext.= $block ^ $otp;
1382                  }
1383              }
1384              if ($this->continuousBuffer) {
1385                  $encryptIV = $xor;
1386                  if ($start = strlen($plaintext) % $block_size) {
1387                      $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1388                  }
1389              }
1390  
1391              return $ciphertext;
1392          }
1393  
1394          if (strlen($buffer['ciphertext'])) {
1395              $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
1396              $plaintext = substr($plaintext, strlen($ciphertext));
1397  
1398              if (!strlen($plaintext)) {
1399                  return $ciphertext;
1400              }
1401          }
1402  
1403          $overflow = strlen($plaintext) % $block_size;
1404          if ($overflow) {
1405              $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
1406              $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1407              $temp = $this->_string_pop($encrypted, $block_size);
1408              $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
1409              if ($this->continuousBuffer) {
1410                  $buffer['ciphertext'] = substr($temp, $overflow);
1411                  $encryptIV = $temp;
1412              }
1413          } elseif (!strlen($buffer['ciphertext'])) {
1414              $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1415              $temp = $this->_string_pop($ciphertext, $block_size);
1416              if ($this->continuousBuffer) {
1417                  $encryptIV = $temp;
1418              }
1419          }
1420          if ($this->continuousBuffer) {
1421              if (!defined('OPENSSL_RAW_DATA')) {
1422                  $encryptIV.= @openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1423              }
1424              $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1425              if ($overflow) {
1426                  $this->_increment_str($encryptIV);
1427              }
1428          }
1429  
1430          return $ciphertext;
1431      }
1432  
1433      /**
1434       * OpenSSL OFB Processor
1435       *
1436       * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1437       * for OFB is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
1438       * and Base::decrypt().
1439       *
1440       * @see self::encrypt()
1441       * @see self::decrypt()
1442       * @param string $plaintext
1443       * @param string $encryptIV
1444       * @param array $buffer
1445       * @return string
1446       * @access private
1447       */
1448      function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
1449      {
1450          if (strlen($buffer['xor'])) {
1451              $ciphertext = $plaintext ^ $buffer['xor'];
1452              $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
1453              $plaintext = substr($plaintext, strlen($ciphertext));
1454          } else {
1455              $ciphertext = '';
1456          }
1457  
1458          $block_size = $this->block_size;
1459  
1460          $len = strlen($plaintext);
1461          $key = $this->key;
1462          $overflow = $len % $block_size;
1463  
1464          if (strlen($plaintext)) {
1465              if ($overflow) {
1466                  $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1467                  $xor = $this->_string_pop($ciphertext, $block_size);
1468                  if ($this->continuousBuffer) {
1469                      $encryptIV = $xor;
1470                  }
1471                  $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
1472                  if ($this->continuousBuffer) {
1473                      $buffer['xor'] = $xor;
1474                  }
1475              } else {
1476                  $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1477                  if ($this->continuousBuffer) {
1478                      $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
1479                  }
1480              }
1481          }
1482  
1483          return $ciphertext;
1484      }
1485  
1486      /**
1487       * phpseclib <-> OpenSSL Mode Mapper
1488       *
1489       * May need to be overwritten by classes extending this one in some cases
1490       *
1491       * @return int
1492       * @access private
1493       */
1494      function _openssl_translate_mode()
1495      {
1496          switch ($this->mode) {
1497              case self::MODE_ECB:
1498                  return 'ecb';
1499              case self::MODE_CBC:
1500                  return 'cbc';
1501              case self::MODE_CTR:
1502                  return 'ctr';
1503              case self::MODE_CFB:
1504                  return 'cfb';
1505              case self::MODE_CFB8:
1506                  return 'cfb8';
1507              case self::MODE_OFB:
1508                  return 'ofb';
1509          }
1510      }
1511  
1512      /**
1513       * Pad "packets".
1514       *
1515       * Block ciphers working by encrypting between their specified [$this->]block_size at a time
1516       * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1517       * pad the input so that it is of the proper length.
1518       *
1519       * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,
1520       * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
1521       * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1522       * transmitted separately)
1523       *
1524       * @see self::disablePadding()
1525       * @access public
1526       */
1527      function enablePadding()
1528      {
1529          $this->padding = true;
1530      }
1531  
1532      /**
1533       * Do not pad packets.
1534       *
1535       * @see self::enablePadding()
1536       * @access public
1537       */
1538      function disablePadding()
1539      {
1540          $this->padding = false;
1541      }
1542  
1543      /**
1544       * Treat consecutive "packets" as if they are a continuous buffer.
1545       *
1546       * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
1547       * will yield different outputs:
1548       *
1549       * <code>
1550       *    echo $rijndael->encrypt(substr($plaintext,  0, 16));
1551       *    echo $rijndael->encrypt(substr($plaintext, 16, 16));
1552       * </code>
1553       * <code>
1554       *    echo $rijndael->encrypt($plaintext);
1555       * </code>
1556       *
1557       * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
1558       * another, as demonstrated with the following:
1559       *
1560       * <code>
1561       *    $rijndael->encrypt(substr($plaintext, 0, 16));
1562       *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1563       * </code>
1564       * <code>
1565       *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1566       * </code>
1567       *
1568       * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
1569       * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
1570       * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
1571       *
1572       * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() object changes after each
1573       * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
1574       * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
1575       * however, they are also less intuitive and more likely to cause you problems.
1576       *
1577       * @see self::disableContinuousBuffer()
1578       * @access public
1579       * @internal Could, but not must, extend by the child Crypt_* class
1580       */
1581      function enableContinuousBuffer()
1582      {
1583          if ($this->mode == self::MODE_ECB) {
1584              return;
1585          }
1586  
1587          $this->continuousBuffer = true;
1588  
1589          $this->_setEngine();
1590      }
1591  
1592      /**
1593       * Treat consecutive packets as if they are a discontinuous buffer.
1594       *
1595       * The default behavior.
1596       *
1597       * @see self::enableContinuousBuffer()
1598       * @access public
1599       * @internal Could, but not must, extend by the child Crypt_* class
1600       */
1601      function disableContinuousBuffer()
1602      {
1603          if ($this->mode == self::MODE_ECB) {
1604              return;
1605          }
1606          if (!$this->continuousBuffer) {
1607              return;
1608          }
1609  
1610          $this->continuousBuffer = false;
1611          $this->changed = true;
1612  
1613          $this->_setEngine();
1614      }
1615  
1616      /**
1617       * Test for engine validity
1618       *
1619       * @see self::__construct()
1620       * @param int $engine
1621       * @access public
1622       * @return bool
1623       */
1624      function isValidEngine($engine)
1625      {
1626          switch ($engine) {
1627              case self::ENGINE_OPENSSL:
1628                  if ($this->mode == self::MODE_STREAM && $this->continuousBuffer) {
1629                      return false;
1630                  }
1631                  $this->openssl_emulate_ctr = false;
1632                  $result = $this->cipher_name_openssl &&
1633                            extension_loaded('openssl') &&
1634                            // PHP 5.3.0 - 5.3.2 did not let you set IV's
1635                            version_compare(PHP_VERSION, '5.3.3', '>=');
1636                  if (!$result) {
1637                      return false;
1638                  }
1639  
1640                  // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
1641                  // $options openssl_encrypt expected a boolean $raw_data.
1642                  if (!defined('OPENSSL_RAW_DATA')) {
1643                      $this->openssl_options = true;
1644                  } else {
1645                      $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
1646                  }
1647  
1648                  $methods = openssl_get_cipher_methods();
1649                  if (in_array($this->cipher_name_openssl, $methods)) {
1650                      return true;
1651                  }
1652                  // not all of openssl's symmetric cipher's support ctr. for those
1653                  // that don't we'll emulate it
1654                  switch ($this->mode) {
1655                      case self::MODE_CTR:
1656                          if (in_array($this->cipher_name_openssl_ecb, $methods)) {
1657                              $this->openssl_emulate_ctr = true;
1658                              return true;
1659                          }
1660                  }
1661                  return false;
1662              case self::ENGINE_MCRYPT:
1663                  set_error_handler(array($this, 'do_nothing'));
1664                  $result = $this->cipher_name_mcrypt &&
1665                         extension_loaded('mcrypt') &&
1666                         in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
1667                  restore_error_handler();
1668                  return $result;
1669              case self::ENGINE_INTERNAL:
1670                  return true;
1671          }
1672  
1673          return false;
1674      }
1675  
1676      /**
1677       * Sets the preferred crypt engine
1678       *
1679       * Currently, $engine could be:
1680       *
1681       * - \phpseclib\Crypt\Base::ENGINE_OPENSSL  [very fast]
1682       *
1683       * - \phpseclib\Crypt\Base::ENGINE_MCRYPT   [fast]
1684       *
1685       * - \phpseclib\Crypt\Base::ENGINE_INTERNAL [slow]
1686       *
1687       * If the preferred crypt engine is not available the fastest available one will be used
1688       *
1689       * @see self::__construct()
1690       * @param int $engine
1691       * @access public
1692       */
1693      function setPreferredEngine($engine)
1694      {
1695          switch ($engine) {
1696              //case self::ENGINE_OPENSSL;
1697              case self::ENGINE_MCRYPT:
1698              case self::ENGINE_INTERNAL:
1699                  $this->preferredEngine = $engine;
1700                  break;
1701              default:
1702                  $this->preferredEngine = self::ENGINE_OPENSSL;
1703          }
1704  
1705          $this->_setEngine();
1706      }
1707  
1708      /**
1709       * Returns the engine currently being utilized
1710       *
1711       * @see self::_setEngine()
1712       * @access public
1713       */
1714      function getEngine()
1715      {
1716          return $this->engine;
1717      }
1718  
1719      /**
1720       * Sets the engine as appropriate
1721       *
1722       * @see self::__construct()
1723       * @access private
1724       */
1725      function _setEngine()
1726      {
1727          $this->engine = null;
1728  
1729          $candidateEngines = array(
1730              $this->preferredEngine,
1731              self::ENGINE_OPENSSL,
1732              self::ENGINE_MCRYPT
1733          );
1734          foreach ($candidateEngines as $engine) {
1735              if ($this->isValidEngine($engine)) {
1736                  $this->engine = $engine;
1737                  break;
1738              }
1739          }
1740          if (!$this->engine) {
1741              $this->engine = self::ENGINE_INTERNAL;
1742          }
1743  
1744          if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
1745              set_error_handler(array($this, 'do_nothing'));
1746              // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
1747              // (re)open them with the module named in $this->cipher_name_mcrypt
1748              mcrypt_module_close($this->enmcrypt);
1749              mcrypt_module_close($this->demcrypt);
1750              $this->enmcrypt = null;
1751              $this->demcrypt = null;
1752  
1753              if ($this->ecb) {
1754                  mcrypt_module_close($this->ecb);
1755                  $this->ecb = null;
1756              }
1757              restore_error_handler();
1758          }
1759  
1760          $this->changed = true;
1761      }
1762  
1763      /**
1764       * Encrypts a block
1765       *
1766       * Note: Must be extended by the child \phpseclib\Crypt\* class
1767       *
1768       * @access private
1769       * @param string $in
1770       * @return string
1771       */
1772      abstract function _encryptBlock($in);
1773  
1774      /**
1775       * Decrypts a block
1776       *
1777       * Note: Must be extended by the child \phpseclib\Crypt\* class
1778       *
1779       * @access private
1780       * @param string $in
1781       * @return string
1782       */
1783      abstract function _decryptBlock($in);
1784  
1785      /**
1786       * Setup the key (expansion)
1787       *
1788       * Only used if $engine == self::ENGINE_INTERNAL
1789       *
1790       * Note: Must extend by the child \phpseclib\Crypt\* class
1791       *
1792       * @see self::_setup()
1793       * @access private
1794       */
1795      abstract function _setupKey();
1796  
1797      /**
1798       * Setup the self::ENGINE_INTERNAL $engine
1799       *
1800       * (re)init, if necessary, the internal cipher $engine and flush all $buffers
1801       * Used (only) if $engine == self::ENGINE_INTERNAL
1802       *
1803       * _setup() will be called each time if $changed === true
1804       * typically this happens when using one or more of following public methods:
1805       *
1806       * - setKey()
1807       *
1808       * - setIV()
1809       *
1810       * - disableContinuousBuffer()
1811       *
1812       * - First run of encrypt() / decrypt() with no init-settings
1813       *
1814       * @see self::setKey()
1815       * @see self::setIV()
1816       * @see self::disableContinuousBuffer()
1817       * @access private
1818       * @internal _setup() is always called before en/decryption.
1819       * @internal Could, but not must, extend by the child Crypt_* class
1820       */
1821      function _setup()
1822      {
1823          $this->_clearBuffers();
1824          $this->_setupKey();
1825  
1826          if ($this->use_inline_crypt) {
1827              $this->_setupInlineCrypt();
1828          }
1829      }
1830  
1831      /**
1832       * Setup the self::ENGINE_MCRYPT $engine
1833       *
1834       * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
1835       * Used (only) if $engine = self::ENGINE_MCRYPT
1836       *
1837       * _setupMcrypt() will be called each time if $changed === true
1838       * typically this happens when using one or more of following public methods:
1839       *
1840       * - setKey()
1841       *
1842       * - setIV()
1843       *
1844       * - disableContinuousBuffer()
1845       *
1846       * - First run of encrypt() / decrypt()
1847       *
1848       * @see self::setKey()
1849       * @see self::setIV()
1850       * @see self::disableContinuousBuffer()
1851       * @access private
1852       * @internal Could, but not must, extend by the child Crypt_* class
1853       */
1854      function _setupMcrypt()
1855      {
1856          $this->_clearBuffers();
1857          $this->enchanged = $this->dechanged = true;
1858  
1859          if (!isset($this->enmcrypt)) {
1860              static $mcrypt_modes = array(
1861                  self::MODE_CTR    => 'ctr',
1862                  self::MODE_ECB    => MCRYPT_MODE_ECB,
1863                  self::MODE_CBC    => MCRYPT_MODE_CBC,
1864                  self::MODE_CFB    => 'ncfb',
1865                  self::MODE_CFB8   => MCRYPT_MODE_CFB,
1866                  self::MODE_OFB    => MCRYPT_MODE_NOFB,
1867                  self::MODE_STREAM => MCRYPT_MODE_STREAM,
1868              );
1869  
1870              $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1871              $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1872  
1873              // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
1874              // to workaround mcrypt's broken ncfb implementation in buffered mode
1875              // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1876              if ($this->mode == self::MODE_CFB) {
1877                  $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
1878              }
1879          } // else should mcrypt_generic_deinit be called?
1880  
1881          if ($this->mode == self::MODE_CFB) {
1882              mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
1883          }
1884      }
1885  
1886      /**
1887       * Pads a string
1888       *
1889       * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1890       * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
1891       * chr($this->block_size - (strlen($text) % $this->block_size)
1892       *
1893       * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1894       * and padding will, hence forth, be enabled.
1895       *
1896       * @see self::_unpad()
1897       * @param string $text
1898       * @access private
1899       * @return string
1900       */
1901      function _pad($text)
1902      {
1903          $length = strlen($text);
1904  
1905          if (!$this->padding) {
1906              if ($length % $this->block_size == 0) {
1907                  return $text;
1908              } else {
1909                  user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
1910                  $this->padding = true;
1911              }
1912          }
1913  
1914          $pad = $this->block_size - ($length % $this->block_size);
1915  
1916          return str_pad($text, $length + $pad, chr($pad));
1917      }
1918  
1919      /**
1920       * Unpads a string.
1921       *
1922       * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1923       * and false will be returned.
1924       *
1925       * @see self::_pad()
1926       * @param string $text
1927       * @access private
1928       * @return string
1929       */
1930      function _unpad($text)
1931      {
1932          if (!$this->padding) {
1933              return $text;
1934          }
1935  
1936          $length = ord($text[strlen($text) - 1]);
1937  
1938          if (!$length || $length > $this->block_size) {
1939              return false;
1940          }
1941  
1942          return substr($text, 0, -$length);
1943      }
1944  
1945      /**
1946       * Clears internal buffers
1947       *
1948       * Clearing/resetting the internal buffers is done everytime
1949       * after disableContinuousBuffer() or on cipher $engine (re)init
1950       * ie after setKey() or setIV()
1951       *
1952       * @access public
1953       * @internal Could, but not must, extend by the child Crypt_* class
1954       */
1955      function _clearBuffers()
1956      {
1957          $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
1958  
1959          // mcrypt's handling of invalid's $iv:
1960          // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
1961          $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
1962  
1963          if (!$this->skip_key_adjustment) {
1964              $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
1965          }
1966      }
1967  
1968      /**
1969       * String Shift
1970       *
1971       * Inspired by array_shift
1972       *
1973       * @param string $string
1974       * @param int $index
1975       * @access private
1976       * @return string
1977       */
1978      function _string_shift(&$string, $index = 1)
1979      {
1980          $substr = substr($string, 0, $index);
1981          $string = substr($string, $index);
1982          return $substr;
1983      }
1984  
1985      /**
1986       * String Pop
1987       *
1988       * Inspired by array_pop
1989       *
1990       * @param string $string
1991       * @param int $index
1992       * @access private
1993       * @return string
1994       */
1995      function _string_pop(&$string, $index = 1)
1996      {
1997          $substr = substr($string, -$index);
1998          $string = substr($string, 0, -$index);
1999          return $substr;
2000      }
2001  
2002      /**
2003       * Increment the current string
2004       *
2005       * @see self::decrypt()
2006       * @see self::encrypt()
2007       * @param string $var
2008       * @access private
2009       */
2010      function _increment_str(&$var)
2011      {
2012          for ($i = 4; $i <= strlen($var); $i+= 4) {
2013              $temp = substr($var, -$i, 4);
2014              switch ($temp) {
2015                  case "\xFF\xFF\xFF\xFF":
2016                      $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
2017                      break;
2018                  case "\x7F\xFF\xFF\xFF":
2019                      $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
2020                      return;
2021                  default:
2022                      $temp = unpack('Nnum', $temp);
2023                      $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
2024                      return;
2025              }
2026          }
2027  
2028          $remainder = strlen($var) % 4;
2029  
2030          if ($remainder == 0) {
2031              return;
2032          }
2033  
2034          $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
2035          $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
2036          $var = substr_replace($var, $temp, 0, $remainder);
2037      }
2038  
2039      /**
2040       * Setup the performance-optimized function for de/encrypt()
2041       *
2042       * Stores the created (or existing) callback function-name
2043       * in $this->inline_crypt
2044       *
2045       * Internally for phpseclib developers:
2046       *
2047       *     _setupInlineCrypt() would be called only if:
2048       *
2049       *     - $engine == self::ENGINE_INTERNAL and
2050       *
2051       *     - $use_inline_crypt === true
2052       *
2053       *     - each time on _setup(), after(!) _setupKey()
2054       *
2055       *
2056       *     This ensures that _setupInlineCrypt() has always a
2057       *     full ready2go initializated internal cipher $engine state
2058       *     where, for example, the keys allready expanded,
2059       *     keys/block_size calculated and such.
2060       *
2061       *     It is, each time if called, the responsibility of _setupInlineCrypt():
2062       *
2063       *     - to set $this->inline_crypt to a valid and fully working callback function
2064       *       as a (faster) replacement for encrypt() / decrypt()
2065       *
2066       *     - NOT to create unlimited callback functions (for memory reasons!)
2067       *       no matter how often _setupInlineCrypt() would be called. At some
2068       *       point of amount they must be generic re-useable.
2069       *
2070       *     - the code of _setupInlineCrypt() it self,
2071       *       and the generated callback code,
2072       *       must be, in following order:
2073       *       - 100% safe
2074       *       - 100% compatible to encrypt()/decrypt()
2075       *       - using only php5+ features/lang-constructs/php-extensions if
2076       *         compatibility (down to php4) or fallback is provided
2077       *       - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
2078       *       - >= 10% faster than encrypt()/decrypt() [which is, by the way,
2079       *         the reason for the existence of _setupInlineCrypt() :-)]
2080       *       - memory-nice
2081       *       - short (as good as possible)
2082       *
2083       * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
2084       *       - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib\Crypt\* class.
2085       *       - The following variable names are reserved:
2086       *         - $_*  (all variable names prefixed with an underscore)
2087       *         - $self (object reference to it self. Do not use $this, but $self instead)
2088       *         - $in (the content of $in has to en/decrypt by the generated code)
2089       *       - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
2090       *
2091       *
2092       * @see self::_setup()
2093       * @see self::_createInlineCryptFunction()
2094       * @see self::encrypt()
2095       * @see self::decrypt()
2096       * @access private
2097       * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
2098       */
2099      function _setupInlineCrypt()
2100      {
2101          // If, for any reason, an extending \phpseclib\Crypt\Base() \phpseclib\Crypt\* class
2102          // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
2103          // ie in the class var declaration of $use_inline_crypt in general for the \phpseclib\Crypt\* class,
2104          // in the constructor at object instance-time
2105          // or, if it's runtime-specific, at runtime
2106  
2107          $this->use_inline_crypt = false;
2108      }
2109  
2110      /**
2111       * Creates the performance-optimized function for en/decrypt()
2112       *
2113       * Internally for phpseclib developers:
2114       *
2115       *    _createInlineCryptFunction():
2116       *
2117       *    - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
2118       *      with the current [$this->]mode of operation code
2119       *
2120       *    - create the $inline function, which called by encrypt() / decrypt()
2121       *      as its replacement to speed up the en/decryption operations.
2122       *
2123       *    - return the name of the created $inline callback function
2124       *
2125       *    - used to speed up en/decryption
2126       *
2127       *
2128       *
2129       *    The main reason why can speed up things [up to 50%] this way are:
2130       *
2131       *    - using variables more effective then regular.
2132       *      (ie no use of expensive arrays but integers $k_0, $k_1 ...
2133       *      or even, for example, the pure $key[] values hardcoded)
2134       *
2135       *    - avoiding 1000's of function calls of ie _encryptBlock()
2136       *      but inlining the crypt operations.
2137       *      in the mode of operation for() loop.
2138       *
2139       *    - full loop unroll the (sometimes key-dependent) rounds
2140       *      avoiding this way ++$i counters and runtime-if's etc...
2141       *
2142       *    The basic code architectur of the generated $inline en/decrypt()
2143       *    lambda function, in pseudo php, is:
2144       *
2145       *    <code>
2146       *    +----------------------------------------------------------------------------------------------+
2147       *    | callback $inline = create_function:                                                          |
2148       *    | lambda_function_0001_crypt_ECB($action, $text)                                               |
2149       *    | {                                                                                            |
2150       *    |     INSERT PHP CODE OF:                                                                      |
2151       *    |     $cipher_code['init_crypt'];                  // general init code.                       |
2152       *    |                                                  // ie: $sbox'es declarations used for       |
2153       *    |                                                  //     encrypt and decrypt'ing.             |
2154       *    |                                                                                              |
2155       *    |     switch ($action) {                                                                       |
2156       *    |         case 'encrypt':                                                                      |
2157       *    |             INSERT PHP CODE OF:                                                              |
2158       *    |             $cipher_code['init_encrypt'];       // encrypt sepcific init code.               |
2159       *    |                                                    ie: specified $key or $box                |
2160       *    |                                                        declarations for encrypt'ing.         |
2161       *    |                                                                                              |
2162       *    |             foreach ($ciphertext) {                                                          |
2163       *    |                 $in = $block_size of $ciphertext;                                            |
2164       *    |                                                                                              |
2165       *    |                 INSERT PHP CODE OF:                                                          |
2166       *    |                 $cipher_code['encrypt_block'];  // encrypt's (string) $in, which is always:  |
2167       *    |                                                 // strlen($in) == $this->block_size          |
2168       *    |                                                 // here comes the cipher algorithm in action |
2169       *    |                                                 // for encryption.                           |
2170       *    |                                                 // $cipher_code['encrypt_block'] has to      |
2171       *    |                                                 // encrypt the content of the $in variable   |
2172       *    |                                                                                              |
2173       *    |                 $plaintext .= $in;                                                           |
2174       *    |             }                                                                                |
2175       *    |             return $plaintext;                                                               |
2176       *    |                                                                                              |
2177       *    |         case 'decrypt':                                                                      |
2178       *    |             INSERT PHP CODE OF:                                                              |
2179       *    |             $cipher_code['init_decrypt'];       // decrypt sepcific init code                |
2180       *    |                                                    ie: specified $key or $box                |
2181       *    |                                                        declarations for decrypt'ing.         |
2182       *    |             foreach ($plaintext) {                                                           |
2183       *    |                 $in = $block_size of $plaintext;                                             |
2184       *    |                                                                                              |
2185       *    |                 INSERT PHP CODE OF:                                                          |
2186       *    |                 $cipher_code['decrypt_block'];  // decrypt's (string) $in, which is always   |
2187       *    |                                                 // strlen($in) == $this->block_size          |
2188       *    |                                                 // here comes the cipher algorithm in action |
2189       *    |                                                 // for decryption.                           |
2190       *    |                                                 // $cipher_code['decrypt_block'] has to      |
2191       *    |                                                 // decrypt the content of the $in variable   |
2192       *    |                 $ciphertext .= $in;                                                          |
2193       *    |             }                                                                                |
2194       *    |             return $ciphertext;                                                              |
2195       *    |     }                                                                                        |
2196       *    | }                                                                                            |
2197       *    +----------------------------------------------------------------------------------------------+
2198       *    </code>
2199       *
2200       *    See also the \phpseclib\Crypt\*::_setupInlineCrypt()'s for
2201       *    productive inline $cipher_code's how they works.
2202       *
2203       *    Structure of:
2204       *    <code>
2205       *    $cipher_code = array(
2206       *        'init_crypt'    => (string) '', // optional
2207       *        'init_encrypt'  => (string) '', // optional
2208       *        'init_decrypt'  => (string) '', // optional
2209       *        'encrypt_block' => (string) '', // required
2210       *        'decrypt_block' => (string) ''  // required
2211       *    );
2212       *    </code>
2213       *
2214       * @see self::_setupInlineCrypt()
2215       * @see self::encrypt()
2216       * @see self::decrypt()
2217       * @param array $cipher_code
2218       * @access private
2219       * @return string (the name of the created callback function)
2220       */
2221      function _createInlineCryptFunction($cipher_code)
2222      {
2223          $block_size = $this->block_size;
2224  
2225          // optional
2226          $init_crypt    = isset($cipher_code['init_crypt'])    ? $cipher_code['init_crypt']    : '';
2227          $init_encrypt  = isset($cipher_code['init_encrypt'])  ? $cipher_code['init_encrypt']  : '';
2228          $init_decrypt  = isset($cipher_code['init_decrypt'])  ? $cipher_code['init_decrypt']  : '';
2229          // required
2230          $encrypt_block = $cipher_code['encrypt_block'];
2231          $decrypt_block = $cipher_code['decrypt_block'];
2232  
2233          // Generating mode of operation inline code,
2234          // merged with the $cipher_code algorithm
2235          // for encrypt- and decryption.
2236          switch ($this->mode) {
2237              case self::MODE_ECB:
2238                  $encrypt = $init_encrypt . '
2239                      $_ciphertext = "";
2240                      $_plaintext_len = strlen($_text);
2241  
2242                      for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2243                          $in = substr($_text, $_i, '.$block_size.');
2244                          '.$encrypt_block.'
2245                          $_ciphertext.= $in;
2246                      }
2247  
2248                      return $_ciphertext;
2249                      ';
2250  
2251                  $decrypt = $init_decrypt . '
2252                      $_plaintext = "";
2253                      $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2254                      $_ciphertext_len = strlen($_text);
2255  
2256                      for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2257                          $in = substr($_text, $_i, '.$block_size.');
2258                          '.$decrypt_block.'
2259                          $_plaintext.= $in;
2260                      }
2261  
2262                      return $self->_unpad($_plaintext);
2263                      ';
2264                  break;
2265              case self::MODE_CTR:
2266                  $encrypt = $init_encrypt . '
2267                      $_ciphertext = "";
2268                      $_plaintext_len = strlen($_text);
2269                      $_xor = $self->encryptIV;
2270                      $_buffer = &$self->enbuffer;
2271                      if (strlen($_buffer["ciphertext"])) {
2272                          for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2273                              $_block = substr($_text, $_i, '.$block_size.');
2274                              if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2275                                  $in = $_xor;
2276                                  '.$encrypt_block.'
2277                                  $self->_increment_str($_xor);
2278                                  $_buffer["ciphertext"].= $in;
2279                              }
2280                              $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2281                              $_ciphertext.= $_block ^ $_key;
2282                          }
2283                      } else {
2284                          for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2285                              $_block = substr($_text, $_i, '.$block_size.');
2286                              $in = $_xor;
2287                              '.$encrypt_block.'
2288                              $self->_increment_str($_xor);
2289                              $_key = $in;
2290                              $_ciphertext.= $_block ^ $_key;
2291                          }
2292                      }
2293                      if ($self->continuousBuffer) {
2294                          $self->encryptIV = $_xor;
2295                          if ($_start = $_plaintext_len % '.$block_size.') {
2296                              $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2297                          }
2298                      }
2299  
2300                      return $_ciphertext;
2301                  ';
2302  
2303                  $decrypt = $init_encrypt . '
2304                      $_plaintext = "";
2305                      $_ciphertext_len = strlen($_text);
2306                      $_xor = $self->decryptIV;
2307                      $_buffer = &$self->debuffer;
2308  
2309                      if (strlen($_buffer["ciphertext"])) {
2310                          for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2311                              $_block = substr($_text, $_i, '.$block_size.');
2312                              if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2313                                  $in = $_xor;
2314                                  '.$encrypt_block.'
2315                                  $self->_increment_str($_xor);
2316                                  $_buffer["ciphertext"].= $in;
2317                              }
2318                              $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2319                              $_plaintext.= $_block ^ $_key;
2320                          }
2321                      } else {
2322                          for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2323                              $_block = substr($_text, $_i, '.$block_size.');
2324                              $in = $_xor;
2325                              '.$encrypt_block.'
2326                              $self->_increment_str($_xor);
2327                              $_key = $in;
2328                              $_plaintext.= $_block ^ $_key;
2329                          }
2330                      }
2331                      if ($self->continuousBuffer) {
2332                          $self->decryptIV = $_xor;
2333                          if ($_start = $_ciphertext_len % '.$block_size.') {
2334                              $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2335                          }
2336                      }
2337  
2338                      return $_plaintext;
2339                      ';
2340                  break;
2341              case self::MODE_CFB:
2342                  $encrypt = $init_encrypt . '
2343                      $_ciphertext = "";
2344                      $_buffer = &$self->enbuffer;
2345  
2346                      if ($self->continuousBuffer) {
2347                          $_iv = &$self->encryptIV;
2348                          $_pos = &$_buffer["pos"];
2349                      } else {
2350                          $_iv = $self->encryptIV;
2351                          $_pos = 0;
2352                      }
2353                      $_len = strlen($_text);
2354                      $_i = 0;
2355                      if ($_pos) {
2356                          $_orig_pos = $_pos;
2357                          $_max = '.$block_size.' - $_pos;
2358                          if ($_len >= $_max) {
2359                              $_i = $_max;
2360                              $_len-= $_max;
2361                              $_pos = 0;
2362                          } else {
2363                              $_i = $_len;
2364                              $_pos+= $_len;
2365                              $_len = 0;
2366                          }
2367                          $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
2368                          $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
2369                      }
2370                      while ($_len >= '.$block_size.') {
2371                          $in = $_iv;
2372                          '.$encrypt_block.';
2373                          $_iv = $in ^ substr($_text, $_i, '.$block_size.');
2374                          $_ciphertext.= $_iv;
2375                          $_len-= '.$block_size.';
2376                          $_i+= '.$block_size.';
2377                      }
2378                      if ($_len) {
2379                          $in = $_iv;
2380                          '.$encrypt_block.'
2381                          $_iv = $in;
2382                          $_block = $_iv ^ substr($_text, $_i);
2383                          $_iv = substr_replace($_iv, $_block, 0, $_len);
2384                          $_ciphertext.= $_block;
2385                          $_pos = $_len;
2386                      }
2387                      return $_ciphertext;
2388                  ';
2389  
2390                  $decrypt = $init_encrypt . '
2391                      $_plaintext = "";
2392                      $_buffer = &$self->debuffer;
2393  
2394                      if ($self->continuousBuffer) {
2395                          $_iv = &$self->decryptIV;
2396                          $_pos = &$_buffer["pos"];
2397                      } else {
2398                          $_iv = $self->decryptIV;
2399                          $_pos = 0;
2400                      }
2401                      $_len = strlen($_text);
2402                      $_i = 0;
2403                      if ($_pos) {
2404                          $_orig_pos = $_pos;
2405                          $_max = '.$block_size.' - $_pos;
2406                          if ($_len >= $_max) {
2407                              $_i = $_max;
2408                              $_len-= $_max;
2409                              $_pos = 0;
2410                          } else {
2411                              $_i = $_len;
2412                              $_pos+= $_len;
2413                              $_len = 0;
2414                          }
2415                          $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
2416                          $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
2417                      }
2418                      while ($_len >= '.$block_size.') {
2419                          $in = $_iv;
2420                          '.$encrypt_block.'
2421                          $_iv = $in;
2422                          $cb = substr($_text, $_i, '.$block_size.');
2423                          $_plaintext.= $_iv ^ $cb;
2424                          $_iv = $cb;
2425                          $_len-= '.$block_size.';
2426                          $_i+= '.$block_size.';
2427                      }
2428                      if ($_len) {
2429                          $in = $_iv;
2430                          '.$encrypt_block.'
2431                          $_iv = $in;
2432                          $_plaintext.= $_iv ^ substr($_text, $_i);
2433                          $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
2434                          $_pos = $_len;
2435                      }
2436  
2437                      return $_plaintext;
2438                      ';
2439                  break;
2440              case self::MODE_CFB8:
2441                  $encrypt = $init_encrypt . '
2442                      $_ciphertext = "";
2443                      $_len = strlen($_text);
2444                      $_iv = $self->encryptIV;
2445  
2446                      for ($_i = 0; $_i < $_len; ++$_i) {
2447                          $in = $_iv;
2448                          '.$encrypt_block.'
2449                          $_ciphertext .= ($_c = $_text[$_i] ^ $in);
2450                          $_iv = substr($_iv, 1) . $_c;
2451                      }
2452  
2453                      if ($self->continuousBuffer) {
2454                          if ($_len >= '.$block_size.') {
2455                              $self->encryptIV = substr($_ciphertext, -'.$block_size.');
2456                          } else {
2457                              $self->encryptIV = substr($self->encryptIV, $_len - '.$block_size.') . substr($_ciphertext, -$_len);
2458                          }
2459                      }
2460  
2461                      return $_ciphertext;
2462                      ';
2463                  $decrypt = $init_encrypt . '
2464                      $_plaintext = "";
2465                      $_len = strlen($_text);
2466                      $_iv = $self->decryptIV;
2467  
2468                      for ($_i = 0; $_i < $_len; ++$_i) {
2469                          $in = $_iv;
2470                          '.$encrypt_block.'
2471                          $_plaintext .= $_text[$_i] ^ $in;
2472                          $_iv = substr($_iv, 1) . $_text[$_i];
2473                      }
2474  
2475                      if ($self->continuousBuffer) {
2476                          if ($_len >= '.$block_size.') {
2477                              $self->decryptIV = substr($_text, -'.$block_size.');
2478                          } else {
2479                              $self->decryptIV = substr($self->decryptIV, $_len - '.$block_size.') . substr($_text, -$_len);
2480                          }
2481                      }
2482  
2483                      return $_plaintext;
2484                      ';
2485                  break;
2486              case self::MODE_OFB:
2487                  $encrypt = $init_encrypt . '
2488                      $_ciphertext = "";
2489                      $_plaintext_len = strlen($_text);
2490                      $_xor = $self->encryptIV;
2491                      $_buffer = &$self->enbuffer;
2492  
2493                      if (strlen($_buffer["xor"])) {
2494                          for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2495                              $_block = substr($_text, $_i, '.$block_size.');
2496                              if (strlen($_block) > strlen($_buffer["xor"])) {
2497                                  $in = $_xor;
2498                                  '.$encrypt_block.'
2499                                  $_xor = $in;
2500                                  $_buffer["xor"].= $_xor;
2501                              }
2502                              $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2503                              $_ciphertext.= $_block ^ $_key;
2504                          }
2505                      } else {
2506                          for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2507                              $in = $_xor;
2508                              '.$encrypt_block.'
2509                              $_xor = $in;
2510                              $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2511                          }
2512                          $_key = $_xor;
2513                      }
2514                      if ($self->continuousBuffer) {
2515                          $self->encryptIV = $_xor;
2516                          if ($_start = $_plaintext_len % '.$block_size.') {
2517                               $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2518                          }
2519                      }
2520                      return $_ciphertext;
2521                      ';
2522  
2523                  $decrypt = $init_encrypt . '
2524                      $_plaintext = "";
2525                      $_ciphertext_len = strlen($_text);
2526                      $_xor = $self->decryptIV;
2527                      $_buffer = &$self->debuffer;
2528  
2529                      if (strlen($_buffer["xor"])) {
2530                          for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2531                              $_block = substr($_text, $_i, '.$block_size.');
2532                              if (strlen($_block) > strlen($_buffer["xor"])) {
2533                                  $in = $_xor;
2534                                  '.$encrypt_block.'
2535                                  $_xor = $in;
2536                                  $_buffer["xor"].= $_xor;
2537                              }
2538                              $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2539                              $_plaintext.= $_block ^ $_key;
2540                          }
2541                      } else {
2542                          for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2543                              $in = $_xor;
2544                              '.$encrypt_block.'
2545                              $_xor = $in;
2546                              $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2547                          }
2548                          $_key = $_xor;
2549                      }
2550                      if ($self->continuousBuffer) {
2551                          $self->decryptIV = $_xor;
2552                          if ($_start = $_ciphertext_len % '.$block_size.') {
2553                               $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2554                          }
2555                      }
2556                      return $_plaintext;
2557                      ';
2558                  break;
2559              case self::MODE_STREAM:
2560                  $encrypt = $init_encrypt . '
2561                      $_ciphertext = "";
2562                      '.$encrypt_block.'
2563                      return $_ciphertext;
2564                      ';
2565                  $decrypt = $init_decrypt . '
2566                      $_plaintext = "";
2567                      '.$decrypt_block.'
2568                      return $_plaintext;
2569                      ';
2570                  break;
2571              // case self::MODE_CBC:
2572              default:
2573                  $encrypt = $init_encrypt . '
2574                      $_ciphertext = "";
2575                      $_plaintext_len = strlen($_text);
2576  
2577                      $in = $self->encryptIV;
2578  
2579                      for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2580                          $in = substr($_text, $_i, '.$block_size.') ^ $in;
2581                          '.$encrypt_block.'
2582                          $_ciphertext.= $in;
2583                      }
2584  
2585                      if ($self->continuousBuffer) {
2586                          $self->encryptIV = $in;
2587                      }
2588  
2589                      return $_ciphertext;
2590                      ';
2591  
2592                  $decrypt = $init_decrypt . '
2593                      $_plaintext = "";
2594                      $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2595                      $_ciphertext_len = strlen($_text);
2596  
2597                      $_iv = $self->decryptIV;
2598  
2599                      for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2600                          $in = $_block = substr($_text, $_i, '.$block_size.');
2601                          '.$decrypt_block.'
2602                          $_plaintext.= $in ^ $_iv;
2603                          $_iv = $_block;
2604                      }
2605  
2606                      if ($self->continuousBuffer) {
2607                          $self->decryptIV = $_iv;
2608                      }
2609  
2610                      return $self->_unpad($_plaintext);
2611                      ';
2612                  break;
2613          }
2614  
2615          // Create the $inline function and return its name as string. Ready to run!
2616          eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
2617          return $func;
2618      }
2619  
2620      /**
2621       * Holds the lambda_functions table (classwide)
2622       *
2623       * Each name of the lambda function, created from
2624       * _setupInlineCrypt() && _createInlineCryptFunction()
2625       * is stored, classwide (!), here for reusing.
2626       *
2627       * The string-based index of $function is a classwide
2628       * unique value representing, at least, the $mode of
2629       * operation (or more... depends of the optimizing level)
2630       * for which $mode the lambda function was created.
2631       *
2632       * @access private
2633       * @return array &$functions
2634       */
2635      function &_getLambdaFunctions()
2636      {
2637          static $functions = array();
2638          return $functions;
2639      }
2640  
2641      /**
2642       * Generates a digest from $bytes
2643       *
2644       * @see self::_setupInlineCrypt()
2645       * @access private
2646       * @param string $bytes
2647       * @return string
2648       */
2649      function _hashInlineCryptFunction($bytes)
2650      {
2651          if (!isset(self::$WHIRLPOOL_AVAILABLE)) {
2652              self::$WHIRLPOOL_AVAILABLE = extension_loaded('hash') && in_array('whirlpool', hash_algos());
2653          }
2654  
2655          $result = '';
2656          $hash = $bytes;
2657  
2658          switch (true) {
2659              case self::$WHIRLPOOL_AVAILABLE:
2660                  foreach (str_split($bytes, 64) as $t) {
2661                      $hash = hash('whirlpool', $hash, true);
2662                      $result .= $t ^ $hash;
2663                  }
2664                  return $result . hash('whirlpool', $hash, true);
2665              default:
2666                  $len = strlen($bytes);
2667                  for ($i = 0; $i < $len; $i+=20) {
2668                      $t = substr($bytes, $i, 20);
2669                      $hash = pack('H*', sha1($hash));
2670                      $result .= $t ^ $hash;
2671                  }
2672                  return $result . pack('H*', sha1($hash));
2673          }
2674      }
2675  
2676      /**
2677       * Convert float to int
2678       *
2679       * On ARM CPUs converting floats to ints doesn't always work
2680       *
2681       * @access private
2682       * @param string $x
2683       * @return int
2684       */
2685      function safe_intval($x)
2686      {
2687          switch (true) {
2688              case is_int($x):
2689              // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
2690              case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
2691                  return $x;
2692          }
2693          return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
2694              ((fmod(floor($x / 0x80000000), 2) & 1) << 31);
2695      }
2696  
2697      /**
2698       * eval()'able string for in-line float to int
2699       *
2700       * @access private
2701       * @return string
2702       */
2703      function safe_intval_inline()
2704      {
2705          switch (true) {
2706              case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
2707              case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
2708                  return '%s';
2709                  break;
2710              default:
2711                  $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
2712                  return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
2713          }
2714      }
2715  
2716      /**
2717       * Dummy error handler to suppress mcrypt errors
2718       *
2719       * @access private
2720       */
2721      function do_nothing()
2722      {
2723      }
2724  }