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