[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4 /** 5 * Base Class for all Crypt_* cipher classes 6 * 7 * PHP versions 4 and 5 8 * 9 * Internally for phpseclib developers: 10 * If you plan to add a new cipher class, please note following rules: 11 * 12 * - The new Crypt_* cipher class should extend Crypt_Base 13 * 14 * - Following methods are then required to be overridden/overloaded: 15 * 16 * - _encryptBlock() 17 * 18 * - _decryptBlock() 19 * 20 * - _setupKey() 21 * 22 * - All other methods are optional to be overridden/overloaded 23 * 24 * - Look at the source code of the current ciphers how they extend Crypt_Base 25 * and take one of them as a start up for the new cipher class. 26 * 27 * - Please read all the other comments/notes/hints here also for each class var/method 28 * 29 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy 30 * of this software and associated documentation files (the "Software"), to deal 31 * in the Software without restriction, including without limitation the rights 32 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 * copies of the Software, and to permit persons to whom the Software is 34 * furnished to do so, subject to the following conditions: 35 * 36 * The above copyright notice and this permission notice shall be included in 37 * all copies or substantial portions of the Software. 38 * 39 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45 * THE SOFTWARE. 46 * 47 * @category Crypt 48 * @package Crypt_Base 49 * @author Jim Wigginton <terrafrost@php.net> 50 * @author Hans-Juergen Petrich <petrich@tronic-media.com> 51 * @copyright MMVII Jim Wigginton 52 * @license http://www.opensource.org/licenses/mit-license.html MIT License 53 * @version 1.0.1 54 * @link http://phpseclib.sourceforge.net 55 */ 56 57 /**#@+ 58 * @access public 59 * @see Crypt_Base::encrypt() 60 * @see Crypt_Base::decrypt() 61 */ 62 /** 63 * Encrypt / decrypt using the Counter mode. 64 * 65 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. 66 * 67 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 68 */ 69 define('CRYPT_MODE_CTR', -1); 70 /** 71 * Encrypt / decrypt using the Electronic Code Book mode. 72 * 73 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 74 */ 75 define('CRYPT_MODE_ECB', 1); 76 /** 77 * Encrypt / decrypt using the Code Book Chaining mode. 78 * 79 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 80 */ 81 define('CRYPT_MODE_CBC', 2); 82 /** 83 * Encrypt / decrypt using the Cipher Feedback mode. 84 * 85 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 86 */ 87 define('CRYPT_MODE_CFB', 3); 88 /** 89 * Encrypt / decrypt using the Output Feedback mode. 90 * 91 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 92 */ 93 define('CRYPT_MODE_OFB', 4); 94 /** 95 * Encrypt / decrypt using streaming mode. 96 * 97 */ 98 define('CRYPT_MODE_STREAM', 5); 99 /**#@-*/ 100 101 /**#@+ 102 * @access private 103 * @see Crypt_Base::Crypt_Base() 104 */ 105 /** 106 * Base value for the internal implementation $engine switch 107 */ 108 define('CRYPT_MODE_INTERNAL', 1); 109 /** 110 * Base value for the mcrypt implementation $engine switch 111 */ 112 define('CRYPT_MODE_MCRYPT', 2); 113 /**#@-*/ 114 115 /** 116 * Base Class for all Crypt_* cipher classes 117 * 118 * @author Jim Wigginton <terrafrost@php.net> 119 * @author Hans-Juergen Petrich <petrich@tronic-media.com> 120 * @version 1.0.0 121 * @access public 122 * @package Crypt_Base 123 */ 124 class Crypt_Base { 125 /** 126 * The Encryption Mode 127 * 128 * @see Crypt_Base::Crypt_Base() 129 * @var Integer 130 * @access private 131 */ 132 var $mode; 133 134 /** 135 * The Block Length of the block cipher 136 * 137 * @var Integer 138 * @access private 139 */ 140 var $block_size = 16; 141 142 /** 143 * The Key 144 * 145 * @see Crypt_Base::setKey() 146 * @var String 147 * @access private 148 */ 149 var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 150 151 /** 152 * The Initialization Vector 153 * 154 * @see Crypt_Base::setIV() 155 * @var String 156 * @access private 157 */ 158 var $iv; 159 160 /** 161 * A "sliding" Initialization Vector 162 * 163 * @see Crypt_Base::enableContinuousBuffer() 164 * @see Crypt_Base::_clearBuffers() 165 * @var String 166 * @access private 167 */ 168 var $encryptIV; 169 170 /** 171 * A "sliding" Initialization Vector 172 * 173 * @see Crypt_Base::enableContinuousBuffer() 174 * @see Crypt_Base::_clearBuffers() 175 * @var String 176 * @access private 177 */ 178 var $decryptIV; 179 180 /** 181 * Continuous Buffer status 182 * 183 * @see Crypt_Base::enableContinuousBuffer() 184 * @var Boolean 185 * @access private 186 */ 187 var $continuousBuffer = false; 188 189 /** 190 * Encryption buffer for CTR, OFB and CFB modes 191 * 192 * @see Crypt_Base::encrypt() 193 * @see Crypt_Base::_clearBuffers() 194 * @var Array 195 * @access private 196 */ 197 var $enbuffer; 198 199 /** 200 * Decryption buffer for CTR, OFB and CFB modes 201 * 202 * @see Crypt_Base::decrypt() 203 * @see Crypt_Base::_clearBuffers() 204 * @var Array 205 * @access private 206 */ 207 var $debuffer; 208 209 /** 210 * mcrypt resource for encryption 211 * 212 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. 213 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. 214 * 215 * @see Crypt_Base::encrypt() 216 * @var Resource 217 * @access private 218 */ 219 var $enmcrypt; 220 221 /** 222 * mcrypt resource for decryption 223 * 224 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. 225 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. 226 * 227 * @see Crypt_Base::decrypt() 228 * @var Resource 229 * @access private 230 */ 231 var $demcrypt; 232 233 /** 234 * Does the enmcrypt resource need to be (re)initialized? 235 * 236 * @see Crypt_Twofish::setKey() 237 * @see Crypt_Twofish::setIV() 238 * @var Boolean 239 * @access private 240 */ 241 var $enchanged = true; 242 243 /** 244 * Does the demcrypt resource need to be (re)initialized? 245 * 246 * @see Crypt_Twofish::setKey() 247 * @see Crypt_Twofish::setIV() 248 * @var Boolean 249 * @access private 250 */ 251 var $dechanged = true; 252 253 /** 254 * mcrypt resource for CFB mode 255 * 256 * mcrypt's CFB mode, in (and only in) buffered context, 257 * is broken, so phpseclib implements the CFB mode by it self, 258 * even when the mcrypt php extension is available. 259 * 260 * In order to do the CFB-mode work (fast) phpseclib 261 * use a separate ECB-mode mcrypt resource. 262 * 263 * @link http://phpseclib.sourceforge.net/cfb-demo.phps 264 * @see Crypt_Base::encrypt() 265 * @see Crypt_Base::decrypt() 266 * @see Crypt_Base::_setupMcrypt() 267 * @var Resource 268 * @access private 269 */ 270 var $ecb; 271 272 /** 273 * Optimizing value while CFB-encrypting 274 * 275 * Only relevant if $continuousBuffer enabled 276 * and $engine == CRYPT_MODE_MCRYPT 277 * 278 * It's faster to re-init $enmcrypt if 279 * $buffer bytes > $cfb_init_len than 280 * using the $ecb resource furthermore. 281 * 282 * This value depends of the choosen cipher 283 * and the time it would be needed for it's 284 * initialization [by mcrypt_generic_init()] 285 * which, typically, depends on the complexity 286 * on its internaly Key-expanding algorithm. 287 * 288 * @see Crypt_Base::encrypt() 289 * @var Integer 290 * @access private 291 */ 292 var $cfb_init_len = 600; 293 294 /** 295 * Does internal cipher state need to be (re)initialized? 296 * 297 * @see setKey() 298 * @see setIV() 299 * @see disableContinuousBuffer() 300 * @var Boolean 301 * @access private 302 */ 303 var $changed = true; 304 305 /** 306 * Padding status 307 * 308 * @see Crypt_Base::enablePadding() 309 * @var Boolean 310 * @access private 311 */ 312 var $padding = true; 313 314 /** 315 * Is the mode one that is paddable? 316 * 317 * @see Crypt_Base::Crypt_Base() 318 * @var Boolean 319 * @access private 320 */ 321 var $paddable = false; 322 323 /** 324 * Holds which crypt engine internaly should be use, 325 * which will be determined automatically on __construct() 326 * 327 * Currently available $engines are: 328 * - CRYPT_MODE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required) 329 * - CRYPT_MODE_INTERNAL (slower, pure php-engine, no php-extension required) 330 * 331 * In the pipeline... maybe. But currently not available: 332 * - CRYPT_MODE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required) 333 * 334 * If possible, CRYPT_MODE_MCRYPT will be used for each cipher. 335 * Otherwise CRYPT_MODE_INTERNAL 336 * 337 * @see Crypt_Base::encrypt() 338 * @see Crypt_Base::decrypt() 339 * @var Integer 340 * @access private 341 */ 342 var $engine; 343 344 /** 345 * The mcrypt specific name of the cipher 346 * 347 * Only used if $engine == CRYPT_MODE_MCRYPT 348 * 349 * @link http://php.net/mcrypt_module_open 350 * @link http://php.net/mcrypt_list_algorithms 351 * @see Crypt_Base::_setupMcrypt() 352 * @var String 353 * @access private 354 */ 355 var $cipher_name_mcrypt; 356 357 /** 358 * The default password key_size used by setPassword() 359 * 360 * @see Crypt_Base::setPassword() 361 * @var Integer 362 * @access private 363 */ 364 var $password_key_size = 32; 365 366 /** 367 * The default salt used by setPassword() 368 * 369 * @see Crypt_Base::setPassword() 370 * @var String 371 * @access private 372 */ 373 var $password_default_salt = 'phpseclib/salt'; 374 375 /** 376 * The namespace used by the cipher for its constants. 377 * 378 * ie: AES.php is using CRYPT_AES_MODE_* for its constants 379 * so $const_namespace is AES 380 * 381 * DES.php is using CRYPT_DES_MODE_* for its constants 382 * so $const_namespace is DES... and so on 383 * 384 * All CRYPT_<$const_namespace>_MODE_* are aliases of 385 * the generic CRYPT_MODE_* constants, so both could be used 386 * for each cipher. 387 * 388 * Example: 389 * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode 390 * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical 391 * 392 * @see Crypt_Base::Crypt_Base() 393 * @var String 394 * @access private 395 */ 396 var $const_namespace; 397 398 /** 399 * The name of the performance-optimized callback function 400 * 401 * Used by encrypt() / decrypt() 402 * only if $engine == CRYPT_MODE_INTERNAL 403 * 404 * @see Crypt_Base::encrypt() 405 * @see Crypt_Base::decrypt() 406 * @see Crypt_Base::_setupInlineCrypt() 407 * @see Crypt_Base::$use_inline_crypt 408 * @var Callback 409 * @access private 410 */ 411 var $inline_crypt; 412 413 /** 414 * Holds whether performance-optimized $inline_crypt() can/should be used. 415 * 416 * @see Crypt_Base::encrypt() 417 * @see Crypt_Base::decrypt() 418 * @see Crypt_Base::inline_crypt 419 * @var mixed 420 * @access private 421 */ 422 var $use_inline_crypt; 423 424 /** 425 * Default Constructor. 426 * 427 * Determines whether or not the mcrypt extension should be used. 428 * 429 * $mode could be: 430 * 431 * - CRYPT_MODE_ECB 432 * 433 * - CRYPT_MODE_CBC 434 * 435 * - CRYPT_MODE_CTR 436 * 437 * - CRYPT_MODE_CFB 438 * 439 * - CRYPT_MODE_OFB 440 * 441 * (or the alias constants of the choosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...) 442 * 443 * If not explictly set, CRYPT_MODE_CBC will be used. 444 * 445 * @param optional Integer $mode 446 * @access public 447 */ 448 function __construct($mode = CRYPT_MODE_CBC) 449 { 450 $const_crypt_mode = 'CRYPT_' . $this->const_namespace . '_MODE'; 451 452 // Determining the availibility of mcrypt support for the cipher 453 if (!defined($const_crypt_mode)) { 454 switch (true) { 455 case extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()): 456 define($const_crypt_mode, CRYPT_MODE_MCRYPT); 457 break; 458 default: 459 define($const_crypt_mode, CRYPT_MODE_INTERNAL); 460 } 461 } 462 463 // Determining which internal $engine should be used. 464 // The fastes possible first. 465 switch (true) { 466 case empty($this->cipher_name_mcrypt): // The cipher module has no mcrypt-engine support at all so we force CRYPT_MODE_INTERNAL 467 $this->engine = CRYPT_MODE_INTERNAL; 468 break; 469 case constant($const_crypt_mode) == CRYPT_MODE_MCRYPT: 470 $this->engine = CRYPT_MODE_MCRYPT; 471 break; 472 default: 473 $this->engine = CRYPT_MODE_INTERNAL; 474 } 475 476 // $mode dependent settings 477 switch ($mode) { 478 case CRYPT_MODE_ECB: 479 $this->paddable = true; 480 $this->mode = $mode; 481 break; 482 case CRYPT_MODE_CTR: 483 case CRYPT_MODE_CFB: 484 case CRYPT_MODE_OFB: 485 case CRYPT_MODE_STREAM: 486 $this->mode = $mode; 487 break; 488 case CRYPT_MODE_CBC: 489 default: 490 $this->paddable = true; 491 $this->mode = CRYPT_MODE_CBC; 492 } 493 494 // Determining whether inline crypting can be used by the cipher 495 if ($this->use_inline_crypt !== false && function_exists('create_function')) { 496 $this->use_inline_crypt = true; 497 } 498 } 499 500 /** 501 * Sets the initialization vector. (optional) 502 * 503 * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explictly set, it'll be assumed 504 * to be all zero's. 505 * 506 * Note: Could, but not must, extend by the child Crypt_* class 507 * 508 * @access public 509 * @param String $iv 510 */ 511 function setIV($iv) 512 { 513 if ($this->mode == CRYPT_MODE_ECB) { 514 return; 515 } 516 517 $this->iv = $iv; 518 $this->changed = true; 519 } 520 521 /** 522 * Sets the key. 523 * 524 * The min/max length(s) of the key depends on the cipher which is used. 525 * If the key not fits the length(s) of the cipher it will paded with null bytes 526 * up to the closest valid key length. If the key is more than max length, 527 * we trim the excess bits. 528 * 529 * If the key is not explicitly set, it'll be assumed to be all null bytes. 530 * 531 * Note: Could, but not must, extend by the child Crypt_* class 532 * 533 * @access public 534 * @param String $key 535 */ 536 function setKey($key) 537 { 538 $this->key = $key; 539 $this->changed = true; 540 } 541 542 /** 543 * Sets the password. 544 * 545 * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: 546 * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}: 547 * $hash, $salt, $count, $dkLen 548 * 549 * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php 550 * 551 * Note: Could, but not must, extend by the child Crypt_* class 552 * 553 * @see Crypt/Hash.php 554 * @param String $password 555 * @param optional String $method 556 * @access public 557 */ 558 function setPassword($password, $method = 'pbkdf2') 559 { 560 $key = ''; 561 562 switch ($method) { 563 default: // 'pbkdf2' 564 $func_args = func_get_args(); 565 566 // Hash function 567 $hash = isset($func_args[2]) ? $func_args[2] : 'sha1'; 568 569 // WPA and WPA2 use the SSID as the salt 570 $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt; 571 572 // RFC2898#section-4.2 uses 1,000 iterations by default 573 // WPA and WPA2 use 4,096. 574 $count = isset($func_args[4]) ? $func_args[4] : 1000; 575 576 // Keylength 577 $dkLen = isset($func_args[5]) ? $func_args[5] : $this->password_key_size; 578 579 // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable 580 switch (true) { 581 case !function_exists('hash_pbkdf2'): 582 case !function_exists('hash_algos'): 583 case !in_array($hash, hash_algos()): 584 if (!class_exists('Crypt_Hash')) { 585 require_once('Crypt/Hash.php'); 586 } 587 $i = 1; 588 while (strlen($key) < $dkLen) { 589 $hmac = new Crypt_Hash(); 590 $hmac->setHash($hash); 591 $hmac->setKey($password); 592 $f = $u = $hmac->hash($salt . pack('N', $i++)); 593 for ($j = 2; $j <= $count; ++$j) { 594 $u = $hmac->hash($u); 595 $f^= $u; 596 } 597 $key.= $f; 598 } 599 $key = substr($key, 0, $dkLen); 600 break; 601 default: 602 $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true); 603 } 604 } 605 606 $this->setKey($key); 607 } 608 609 /** 610 * Encrypts a message. 611 * 612 * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher 613 * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's 614 * necessary are discussed in the following 615 * URL: 616 * 617 * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html} 618 * 619 * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. 620 * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that 621 * length. 622 * 623 * Note: Could, but not must, extend by the child Crypt_* class 624 * 625 * @see Crypt_Base::decrypt() 626 * @access public 627 * @param String $plaintext 628 * @return String $cipertext 629 */ 630 function encrypt($plaintext) 631 { 632 if ($this->engine == CRYPT_MODE_MCRYPT) { 633 if ($this->changed) { 634 $this->_setupMcrypt(); 635 $this->changed = false; 636 } 637 if ($this->enchanged) { 638 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); 639 $this->enchanged = false; 640 } 641 642 // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} 643 // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's 644 // rewritten CFB implementation the above outputs the same thing twice. 645 if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) { 646 $block_size = $this->block_size; 647 $iv = &$this->encryptIV; 648 $pos = &$this->enbuffer['pos']; 649 $len = strlen($plaintext); 650 $ciphertext = ''; 651 $i = 0; 652 if ($pos) { 653 $orig_pos = $pos; 654 $max = $block_size - $pos; 655 if ($len >= $max) { 656 $i = $max; 657 $len-= $max; 658 $pos = 0; 659 } else { 660 $i = $len; 661 $pos+= $len; 662 $len = 0; 663 } 664 $ciphertext = substr($iv, $orig_pos) ^ $plaintext; 665 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); 666 $this->enbuffer['enmcrypt_init'] = true; 667 } 668 if ($len >= $block_size) { 669 if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { 670 if ($this->enbuffer['enmcrypt_init'] === true) { 671 mcrypt_generic_init($this->enmcrypt, $this->key, $iv); 672 $this->enbuffer['enmcrypt_init'] = false; 673 } 674 $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); 675 $iv = substr($ciphertext, -$block_size); 676 $len%= $block_size; 677 } else { 678 while ($len >= $block_size) { 679 $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); 680 $ciphertext.= $iv; 681 $len-= $block_size; 682 $i+= $block_size; 683 } 684 } 685 } 686 687 if ($len) { 688 $iv = mcrypt_generic($this->ecb, $iv); 689 $block = $iv ^ substr($plaintext, -$len); 690 $iv = substr_replace($iv, $block, 0, $len); 691 $ciphertext.= $block; 692 $pos = $len; 693 } 694 695 return $ciphertext; 696 } 697 698 if ($this->paddable) { 699 $plaintext = $this->_pad($plaintext); 700 } 701 702 $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); 703 704 if (!$this->continuousBuffer) { 705 mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); 706 } 707 708 return $ciphertext; 709 } 710 711 if ($this->changed) { 712 $this->_setup(); 713 $this->changed = false; 714 } 715 if ($this->use_inline_crypt) { 716 $inline = $this->inline_crypt; 717 return $inline('encrypt', $this, $plaintext); 718 } 719 if ($this->paddable) { 720 $plaintext = $this->_pad($plaintext); 721 } 722 723 $buffer = &$this->enbuffer; 724 $block_size = $this->block_size; 725 $ciphertext = ''; 726 switch ($this->mode) { 727 case CRYPT_MODE_ECB: 728 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { 729 $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size)); 730 } 731 break; 732 case CRYPT_MODE_CBC: 733 $xor = $this->encryptIV; 734 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { 735 $block = substr($plaintext, $i, $block_size); 736 $block = $this->_encryptBlock($block ^ $xor); 737 $xor = $block; 738 $ciphertext.= $block; 739 } 740 if ($this->continuousBuffer) { 741 $this->encryptIV = $xor; 742 } 743 break; 744 case CRYPT_MODE_CTR: 745 $xor = $this->encryptIV; 746 if (strlen($buffer['encrypted'])) { 747 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { 748 $block = substr($plaintext, $i, $block_size); 749 if (strlen($block) > strlen($buffer['encrypted'])) { 750 $buffer['encrypted'].= $this->_encryptBlock($this->_generateXor($xor, $block_size)); 751 } 752 $key = $this->_stringShift($buffer['encrypted'], $block_size); 753 $ciphertext.= $block ^ $key; 754 } 755 } else { 756 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { 757 $block = substr($plaintext, $i, $block_size); 758 $key = $this->_encryptBlock($this->_generateXor($xor, $block_size)); 759 $ciphertext.= $block ^ $key; 760 } 761 } 762 if ($this->continuousBuffer) { 763 $this->encryptIV = $xor; 764 if ($start = strlen($plaintext) % $block_size) { 765 $buffer['encrypted'] = substr($key, $start) . $buffer['encrypted']; 766 } 767 } 768 break; 769 case CRYPT_MODE_CFB: 770 // cfb loosely routines inspired by openssl's: 771 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} 772 if ($this->continuousBuffer) { 773 $iv = &$this->encryptIV; 774 $pos = &$buffer['pos']; 775 } else { 776 $iv = $this->encryptIV; 777 $pos = 0; 778 } 779 $len = strlen($plaintext); 780 $i = 0; 781 if ($pos) { 782 $orig_pos = $pos; 783 $max = $block_size - $pos; 784 if ($len >= $max) { 785 $i = $max; 786 $len-= $max; 787 $pos = 0; 788 } else { 789 $i = $len; 790 $pos+= $len; 791 $len = 0; 792 } 793 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 794 $ciphertext = substr($iv, $orig_pos) ^ $plaintext; 795 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); 796 } 797 while ($len >= $block_size) { 798 $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size); 799 $ciphertext.= $iv; 800 $len-= $block_size; 801 $i+= $block_size; 802 } 803 if ($len) { 804 $iv = $this->_encryptBlock($iv); 805 $block = $iv ^ substr($plaintext, $i); 806 $iv = substr_replace($iv, $block, 0, $len); 807 $ciphertext.= $block; 808 $pos = $len; 809 } 810 break; 811 case CRYPT_MODE_OFB: 812 $xor = $this->encryptIV; 813 if (strlen($buffer['xor'])) { 814 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { 815 $block = substr($plaintext, $i, $block_size); 816 if (strlen($block) > strlen($buffer['xor'])) { 817 $xor = $this->_encryptBlock($xor); 818 $buffer['xor'].= $xor; 819 } 820 $key = $this->_stringShift($buffer['xor'], $block_size); 821 $ciphertext.= $block ^ $key; 822 } 823 } else { 824 for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { 825 $xor = $this->_encryptBlock($xor); 826 $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor; 827 } 828 $key = $xor; 829 } 830 if ($this->continuousBuffer) { 831 $this->encryptIV = $xor; 832 if ($start = strlen($plaintext) % $block_size) { 833 $buffer['xor'] = substr($key, $start) . $buffer['xor']; 834 } 835 } 836 break; 837 case CRYPT_MODE_STREAM: 838 $ciphertext = $this->_encryptBlock($plaintext); 839 break; 840 } 841 842 return $ciphertext; 843 } 844 845 /** 846 * Decrypts a message. 847 * 848 * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until 849 * it is. 850 * 851 * Note: Could, but not must, extend by the child Crypt_* class 852 * 853 * @see Crypt_Base::encrypt() 854 * @access public 855 * @param String $ciphertext 856 * @return String $plaintext 857 */ 858 function decrypt($ciphertext) 859 { 860 if ($this->engine == CRYPT_MODE_MCRYPT) { 861 $block_size = $this->block_size; 862 if ($this->changed) { 863 $this->_setupMcrypt(); 864 $this->changed = false; 865 } 866 if ($this->dechanged) { 867 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); 868 $this->dechanged = false; 869 } 870 871 if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) { 872 $iv = &$this->decryptIV; 873 $pos = &$this->debuffer['pos']; 874 $len = strlen($ciphertext); 875 $plaintext = ''; 876 $i = 0; 877 if ($pos) { 878 $orig_pos = $pos; 879 $max = $block_size - $pos; 880 if ($len >= $max) { 881 $i = $max; 882 $len-= $max; 883 $pos = 0; 884 } else { 885 $i = $len; 886 $pos+= $len; 887 $len = 0; 888 } 889 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 890 $plaintext = substr($iv, $orig_pos) ^ $ciphertext; 891 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); 892 } 893 if ($len >= $block_size) { 894 $cb = substr($ciphertext, $i, $len - $len % $block_size); 895 $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; 896 $iv = substr($cb, -$block_size); 897 $len%= $block_size; 898 } 899 if ($len) { 900 $iv = mcrypt_generic($this->ecb, $iv); 901 $plaintext.= $iv ^ substr($ciphertext, -$len); 902 $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); 903 $pos = $len; 904 } 905 906 return $plaintext; 907 } 908 909 if ($this->paddable) { 910 // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://php.net/function.mcrypt-generic}: 911 // "The data is padded with "\0" to make sure the length of the data is n * blocksize." 912 $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0)); 913 } 914 915 $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); 916 917 if (!$this->continuousBuffer) { 918 mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); 919 } 920 921 return $this->paddable ? $this->_unpad($plaintext) : $plaintext; 922 } 923 924 if ($this->changed) { 925 $this->_setup(); 926 $this->changed = false; 927 } 928 if ($this->use_inline_crypt) { 929 $inline = $this->inline_crypt; 930 return $inline('decrypt', $this, $ciphertext); 931 } 932 933 $block_size = $this->block_size; 934 if ($this->paddable) { 935 // we pad with chr(0) since that's what mcrypt_generic does [...] 936 $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0)); 937 } 938 939 $buffer = &$this->debuffer; 940 $plaintext = ''; 941 switch ($this->mode) { 942 case CRYPT_MODE_ECB: 943 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { 944 $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size)); 945 } 946 break; 947 case CRYPT_MODE_CBC: 948 $xor = $this->decryptIV; 949 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { 950 $block = substr($ciphertext, $i, $block_size); 951 $plaintext.= $this->_decryptBlock($block) ^ $xor; 952 $xor = $block; 953 } 954 if ($this->continuousBuffer) { 955 $this->decryptIV = $xor; 956 } 957 break; 958 case CRYPT_MODE_CTR: 959 $xor = $this->decryptIV; 960 if (strlen($buffer['ciphertext'])) { 961 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { 962 $block = substr($ciphertext, $i, $block_size); 963 if (strlen($block) > strlen($buffer['ciphertext'])) { 964 $buffer['ciphertext'].= $this->_encryptBlock($this->_generateXor($xor, $block_size)); 965 } 966 $key = $this->_stringShift($buffer['ciphertext'], $block_size); 967 $plaintext.= $block ^ $key; 968 } 969 } else { 970 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { 971 $block = substr($ciphertext, $i, $block_size); 972 $key = $this->_encryptBlock($this->_generateXor($xor, $block_size)); 973 $plaintext.= $block ^ $key; 974 } 975 } 976 if ($this->continuousBuffer) { 977 $this->decryptIV = $xor; 978 if ($start = strlen($ciphertext) % $block_size) { 979 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; 980 } 981 } 982 break; 983 case CRYPT_MODE_CFB: 984 if ($this->continuousBuffer) { 985 $iv = &$this->decryptIV; 986 $pos = &$buffer['pos']; 987 } else { 988 $iv = $this->decryptIV; 989 $pos = 0; 990 } 991 $len = strlen($ciphertext); 992 $i = 0; 993 if ($pos) { 994 $orig_pos = $pos; 995 $max = $block_size - $pos; 996 if ($len >= $max) { 997 $i = $max; 998 $len-= $max; 999 $pos = 0; 1000 } else { 1001 $i = $len; 1002 $pos+= $len; 1003 $len = 0; 1004 } 1005 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 1006 $plaintext = substr($iv, $orig_pos) ^ $ciphertext; 1007 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); 1008 } 1009 while ($len >= $block_size) { 1010 $iv = $this->_encryptBlock($iv); 1011 $cb = substr($ciphertext, $i, $block_size); 1012 $plaintext.= $iv ^ $cb; 1013 $iv = $cb; 1014 $len-= $block_size; 1015 $i+= $block_size; 1016 } 1017 if ($len) { 1018 $iv = $this->_encryptBlock($iv); 1019 $plaintext.= $iv ^ substr($ciphertext, $i); 1020 $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len); 1021 $pos = $len; 1022 } 1023 break; 1024 case CRYPT_MODE_OFB: 1025 $xor = $this->decryptIV; 1026 if (strlen($buffer['xor'])) { 1027 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { 1028 $block = substr($ciphertext, $i, $block_size); 1029 if (strlen($block) > strlen($buffer['xor'])) { 1030 $xor = $this->_encryptBlock($xor); 1031 $buffer['xor'].= $xor; 1032 } 1033 $key = $this->_stringShift($buffer['xor'], $block_size); 1034 $plaintext.= $block ^ $key; 1035 } 1036 } else { 1037 for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { 1038 $xor = $this->_encryptBlock($xor); 1039 $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor; 1040 } 1041 $key = $xor; 1042 } 1043 if ($this->continuousBuffer) { 1044 $this->decryptIV = $xor; 1045 if ($start = strlen($ciphertext) % $block_size) { 1046 $buffer['xor'] = substr($key, $start) . $buffer['xor']; 1047 } 1048 } 1049 break; 1050 case CRYPT_MODE_STREAM: 1051 $plaintext = $this->_decryptBlock($ciphertext); 1052 break; 1053 } 1054 return $this->paddable ? $this->_unpad($plaintext) : $plaintext; 1055 } 1056 1057 /** 1058 * Pad "packets". 1059 * 1060 * Block ciphers working by encrypting between their specified [$this->]block_size at a time 1061 * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to 1062 * pad the input so that it is of the proper length. 1063 * 1064 * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH, 1065 * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping 1066 * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is 1067 * transmitted separately) 1068 * 1069 * @see Crypt_Base::disablePadding() 1070 * @access public 1071 */ 1072 function enablePadding() 1073 { 1074 $this->padding = true; 1075 } 1076 1077 /** 1078 * Do not pad packets. 1079 * 1080 * @see Crypt_Base::enablePadding() 1081 * @access public 1082 */ 1083 function disablePadding() 1084 { 1085 $this->padding = false; 1086 } 1087 1088 /** 1089 * Treat consecutive "packets" as if they are a continuous buffer. 1090 * 1091 * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets 1092 * will yield different outputs: 1093 * 1094 * <code> 1095 * echo $rijndael->encrypt(substr($plaintext, 0, 16)); 1096 * echo $rijndael->encrypt(substr($plaintext, 16, 16)); 1097 * </code> 1098 * <code> 1099 * echo $rijndael->encrypt($plaintext); 1100 * </code> 1101 * 1102 * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates 1103 * another, as demonstrated with the following: 1104 * 1105 * <code> 1106 * $rijndael->encrypt(substr($plaintext, 0, 16)); 1107 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); 1108 * </code> 1109 * <code> 1110 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); 1111 * </code> 1112 * 1113 * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different 1114 * outputs. The reason is due to the fact that the initialization vector's change after every encryption / 1115 * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. 1116 * 1117 * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each 1118 * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that 1119 * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), 1120 * however, they are also less intuitive and more likely to cause you problems. 1121 * 1122 * Note: Could, but not must, extend by the child Crypt_* class 1123 * 1124 * @see Crypt_Base::disableContinuousBuffer() 1125 * @access public 1126 */ 1127 function enableContinuousBuffer() 1128 { 1129 if ($this->mode == CRYPT_MODE_ECB) { 1130 return; 1131 } 1132 1133 $this->continuousBuffer = true; 1134 } 1135 1136 /** 1137 * Treat consecutive packets as if they are a discontinuous buffer. 1138 * 1139 * The default behavior. 1140 * 1141 * Note: Could, but not must, extend by the child Crypt_* class 1142 * 1143 * @see Crypt_Base::enableContinuousBuffer() 1144 * @access public 1145 */ 1146 function disableContinuousBuffer() 1147 { 1148 if ($this->mode == CRYPT_MODE_ECB) { 1149 return; 1150 } 1151 if (!$this->continuousBuffer) { 1152 return; 1153 } 1154 1155 $this->continuousBuffer = false; 1156 $this->changed = true; 1157 } 1158 1159 /** 1160 * Encrypts a block 1161 * 1162 * Note: Must extend by the child Crypt_* class 1163 * 1164 * @access private 1165 * @param String $in 1166 * @return String 1167 */ 1168 function _encryptBlock($in) 1169 { 1170 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); 1171 } 1172 1173 /** 1174 * Decrypts a block 1175 * 1176 * Note: Must extend by the child Crypt_* class 1177 * 1178 * @access private 1179 * @param String $in 1180 * @return String 1181 */ 1182 function _decryptBlock($in) 1183 { 1184 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); 1185 } 1186 1187 /** 1188 * Setup the key (expansion) 1189 * 1190 * Only used if $engine == CRYPT_MODE_INTERNAL 1191 * 1192 * Note: Must extend by the child Crypt_* class 1193 * 1194 * @see Crypt_Base::_setup() 1195 * @access private 1196 */ 1197 function _setupKey() 1198 { 1199 user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); 1200 } 1201 1202 /** 1203 * Setup the CRYPT_MODE_INTERNAL $engine 1204 * 1205 * (re)init, if necessary, the internal cipher $engine and flush all $buffers 1206 * Used (only) if $engine == CRYPT_MODE_INTERNAL 1207 * 1208 * _setup() will be called each time if $changed === true 1209 * typically this happens when using one or more of following public methods: 1210 * 1211 * - setKey() 1212 * 1213 * - setIV() 1214 * 1215 * - disableContinuousBuffer() 1216 * 1217 * - First run of encrypt() / decrypt() with no init-settings 1218 * 1219 * Internally: _setup() is called always before(!) en/decryption. 1220 * 1221 * Note: Could, but not must, extend by the child Crypt_* class 1222 * 1223 * @see setKey() 1224 * @see setIV() 1225 * @see disableContinuousBuffer() 1226 * @access private 1227 */ 1228 function _setup() 1229 { 1230 $this->_clearBuffers(); 1231 $this->_setupKey(); 1232 1233 if ($this->use_inline_crypt) { 1234 $this->_setupInlineCrypt(); 1235 } 1236 } 1237 1238 /** 1239 * Setup the CRYPT_MODE_MCRYPT $engine 1240 * 1241 * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers 1242 * Used (only) if $engine = CRYPT_MODE_MCRYPT 1243 * 1244 * _setupMcrypt() will be called each time if $changed === true 1245 * typically this happens when using one or more of following public methods: 1246 * 1247 * - setKey() 1248 * 1249 * - setIV() 1250 * 1251 * - disableContinuousBuffer() 1252 * 1253 * - First run of encrypt() / decrypt() 1254 * 1255 * 1256 * Note: Could, but not must, extend by the child Crypt_* class 1257 * 1258 * @see setKey() 1259 * @see setIV() 1260 * @see disableContinuousBuffer() 1261 * @access private 1262 */ 1263 function _setupMcrypt() 1264 { 1265 $this->_clearBuffers(); 1266 $this->enchanged = $this->dechanged = true; 1267 1268 if (!isset($this->enmcrypt)) { 1269 static $mcrypt_modes = array( 1270 CRYPT_MODE_CTR => 'ctr', 1271 CRYPT_MODE_ECB => MCRYPT_MODE_ECB, 1272 CRYPT_MODE_CBC => MCRYPT_MODE_CBC, 1273 CRYPT_MODE_CFB => 'ncfb', 1274 CRYPT_MODE_OFB => MCRYPT_MODE_NOFB, 1275 CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM, 1276 ); 1277 1278 $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); 1279 $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); 1280 1281 // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() 1282 // to workaround mcrypt's broken ncfb implementation in buffered mode 1283 // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} 1284 if ($this->mode == CRYPT_MODE_CFB) { 1285 $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); 1286 } 1287 1288 } // else should mcrypt_generic_deinit be called? 1289 1290 if ($this->mode == CRYPT_MODE_CFB) { 1291 mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); 1292 } 1293 } 1294 1295 /** 1296 * Pads a string 1297 * 1298 * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize. 1299 * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to 1300 * chr($this->block_size - (strlen($text) % $this->block_size) 1301 * 1302 * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless 1303 * and padding will, hence forth, be enabled. 1304 * 1305 * @see Crypt_Base::_unpad() 1306 * @param String $text 1307 * @access private 1308 * @return String 1309 */ 1310 function _pad($text) 1311 { 1312 $length = strlen($text); 1313 1314 if (!$this->padding) { 1315 if ($length % $this->block_size == 0) { 1316 return $text; 1317 } else { 1318 user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})"); 1319 $this->padding = true; 1320 } 1321 } 1322 1323 $pad = $this->block_size - ($length % $this->block_size); 1324 1325 return str_pad($text, $length + $pad, chr($pad)); 1326 } 1327 1328 /** 1329 * Unpads a string. 1330 * 1331 * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong 1332 * and false will be returned. 1333 * 1334 * @see Crypt_Base::_pad() 1335 * @param String $text 1336 * @access private 1337 * @return String 1338 */ 1339 function _unpad($text) 1340 { 1341 if (!$this->padding) { 1342 return $text; 1343 } 1344 1345 $length = ord($text[strlen($text) - 1]); 1346 1347 if (!$length || $length > $this->block_size) { 1348 return false; 1349 } 1350 1351 return substr($text, 0, -$length); 1352 } 1353 1354 /** 1355 * Clears internal buffers 1356 * 1357 * Clearing/resetting the internal buffers is done everytime 1358 * after disableContinuousBuffer() or on cipher $engine (re)init 1359 * ie after setKey() or setIV() 1360 * 1361 * Note: Could, but not must, extend by the child Crypt_* class 1362 * 1363 * @access public 1364 */ 1365 function _clearBuffers() 1366 { 1367 $this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true); 1368 $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true); 1369 1370 // mcrypt's handling of invalid's $iv: 1371 // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size); 1372 $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0"); 1373 } 1374 1375 /** 1376 * String Shift 1377 * 1378 * Inspired by array_shift 1379 * 1380 * @param String $string 1381 * @param optional Integer $index 1382 * @access private 1383 * @return String 1384 */ 1385 function _stringShift(&$string, $index = 1) 1386 { 1387 $substr = substr($string, 0, $index); 1388 $string = substr($string, $index); 1389 return $substr; 1390 } 1391 1392 /** 1393 * Generate CTR XOR encryption key 1394 * 1395 * Encrypt the output of this and XOR it against the ciphertext / plaintext to get the 1396 * plaintext / ciphertext in CTR mode. 1397 * 1398 * @see Crypt_Base::decrypt() 1399 * @see Crypt_Base::encrypt() 1400 * @param String $iv 1401 * @param Integer $length 1402 * @access private 1403 * @return String $xor 1404 */ 1405 function _generateXor(&$iv, $length) 1406 { 1407 $xor = ''; 1408 $block_size = $this->block_size; 1409 $num_blocks = floor(($length + ($block_size - 1)) / $block_size); 1410 for ($i = 0; $i < $num_blocks; $i++) { 1411 $xor.= $iv; 1412 for ($j = 4; $j <= $block_size; $j+= 4) { 1413 $temp = substr($iv, -$j, 4); 1414 switch ($temp) { 1415 case "\xFF\xFF\xFF\xFF": 1416 $iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4); 1417 break; 1418 case "\x7F\xFF\xFF\xFF": 1419 $iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4); 1420 break 2; 1421 default: 1422 extract(unpack('Ncount', $temp)); 1423 $iv = substr_replace($iv, pack('N', $count + 1), -$j, 4); 1424 break 2; 1425 } 1426 } 1427 } 1428 1429 return $xor; 1430 } 1431 1432 /** 1433 * Setup the performance-optimized function for de/encrypt() 1434 * 1435 * Stores the created (or existing) callback function-name 1436 * in $this->inline_crypt 1437 * 1438 * Internally for phpseclib developers: 1439 * 1440 * _setupInlineCrypt() would be called only if: 1441 * 1442 * - $engine == CRYPT_MODE_INTERNAL and 1443 * 1444 * - $use_inline_crypt === true 1445 * 1446 * - each time on _setup(), after(!) _setupKey() 1447 * 1448 * 1449 * This ensures that _setupInlineCrypt() has allways a 1450 * full ready2go initializated internal cipher $engine state 1451 * where, for example, the keys allready expanded, 1452 * keys/block_size calculated and such. 1453 * 1454 * It is, each time if called, the responsibility of _setupInlineCrypt(): 1455 * 1456 * - to set $this->inline_crypt to a valid and fully working callback function 1457 * as a (faster) replacement for encrypt() / decrypt() 1458 * 1459 * - NOT to create unlimited callback functions (for memory reasons!) 1460 * no matter how often _setupInlineCrypt() would be called. At some 1461 * point of amount they must be generic re-useable. 1462 * 1463 * - the code of _setupInlineCrypt() it self, 1464 * and the generated callback code, 1465 * must be, in following order: 1466 * - 100% safe 1467 * - 100% compatible to encrypt()/decrypt() 1468 * - using only php5+ features/lang-constructs/php-extensions if 1469 * compatibility (down to php4) or fallback is provided 1470 * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-) 1471 * - >= 10% faster than encrypt()/decrypt() [which is, by the way, 1472 * the reason for the existence of _setupInlineCrypt() :-)] 1473 * - memory-nice 1474 * - short (as good as possible) 1475 * 1476 * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code. 1477 * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class. 1478 * - The following variable names are reserved: 1479 * - $_* (all variable names prefixed with an underscore) 1480 * - $self (object reference to it self. Do not use $this, but $self instead) 1481 * - $in (the content of $in has to en/decrypt by the generated code) 1482 * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only 1483 * 1484 * 1485 * @see Crypt_Base::_setup() 1486 * @see Crypt_Base::_createInlineCryptFunction() 1487 * @see Crypt_Base::encrypt() 1488 * @see Crypt_Base::decrypt() 1489 * @access private 1490 */ 1491 function _setupInlineCrypt() 1492 { 1493 // If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt() 1494 1495 // If, for any reason, an extending Crypt_Base() Crypt_* class 1496 // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false 1497 // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class, 1498 // in the constructor at object instance-time 1499 // or, if it's runtime-specific, at runtime 1500 1501 $this->use_inline_crypt = false; 1502 } 1503 1504 /** 1505 * Creates the performance-optimized function for en/decrypt() 1506 * 1507 * Internally for phpseclib developers: 1508 * 1509 * _createInlineCryptFunction(): 1510 * 1511 * - merge the $cipher_code [setup'ed by _setupInlineCrypt()] 1512 * with the current [$this->]mode of operation code 1513 * 1514 * - create the $inline function, which called by encrypt() / decrypt() 1515 * as its replacement to speed up the en/decryption operations. 1516 * 1517 * - return the name of the created $inline callback function 1518 * 1519 * - used to speed up en/decryption 1520 * 1521 * 1522 * 1523 * The main reason why can speed up things [up to 50%] this way are: 1524 * 1525 * - using variables more effective then regular. 1526 * (ie no use of expensive arrays but integers $k_0, $k_1 ... 1527 * or even, for example, the pure $key[] values hardcoded) 1528 * 1529 * - avoiding 1000's of function calls of ie _encryptBlock() 1530 * but inlining the crypt operations. 1531 * in the mode of operation for() loop. 1532 * 1533 * - full loop unroll the (sometimes key-dependent) rounds 1534 * avoiding this way ++$i counters and runtime-if's etc... 1535 * 1536 * The basic code architectur of the generated $inline en/decrypt() 1537 * lambda function, in pseudo php, is: 1538 * 1539 * <code> 1540 * +----------------------------------------------------------------------------------------------+ 1541 * | callback $inline = create_function: | 1542 * | lambda_function_0001_crypt_ECB($action, $text) | 1543 * | { | 1544 * | INSERT PHP CODE OF: | 1545 * | $cipher_code['init_crypt']; // general init code. | 1546 * | // ie: $sbox'es declarations used for | 1547 * | // encrypt and decrypt'ing. | 1548 * | | 1549 * | switch ($action) { | 1550 * | case 'encrypt': | 1551 * | INSERT PHP CODE OF: | 1552 * | $cipher_code['init_encrypt']; // encrypt sepcific init code. | 1553 * | ie: specified $key or $box | 1554 * | declarations for encrypt'ing. | 1555 * | | 1556 * | foreach ($ciphertext) { | 1557 * | $in = $block_size of $ciphertext; | 1558 * | | 1559 * | INSERT PHP CODE OF: | 1560 * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: | 1561 * | // strlen($in) == $this->block_size | 1562 * | // here comes the cipher algorithm in action | 1563 * | // for encryption. | 1564 * | // $cipher_code['encrypt_block'] has to | 1565 * | // encrypt the content of the $in variable | 1566 * | | 1567 * | $plaintext .= $in; | 1568 * | } | 1569 * | return $plaintext; | 1570 * | | 1571 * | case 'decrypt': | 1572 * | INSERT PHP CODE OF: | 1573 * | $cipher_code['init_decrypt']; // decrypt sepcific init code | 1574 * | ie: specified $key or $box | 1575 * | declarations for decrypt'ing. | 1576 * | foreach ($plaintext) { | 1577 * | $in = $block_size of $plaintext; | 1578 * | | 1579 * | INSERT PHP CODE OF: | 1580 * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always | 1581 * | // strlen($in) == $this->block_size | 1582 * | // here comes the cipher algorithm in action | 1583 * | // for decryption. | 1584 * | // $cipher_code['decrypt_block'] has to | 1585 * | // decrypt the content of the $in variable | 1586 * | $ciphertext .= $in; | 1587 * | } | 1588 * | return $ciphertext; | 1589 * | } | 1590 * | } | 1591 * +----------------------------------------------------------------------------------------------+ 1592 * </code> 1593 * 1594 * See also the Crypt_*::_setupInlineCrypt()'s for 1595 * productive inline $cipher_code's how they works. 1596 * 1597 * Structure of: 1598 * <code> 1599 * $cipher_code = array( 1600 * 'init_crypt' => (string) '', // optional 1601 * 'init_encrypt' => (string) '', // optional 1602 * 'init_decrypt' => (string) '', // optional 1603 * 'encrypt_block' => (string) '', // required 1604 * 'decrypt_block' => (string) '' // required 1605 * ); 1606 * </code> 1607 * 1608 * @see Crypt_Base::_setupInlineCrypt() 1609 * @see Crypt_Base::encrypt() 1610 * @see Crypt_Base::decrypt() 1611 * @param Array $cipher_code 1612 * @access private 1613 * @return String (the name of the created callback function) 1614 */ 1615 function _createInlineCryptFunction($cipher_code) 1616 { 1617 $block_size = $this->block_size; 1618 1619 // optional 1620 $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : ''; 1621 $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : ''; 1622 $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : ''; 1623 // required 1624 $encrypt_block = $cipher_code['encrypt_block']; 1625 $decrypt_block = $cipher_code['decrypt_block']; 1626 1627 // Generating mode of operation inline code, 1628 // merged with the $cipher_code algorithm 1629 // for encrypt- and decryption. 1630 switch ($this->mode) { 1631 case CRYPT_MODE_ECB: 1632 $encrypt = $init_encrypt . ' 1633 $_ciphertext = ""; 1634 $_text = $self->_pad($_text); 1635 $_plaintext_len = strlen($_text); 1636 1637 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { 1638 $in = substr($_text, $_i, '.$block_size.'); 1639 '.$encrypt_block.' 1640 $_ciphertext.= $in; 1641 } 1642 1643 return $_ciphertext; 1644 '; 1645 1646 $decrypt = $init_decrypt . ' 1647 $_plaintext = ""; 1648 $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0)); 1649 $_ciphertext_len = strlen($_text); 1650 1651 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { 1652 $in = substr($_text, $_i, '.$block_size.'); 1653 '.$decrypt_block.' 1654 $_plaintext.= $in; 1655 } 1656 1657 return $self->_unpad($_plaintext); 1658 '; 1659 break; 1660 case CRYPT_MODE_CTR: 1661 $encrypt = $init_encrypt . ' 1662 $_ciphertext = ""; 1663 $_plaintext_len = strlen($_text); 1664 $_xor = $self->encryptIV; 1665 $_buffer = &$self->enbuffer; 1666 1667 if (strlen($_buffer["encrypted"])) { 1668 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { 1669 $_block = substr($_text, $_i, '.$block_size.'); 1670 if (strlen($_block) > strlen($_buffer["encrypted"])) { 1671 $in = $self->_generateXor($_xor, '.$block_size.'); 1672 '.$encrypt_block.' 1673 $_buffer["encrypted"].= $in; 1674 } 1675 $_key = $self->_stringShift($_buffer["encrypted"], '.$block_size.'); 1676 $_ciphertext.= $_block ^ $_key; 1677 } 1678 } else { 1679 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { 1680 $_block = substr($_text, $_i, '.$block_size.'); 1681 $in = $self->_generateXor($_xor, '.$block_size.'); 1682 '.$encrypt_block.' 1683 $_key = $in; 1684 $_ciphertext.= $_block ^ $_key; 1685 } 1686 } 1687 if ($self->continuousBuffer) { 1688 $self->encryptIV = $_xor; 1689 if ($_start = $_plaintext_len % '.$block_size.') { 1690 $_buffer["encrypted"] = substr($_key, $_start) . $_buffer["encrypted"]; 1691 } 1692 } 1693 1694 return $_ciphertext; 1695 '; 1696 1697 $decrypt = $init_encrypt . ' 1698 $_plaintext = ""; 1699 $_ciphertext_len = strlen($_text); 1700 $_xor = $self->decryptIV; 1701 $_buffer = &$self->debuffer; 1702 1703 if (strlen($_buffer["ciphertext"])) { 1704 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { 1705 $_block = substr($_text, $_i, '.$block_size.'); 1706 if (strlen($_block) > strlen($_buffer["ciphertext"])) { 1707 $in = $self->_generateXor($_xor, '.$block_size.'); 1708 '.$encrypt_block.' 1709 $_buffer["ciphertext"].= $in; 1710 } 1711 $_key = $self->_stringShift($_buffer["ciphertext"], '.$block_size.'); 1712 $_plaintext.= $_block ^ $_key; 1713 } 1714 } else { 1715 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { 1716 $_block = substr($_text, $_i, '.$block_size.'); 1717 $in = $self->_generateXor($_xor, '.$block_size.'); 1718 '.$encrypt_block.' 1719 $_key = $in; 1720 $_plaintext.= $_block ^ $_key; 1721 } 1722 } 1723 if ($self->continuousBuffer) { 1724 $self->decryptIV = $_xor; 1725 if ($_start = $_ciphertext_len % '.$block_size.') { 1726 $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; 1727 } 1728 } 1729 1730 return $_plaintext; 1731 '; 1732 break; 1733 case CRYPT_MODE_CFB: 1734 $encrypt = $init_encrypt . ' 1735 $_ciphertext = ""; 1736 $_buffer = &$self->enbuffer; 1737 1738 if ($self->continuousBuffer) { 1739 $_iv = &$self->encryptIV; 1740 $_pos = &$_buffer["pos"]; 1741 } else { 1742 $_iv = $self->encryptIV; 1743 $_pos = 0; 1744 } 1745 $_len = strlen($_text); 1746 $_i = 0; 1747 if ($_pos) { 1748 $_orig_pos = $_pos; 1749 $_max = '.$block_size.' - $_pos; 1750 if ($_len >= $_max) { 1751 $_i = $_max; 1752 $_len-= $_max; 1753 $_pos = 0; 1754 } else { 1755 $_i = $_len; 1756 $_pos+= $_len; 1757 $_len = 0; 1758 } 1759 $_ciphertext = substr($_iv, $_orig_pos) ^ $_text; 1760 $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i); 1761 } 1762 while ($_len >= '.$block_size.') { 1763 $in = $_iv; 1764 '.$encrypt_block.'; 1765 $_iv = $in ^ substr($_text, $_i, '.$block_size.'); 1766 $_ciphertext.= $_iv; 1767 $_len-= '.$block_size.'; 1768 $_i+= '.$block_size.'; 1769 } 1770 if ($_len) { 1771 $in = $_iv; 1772 '.$encrypt_block.' 1773 $_iv = $in; 1774 $_block = $_iv ^ substr($_text, $_i); 1775 $_iv = substr_replace($_iv, $_block, 0, $_len); 1776 $_ciphertext.= $_block; 1777 $_pos = $_len; 1778 } 1779 return $_ciphertext; 1780 '; 1781 1782 $decrypt = $init_encrypt . ' 1783 $_plaintext = ""; 1784 $_buffer = &$self->debuffer; 1785 1786 if ($self->continuousBuffer) { 1787 $_iv = &$self->decryptIV; 1788 $_pos = &$_buffer["pos"]; 1789 } else { 1790 $_iv = $self->decryptIV; 1791 $_pos = 0; 1792 } 1793 $_len = strlen($_text); 1794 $_i = 0; 1795 if ($_pos) { 1796 $_orig_pos = $_pos; 1797 $_max = '.$block_size.' - $_pos; 1798 if ($_len >= $_max) { 1799 $_i = $_max; 1800 $_len-= $_max; 1801 $_pos = 0; 1802 } else { 1803 $_i = $_len; 1804 $_pos+= $_len; 1805 $_len = 0; 1806 } 1807 $_plaintext = substr($_iv, $_orig_pos) ^ $_text; 1808 $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i); 1809 } 1810 while ($_len >= '.$block_size.') { 1811 $in = $_iv; 1812 '.$encrypt_block.' 1813 $_iv = $in; 1814 $cb = substr($_text, $_i, '.$block_size.'); 1815 $_plaintext.= $_iv ^ $cb; 1816 $_iv = $cb; 1817 $_len-= '.$block_size.'; 1818 $_i+= '.$block_size.'; 1819 } 1820 if ($_len) { 1821 $in = $_iv; 1822 '.$encrypt_block.' 1823 $_iv = $in; 1824 $_plaintext.= $_iv ^ substr($_text, $_i); 1825 $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len); 1826 $_pos = $_len; 1827 } 1828 1829 return $_plaintext; 1830 '; 1831 break; 1832 case CRYPT_MODE_OFB: 1833 $encrypt = $init_encrypt . ' 1834 $_ciphertext = ""; 1835 $_plaintext_len = strlen($_text); 1836 $_xor = $self->encryptIV; 1837 $_buffer = &$self->enbuffer; 1838 1839 if (strlen($_buffer["xor"])) { 1840 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { 1841 $_block = substr($_text, $_i, '.$block_size.'); 1842 if (strlen($_block) > strlen($_buffer["xor"])) { 1843 $in = $_xor; 1844 '.$encrypt_block.' 1845 $_xor = $in; 1846 $_buffer["xor"].= $_xor; 1847 } 1848 $_key = $self->_stringShift($_buffer["xor"], '.$block_size.'); 1849 $_ciphertext.= $_block ^ $_key; 1850 } 1851 } else { 1852 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { 1853 $in = $_xor; 1854 '.$encrypt_block.' 1855 $_xor = $in; 1856 $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor; 1857 } 1858 $_key = $_xor; 1859 } 1860 if ($self->continuousBuffer) { 1861 $self->encryptIV = $_xor; 1862 if ($_start = $_plaintext_len % '.$block_size.') { 1863 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; 1864 } 1865 } 1866 return $_ciphertext; 1867 '; 1868 1869 $decrypt = $init_encrypt . ' 1870 $_plaintext = ""; 1871 $_ciphertext_len = strlen($_text); 1872 $_xor = $self->decryptIV; 1873 $_buffer = &$self->debuffer; 1874 1875 if (strlen($_buffer["xor"])) { 1876 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { 1877 $_block = substr($_text, $_i, '.$block_size.'); 1878 if (strlen($_block) > strlen($_buffer["xor"])) { 1879 $in = $_xor; 1880 '.$encrypt_block.' 1881 $_xor = $in; 1882 $_buffer["xor"].= $_xor; 1883 } 1884 $_key = $self->_stringShift($_buffer["xor"], '.$block_size.'); 1885 $_plaintext.= $_block ^ $_key; 1886 } 1887 } else { 1888 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { 1889 $in = $_xor; 1890 '.$encrypt_block.' 1891 $_xor = $in; 1892 $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor; 1893 } 1894 $_key = $_xor; 1895 } 1896 if ($self->continuousBuffer) { 1897 $self->decryptIV = $_xor; 1898 if ($_start = $_ciphertext_len % '.$block_size.') { 1899 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; 1900 } 1901 } 1902 return $_plaintext; 1903 '; 1904 break; 1905 case CRYPT_MODE_STREAM: 1906 $encrypt = $init_encrypt . ' 1907 $_ciphertext = ""; 1908 '.$encrypt_block.' 1909 return $_ciphertext; 1910 '; 1911 $decrypt = $init_decrypt . ' 1912 $_plaintext = ""; 1913 '.$decrypt_block.' 1914 return $_plaintext; 1915 '; 1916 break; 1917 // case CRYPT_MODE_CBC: 1918 default: 1919 $encrypt = $init_encrypt . ' 1920 $_ciphertext = ""; 1921 $_text = $self->_pad($_text); 1922 $_plaintext_len = strlen($_text); 1923 1924 $in = $self->encryptIV; 1925 1926 for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') { 1927 $in = substr($_text, $_i, '.$block_size.') ^ $in; 1928 '.$encrypt_block.' 1929 $_ciphertext.= $in; 1930 } 1931 1932 if ($self->continuousBuffer) { 1933 $self->encryptIV = $in; 1934 } 1935 1936 return $_ciphertext; 1937 '; 1938 1939 $decrypt = $init_decrypt . ' 1940 $_plaintext = ""; 1941 $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0)); 1942 $_ciphertext_len = strlen($_text); 1943 1944 $_iv = $self->decryptIV; 1945 1946 for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') { 1947 $in = $_block = substr($_text, $_i, '.$block_size.'); 1948 '.$decrypt_block.' 1949 $_plaintext.= $in ^ $_iv; 1950 $_iv = $_block; 1951 } 1952 1953 if ($self->continuousBuffer) { 1954 $self->decryptIV = $_iv; 1955 } 1956 1957 return $self->_unpad($_plaintext); 1958 '; 1959 break; 1960 } 1961 1962 // Create the $inline function and return its name as string. Ready to run! 1963 return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }'); 1964 } 1965 1966 /** 1967 * Holds the lambda_functions table (classwide) 1968 * 1969 * Each name of the lambda function, created from 1970 * _setupInlineCrypt() && _createInlineCryptFunction() 1971 * is stored, classwide (!), here for reusing. 1972 * 1973 * The string-based index of $function is a classwide 1974 * uniqe value representing, at least, the $mode of 1975 * operation (or more... depends of the optimizing level) 1976 * for which $mode the lambda function was created. 1977 * 1978 * @access private 1979 * @return &Array 1980 */ 1981 function &_getLambdaFunctions() 1982 { 1983 static $functions = array(); 1984 return $functions; 1985 } 1986 } 1987 1988 // vim: ts=4:sw=4:et: 1989 // vim6: fdl=1:
title
Description
Body
title
Description
Body
title
Description
Body
title
Body