[ 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 = 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body