1<?php 2 3/** 4 * Base Class for all \phpseclib3\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 \phpseclib3\Crypt\* cipher class should extend \phpseclib3\Crypt\Common\SymmetricKey 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 \phpseclib3\Crypt\Common\SymmetricKey 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 37namespace phpseclib3\Crypt\Common; 38 39use phpseclib3\Common\Functions\Strings; 40use phpseclib3\Crypt\Hash; 41use phpseclib3\Exception\BadDecryptionException; 42use phpseclib3\Exception\BadModeException; 43use phpseclib3\Exception\InconsistentSetupException; 44use phpseclib3\Exception\InsufficientSetupException; 45use phpseclib3\Exception\UnsupportedAlgorithmException; 46use phpseclib3\Math\BigInteger; 47use phpseclib3\Math\BinaryField; 48use phpseclib3\Math\PrimeField; 49 50/** 51 * Base Class for all \phpseclib3\Crypt\* cipher classes 52 * 53 * @package Base 54 * @author Jim Wigginton <terrafrost@php.net> 55 * @author Hans-Juergen Petrich <petrich@tronic-media.com> 56 */ 57abstract class SymmetricKey 58{ 59 /** 60 * Encrypt / decrypt using the Counter mode. 61 * 62 * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. 63 * 64 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 65 * @access public 66 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 67 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 68 */ 69 const 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 * @access public 75 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 76 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 77 */ 78 const MODE_ECB = 1; 79 /** 80 * Encrypt / decrypt using the Code Book Chaining mode. 81 * 82 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 83 * @access public 84 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 85 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 86 */ 87 const MODE_CBC = 2; 88 /** 89 * Encrypt / decrypt using the Cipher Feedback mode. 90 * 91 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 92 * @access public 93 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 94 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 95 */ 96 const MODE_CFB = 3; 97 /** 98 * Encrypt / decrypt using the Cipher Feedback mode (8bit) 99 * 100 * @access public 101 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 102 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 103 */ 104 const MODE_CFB8 = 7; 105 /** 106 * Encrypt / decrypt using the Output Feedback mode (8bit) 107 * 108 * @access public 109 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 110 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 111 */ 112 const MODE_OFB8 = 8; 113 /** 114 * Encrypt / decrypt using the Output Feedback mode. 115 * 116 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 117 * @access public 118 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 119 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 120 */ 121 const MODE_OFB = 4; 122 /** 123 * Encrypt / decrypt using Galois/Counter mode. 124 * 125 * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode 126 * @access public 127 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 128 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 129 */ 130 const MODE_GCM = 5; 131 /** 132 * Encrypt / decrypt using streaming mode. 133 * 134 * @access public 135 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() 136 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() 137 */ 138 const MODE_STREAM = 6; 139 140 /** 141 * Mode Map 142 * 143 * @access private 144 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 145 */ 146 const MODE_MAP = [ 147 'ctr' => self::MODE_CTR, 148 'ecb' => self::MODE_ECB, 149 'cbc' => self::MODE_CBC, 150 'cfb' => self::MODE_CFB, 151 'cfb8' => self::MODE_CFB8, 152 'ofb' => self::MODE_OFB, 153 'ofb8' => self::MODE_OFB8, 154 'gcm' => self::MODE_GCM, 155 'stream' => self::MODE_STREAM 156 ]; 157 158 /** 159 * Base value for the internal implementation $engine switch 160 * 161 * @access private 162 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 163 */ 164 const ENGINE_INTERNAL = 1; 165 /** 166 * Base value for the eval() implementation $engine switch 167 * 168 * @access private 169 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 170 */ 171 const ENGINE_EVAL = 2; 172 /** 173 * Base value for the mcrypt implementation $engine switch 174 * 175 * @access private 176 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 177 */ 178 const ENGINE_MCRYPT = 3; 179 /** 180 * Base value for the openssl implementation $engine switch 181 * 182 * @access private 183 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 184 */ 185 const ENGINE_OPENSSL = 4; 186 /** 187 * Base value for the libsodium implementation $engine switch 188 * 189 * @access private 190 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 191 */ 192 const ENGINE_LIBSODIUM = 5; 193 /** 194 * Base value for the openssl / gcm implementation $engine switch 195 * 196 * @access private 197 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() 198 */ 199 const ENGINE_OPENSSL_GCM = 6; 200 201 /** 202 * Engine Reverse Map 203 * 204 * @access private 205 * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine() 206 */ 207 const ENGINE_MAP = [ 208 self::ENGINE_INTERNAL => 'PHP', 209 self::ENGINE_EVAL => 'Eval', 210 self::ENGINE_MCRYPT => 'mcrypt', 211 self::ENGINE_OPENSSL => 'OpenSSL', 212 self::ENGINE_LIBSODIUM => 'libsodium', 213 self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)' 214 ]; 215 216 /** 217 * The Encryption Mode 218 * 219 * @see self::__construct() 220 * @var int 221 * @access private 222 */ 223 protected $mode; 224 225 /** 226 * The Block Length of the block cipher 227 * 228 * @var int 229 * @access private 230 */ 231 protected $block_size = 16; 232 233 /** 234 * The Key 235 * 236 * @see self::setKey() 237 * @var string 238 * @access private 239 */ 240 protected $key = false; 241 242 /** 243 * The Initialization Vector 244 * 245 * @see self::setIV() 246 * @var string 247 * @access private 248 */ 249 protected $iv = false; 250 251 /** 252 * A "sliding" Initialization Vector 253 * 254 * @see self::enableContinuousBuffer() 255 * @see self::clearBuffers() 256 * @var string 257 * @access private 258 */ 259 protected $encryptIV; 260 261 /** 262 * A "sliding" Initialization Vector 263 * 264 * @see self::enableContinuousBuffer() 265 * @see self::clearBuffers() 266 * @var string 267 * @access private 268 */ 269 protected $decryptIV; 270 271 /** 272 * Continuous Buffer status 273 * 274 * @see self::enableContinuousBuffer() 275 * @var bool 276 * @access private 277 */ 278 protected $continuousBuffer = false; 279 280 /** 281 * Encryption buffer for CTR, OFB and CFB modes 282 * 283 * @see self::encrypt() 284 * @see self::clearBuffers() 285 * @var array 286 * @access private 287 */ 288 protected $enbuffer; 289 290 /** 291 * Decryption buffer for CTR, OFB and CFB modes 292 * 293 * @see self::decrypt() 294 * @see self::clearBuffers() 295 * @var array 296 * @access private 297 */ 298 protected $debuffer; 299 300 /** 301 * mcrypt resource for encryption 302 * 303 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. 304 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. 305 * 306 * @see self::encrypt() 307 * @var resource 308 * @access private 309 */ 310 private $enmcrypt; 311 312 /** 313 * mcrypt resource for decryption 314 * 315 * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. 316 * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. 317 * 318 * @see self::decrypt() 319 * @var resource 320 * @access private 321 */ 322 private $demcrypt; 323 324 /** 325 * Does the enmcrypt resource need to be (re)initialized? 326 * 327 * @see \phpseclib3\Crypt\Twofish::setKey() 328 * @see \phpseclib3\Crypt\Twofish::setIV() 329 * @var bool 330 * @access private 331 */ 332 private $enchanged = true; 333 334 /** 335 * Does the demcrypt resource need to be (re)initialized? 336 * 337 * @see \phpseclib3\Crypt\Twofish::setKey() 338 * @see \phpseclib3\Crypt\Twofish::setIV() 339 * @var bool 340 * @access private 341 */ 342 private $dechanged = true; 343 344 /** 345 * mcrypt resource for CFB mode 346 * 347 * mcrypt's CFB mode, in (and only in) buffered context, 348 * is broken, so phpseclib implements the CFB mode by it self, 349 * even when the mcrypt php extension is available. 350 * 351 * In order to do the CFB-mode work (fast) phpseclib 352 * use a separate ECB-mode mcrypt resource. 353 * 354 * @link http://phpseclib.sourceforge.net/cfb-demo.phps 355 * @see self::encrypt() 356 * @see self::decrypt() 357 * @see self::setupMcrypt() 358 * @var resource 359 * @access private 360 */ 361 private $ecb; 362 363 /** 364 * Optimizing value while CFB-encrypting 365 * 366 * Only relevant if $continuousBuffer enabled 367 * and $engine == self::ENGINE_MCRYPT 368 * 369 * It's faster to re-init $enmcrypt if 370 * $buffer bytes > $cfb_init_len than 371 * using the $ecb resource furthermore. 372 * 373 * This value depends of the chosen cipher 374 * and the time it would be needed for it's 375 * initialization [by mcrypt_generic_init()] 376 * which, typically, depends on the complexity 377 * on its internaly Key-expanding algorithm. 378 * 379 * @see self::encrypt() 380 * @var int 381 * @access private 382 */ 383 protected $cfb_init_len = 600; 384 385 /** 386 * Does internal cipher state need to be (re)initialized? 387 * 388 * @see self::setKey() 389 * @see self::setIV() 390 * @see self::disableContinuousBuffer() 391 * @var bool 392 * @access private 393 */ 394 protected $changed = true; 395 396 /** 397 * Does Eval engie need to be (re)initialized? 398 * 399 * @see self::setup() 400 * @var bool 401 * @access private 402 */ 403 protected $nonIVChanged = true; 404 405 /** 406 * Padding status 407 * 408 * @see self::enablePadding() 409 * @var bool 410 * @access private 411 */ 412 private $padding = true; 413 414 /** 415 * Is the mode one that is paddable? 416 * 417 * @see self::__construct() 418 * @var bool 419 * @access private 420 */ 421 private $paddable = false; 422 423 /** 424 * Holds which crypt engine internaly should be use, 425 * which will be determined automatically on __construct() 426 * 427 * Currently available $engines are: 428 * - self::ENGINE_LIBSODIUM (very fast, php-extension: libsodium, extension_loaded('libsodium') required) 429 * - self::ENGINE_OPENSSL_GCM (very fast, php-extension: openssl, extension_loaded('openssl') required) 430 * - self::ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required) 431 * - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required) 432 * - self::ENGINE_EVAL (medium, pure php-engine, no php-extension required) 433 * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required) 434 * 435 * @see self::setEngine() 436 * @see self::encrypt() 437 * @see self::decrypt() 438 * @var int 439 * @access private 440 */ 441 protected $engine; 442 443 /** 444 * Holds the preferred crypt engine 445 * 446 * @see self::setEngine() 447 * @see self::setPreferredEngine() 448 * @var int 449 * @access private 450 */ 451 private $preferredEngine; 452 453 /** 454 * The mcrypt specific name of the cipher 455 * 456 * Only used if $engine == self::ENGINE_MCRYPT 457 * 458 * @link http://www.php.net/mcrypt_module_open 459 * @link http://www.php.net/mcrypt_list_algorithms 460 * @see self::setupMcrypt() 461 * @var string 462 * @access private 463 */ 464 protected $cipher_name_mcrypt; 465 466 /** 467 * The openssl specific name of the cipher 468 * 469 * Only used if $engine == self::ENGINE_OPENSSL 470 * 471 * @link http://www.php.net/openssl-get-cipher-methods 472 * @var string 473 * @access private 474 */ 475 protected $cipher_name_openssl; 476 477 /** 478 * The openssl specific name of the cipher in ECB mode 479 * 480 * If OpenSSL does not support the mode we're trying to use (CTR) 481 * it can still be emulated with ECB mode. 482 * 483 * @link http://www.php.net/openssl-get-cipher-methods 484 * @var string 485 * @access private 486 */ 487 protected $cipher_name_openssl_ecb; 488 489 /** 490 * The default salt used by setPassword() 491 * 492 * @see self::setPassword() 493 * @var string 494 * @access private 495 */ 496 private $password_default_salt = 'phpseclib/salt'; 497 498 /** 499 * The name of the performance-optimized callback function 500 * 501 * Used by encrypt() / decrypt() 502 * only if $engine == self::ENGINE_INTERNAL 503 * 504 * @see self::encrypt() 505 * @see self::decrypt() 506 * @see self::setupInlineCrypt() 507 * @var Callback 508 * @access private 509 */ 510 protected $inline_crypt; 511 512 /** 513 * If OpenSSL can be used in ECB but not in CTR we can emulate CTR 514 * 515 * @see self::openssl_ctr_process() 516 * @var bool 517 * @access private 518 */ 519 private $openssl_emulate_ctr = false; 520 521 /** 522 * Don't truncate / null pad key 523 * 524 * @see self::clearBuffers() 525 * @var bool 526 * @access private 527 */ 528 private $skip_key_adjustment = false; 529 530 /** 531 * Has the key length explicitly been set or should it be derived from the key, itself? 532 * 533 * @see self::setKeyLength() 534 * @var bool 535 * @access private 536 */ 537 protected $explicit_key_length = false; 538 539 /** 540 * Hash subkey for GHASH 541 * 542 * @see self::setupGCM() 543 * @see self::ghash() 544 * @var BinaryField\Integer 545 * @access private 546 */ 547 private $h; 548 549 /** 550 * Additional authenticated data 551 * 552 * @var string 553 * @access private 554 */ 555 protected $aad = ''; 556 557 /** 558 * Authentication Tag produced after a round of encryption 559 * 560 * @var string 561 * @access private 562 */ 563 protected $newtag = false; 564 565 /** 566 * Authentication Tag to be verified during decryption 567 * 568 * @var string 569 * @access private 570 */ 571 protected $oldtag = false; 572 573 /** 574 * GCM Binary Field 575 * 576 * @see self::__construct() 577 * @see self::ghash() 578 * @var BinaryField 579 * @access private 580 */ 581 private static $gcmField; 582 583 /** 584 * Poly1305 Prime Field 585 * 586 * @see self::enablePoly1305() 587 * @see self::poly1305() 588 * @var PrimeField 589 * @access private 590 */ 591 private static $poly1305Field; 592 593 /** 594 * Poly1305 Key 595 * 596 * @see self::setPoly1305Key() 597 * @see self::poly1305() 598 * @var string 599 * @access private 600 */ 601 protected $poly1305Key; 602 603 /** 604 * Poly1305 Flag 605 * 606 * @see self::setPoly1305Key() 607 * @see self::enablePoly1305() 608 * @var boolean 609 * @access private 610 */ 611 protected $usePoly1305 = false; 612 613 /** 614 * The Original Initialization Vector 615 * 616 * GCM uses the nonce to build the IV but we want to be able to distinguish between nonce-derived 617 * IV's and user-set IV's 618 * 619 * @see self::setIV() 620 * @var string 621 * @access private 622 */ 623 private $origIV = false; 624 625 /** 626 * Nonce 627 * 628 * Only used with GCM. We could re-use setIV() but nonce's can be of a different length and 629 * toggling between GCM and other modes could be more complicated if we re-used setIV() 630 * 631 * @see self::setNonce() 632 * @var string 633 * @access private 634 */ 635 protected $nonce = false; 636 637 /** 638 * Default Constructor. 639 * 640 * $mode could be: 641 * 642 * - ecb 643 * 644 * - cbc 645 * 646 * - ctr 647 * 648 * - cfb 649 * 650 * - cfb8 651 * 652 * - ofb 653 * 654 * - ofb8 655 * 656 * - gcm 657 * 658 * @param string $mode 659 * @access public 660 * @throws BadModeException if an invalid / unsupported mode is provided 661 */ 662 public function __construct($mode) 663 { 664 $mode = strtolower($mode); 665 // necessary because of 5.6 compatibility; we can't do isset(self::MODE_MAP[$mode]) in 5.6 666 $map = self::MODE_MAP; 667 if (!isset($map[$mode])) { 668 throw new BadModeException('No valid mode has been specified'); 669 } 670 671 $mode = self::MODE_MAP[$mode]; 672 673 // $mode dependent settings 674 switch ($mode) { 675 case self::MODE_ECB: 676 case self::MODE_CBC: 677 $this->paddable = true; 678 break; 679 case self::MODE_CTR: 680 case self::MODE_CFB: 681 case self::MODE_CFB8: 682 case self::MODE_OFB: 683 case self::MODE_OFB8: 684 case self::MODE_STREAM: 685 $this->paddable = false; 686 break; 687 case self::MODE_GCM: 688 if ($this->block_size != 16) { 689 throw new BadModeException('GCM is only valid for block ciphers with a block size of 128 bits'); 690 } 691 if (!isset(self::$gcmField)) { 692 self::$gcmField = new BinaryField(128, 7, 2, 1, 0); 693 } 694 $this->paddable = false; 695 break; 696 default: 697 throw new BadModeException('No valid mode has been specified'); 698 } 699 700 $this->mode = $mode; 701 } 702 703 /** 704 * Sets the initialization vector. 705 * 706 * setIV() is not required when ecb or gcm modes are being used. 707 * 708 * {@internal Can be overwritten by a sub class, but does not have to be} 709 * 710 * @access public 711 * @param string $iv 712 * @throws \LengthException if the IV length isn't equal to the block size 713 * @throws \BadMethodCallException if an IV is provided when one shouldn't be 714 */ 715 public function setIV($iv) 716 { 717 if ($this->mode == self::MODE_ECB) { 718 throw new \BadMethodCallException('This mode does not require an IV.'); 719 } 720 721 if ($this->mode == self::MODE_GCM) { 722 throw new \BadMethodCallException('Use setNonce instead'); 723 } 724 725 if (!$this->usesIV()) { 726 throw new \BadMethodCallException('This algorithm does not use an IV.'); 727 } 728 729 if (strlen($iv) != $this->block_size) { 730 throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required'); 731 } 732 733 $this->iv = $this->origIV = $iv; 734 $this->changed = true; 735 } 736 737 /** 738 * Enables Poly1305 mode. 739 * 740 * Once enabled Poly1305 cannot be disabled. 741 * 742 * @access public 743 * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode 744 */ 745 public function enablePoly1305() 746 { 747 if ($this->mode == self::MODE_GCM) { 748 throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode'); 749 } 750 751 $this->usePoly1305 = true; 752 } 753 754 /** 755 * Enables Poly1305 mode. 756 * 757 * Once enabled Poly1305 cannot be disabled. If $key is not passed then an attempt to call createPoly1305Key 758 * will be made. 759 * 760 * @access public 761 * @param string $key optional 762 * @throws \LengthException if the key isn't long enough 763 * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode 764 */ 765 public function setPoly1305Key($key = null) 766 { 767 if ($this->mode == self::MODE_GCM) { 768 throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode'); 769 } 770 771 if (!is_string($key) || strlen($key) != 32) { 772 throw new \LengthException('The Poly1305 key must be 32 bytes long (256 bits)'); 773 } 774 775 if (!isset(self::$poly1305Field)) { 776 // 2^130-5 777 self::$poly1305Field = new PrimeField(new BigInteger('3fffffffffffffffffffffffffffffffb', 16)); 778 } 779 780 $this->poly1305Key = $key; 781 $this->usePoly1305 = true; 782 } 783 784 /** 785 * Sets the nonce. 786 * 787 * setNonce() is only required when gcm is used 788 * 789 * @access public 790 * @param string $nonce 791 * @throws \BadMethodCallException if an nonce is provided when one shouldn't be 792 */ 793 public function setNonce($nonce) 794 { 795 if ($this->mode != self::MODE_GCM) { 796 throw new \BadMethodCallException('Nonces are only used in GCM mode.'); 797 } 798 799 $this->nonce = $nonce; 800 $this->setEngine(); 801 } 802 803 /** 804 * Sets additional authenticated data 805 * 806 * setAAD() is only used by gcm or in poly1305 mode 807 * 808 * @access public 809 * @param string $aad 810 * @throws \BadMethodCallException if mode isn't GCM or if poly1305 isn't being utilized 811 */ 812 public function setAAD($aad) 813 { 814 if ($this->mode != self::MODE_GCM && !$this->usePoly1305) { 815 throw new \BadMethodCallException('Additional authenticated data is only utilized in GCM mode or with Poly1305'); 816 } 817 818 $this->aad = $aad; 819 } 820 821 /** 822 * Returns whether or not the algorithm uses an IV 823 * 824 * @access public 825 * @return bool 826 */ 827 public function usesIV() 828 { 829 return $this->mode != self::MODE_GCM && $this->mode != self::MODE_ECB; 830 } 831 832 /** 833 * Returns whether or not the algorithm uses a nonce 834 * 835 * @access public 836 * @return bool 837 */ 838 public function usesNonce() 839 { 840 return $this->mode == self::MODE_GCM; 841 } 842 843 /** 844 * Returns the current key length in bits 845 * 846 * @access public 847 * @return int 848 */ 849 public function getKeyLength() 850 { 851 return $this->key_length << 3; 852 } 853 854 /** 855 * Returns the current block length in bits 856 * 857 * @access public 858 * @return int 859 */ 860 public function getBlockLength() 861 { 862 return $this->block_size << 3; 863 } 864 865 /** 866 * Returns the current block length in bytes 867 * 868 * @access public 869 * @return int 870 */ 871 public function getBlockLengthInBytes() 872 { 873 return $this->block_size; 874 } 875 876 /** 877 * Sets the key length. 878 * 879 * Keys with explicitly set lengths need to be treated accordingly 880 * 881 * @access public 882 * @param int $length 883 */ 884 public function setKeyLength($length) 885 { 886 $this->explicit_key_length = $length >> 3; 887 888 if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) { 889 $this->key = false; 890 throw new InconsistentSetupException('Key has already been set and is not ' . $this->explicit_key_length . ' bytes long'); 891 } 892 } 893 894 /** 895 * Sets the key. 896 * 897 * The min/max length(s) of the key depends on the cipher which is used. 898 * If the key not fits the length(s) of the cipher it will paded with null bytes 899 * up to the closest valid key length. If the key is more than max length, 900 * we trim the excess bits. 901 * 902 * If the key is not explicitly set, it'll be assumed to be all null bytes. 903 * 904 * {@internal Could, but not must, extend by the child Crypt_* class} 905 * 906 * @access public 907 * @param string $key 908 */ 909 public function setKey($key) 910 { 911 if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) { 912 throw new InconsistentSetupException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes'); 913 } 914 915 $this->key = $key; 916 $this->key_length = strlen($key); 917 $this->setEngine(); 918 } 919 920 /** 921 * Sets the password. 922 * 923 * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: 924 * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1: 925 * $hash, $salt, $count, $dkLen 926 * 927 * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php 928 * 929 * {@internal Could, but not must, extend by the child Crypt_* class} 930 * 931 * @see Crypt/Hash.php 932 * @param string $password 933 * @param string $method 934 * @param string[] ...$func_args 935 * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length 936 * @return bool 937 * @access public 938 */ 939 public function setPassword($password, $method = 'pbkdf2', ...$func_args) 940 { 941 $key = ''; 942 943 $method = strtolower($method); 944 switch ($method) { 945 case 'pkcs12': // from https://tools.ietf.org/html/rfc7292#appendix-B.2 946 case 'pbkdf1': 947 case 'pbkdf2': 948 // Hash function 949 $hash = isset($func_args[0]) ? strtolower($func_args[0]) : 'sha1'; 950 $hashObj = new Hash(); 951 $hashObj->setHash($hash); 952 953 // WPA and WPA2 use the SSID as the salt 954 $salt = isset($func_args[1]) ? $func_args[1] : $this->password_default_salt; 955 956 // RFC2898#section-4.2 uses 1,000 iterations by default 957 // WPA and WPA2 use 4,096. 958 $count = isset($func_args[2]) ? $func_args[2] : 1000; 959 960 // Keylength 961 if (isset($func_args[3])) { 962 if ($func_args[3] <= 0) { 963 throw new \LengthException('Derived key length cannot be longer 0 or less'); 964 } 965 $dkLen = $func_args[3]; 966 } else { 967 $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length; 968 $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length; 969 } 970 971 switch (true) { 972 case $method == 'pkcs12': 973 /* 974 In this specification, however, all passwords are created from 975 BMPStrings with a NULL terminator. This means that each character in 976 the original BMPString is encoded in 2 bytes in big-endian format 977 (most-significant byte first). There are no Unicode byte order 978 marks. The 2 bytes produced from the last character in the BMPString 979 are followed by 2 additional bytes with the value 0x00. 980 981 -- https://tools.ietf.org/html/rfc7292#appendix-B.1 982 */ 983 $password = "\0" . chunk_split($password, 1, "\0") . "\0"; 984 985 /* 986 This standard specifies 3 different values for the ID byte mentioned 987 above: 988 989 1. If ID=1, then the pseudorandom bits being produced are to be used 990 as key material for performing encryption or decryption. 991 992 2. If ID=2, then the pseudorandom bits being produced are to be used 993 as an IV (Initial Value) for encryption or decryption. 994 995 3. If ID=3, then the pseudorandom bits being produced are to be used 996 as an integrity key for MACing. 997 */ 998 // Construct a string, D (the "diversifier"), by concatenating v/8 999 // copies of ID. 1000 $blockLength = $hashObj->getBlockLengthInBytes(); 1001 $d1 = str_repeat(chr(1), $blockLength); 1002 $d2 = str_repeat(chr(2), $blockLength); 1003 $s = ''; 1004 if (strlen($salt)) { 1005 while (strlen($s) < $blockLength) { 1006 $s .= $salt; 1007 } 1008 } 1009 $s = substr($s, 0, $blockLength); 1010 1011 $p = ''; 1012 if (strlen($password)) { 1013 while (strlen($p) < $blockLength) { 1014 $p .= $password; 1015 } 1016 } 1017 $p = substr($p, 0, $blockLength); 1018 1019 $i = $s . $p; 1020 1021 $this->setKey(self::pkcs12helper($dkLen, $hashObj, $i, $d1, $count)); 1022 if ($this->usesIV()) { 1023 $this->setIV(self::pkcs12helper($this->block_size, $hashObj, $i, $d2, $count)); 1024 } 1025 1026 return true; 1027 case $method == 'pbkdf1': 1028 if ($dkLen > $hashObj->getLengthInBytes()) { 1029 throw new \LengthException('Derived key length cannot be longer than the hash length'); 1030 } 1031 $t = $password . $salt; 1032 for ($i = 0; $i < $count; ++$i) { 1033 $t = $hashObj->hash($t); 1034 } 1035 $key = substr($t, 0, $dkLen); 1036 1037 $this->setKey(substr($key, 0, $dkLen >> 1)); 1038 if ($this->usesIV()) { 1039 $this->setIV(substr($key, $dkLen >> 1)); 1040 } 1041 1042 return true; 1043 case !in_array($hash, hash_algos()): 1044 $i = 1; 1045 $hashObj->setKey($password); 1046 while (strlen($key) < $dkLen) { 1047 $f = $u = $hashObj->hash($salt . pack('N', $i++)); 1048 for ($j = 2; $j <= $count; ++$j) { 1049 $u = $hashObj->hash($u); 1050 $f ^= $u; 1051 } 1052 $key .= $f; 1053 } 1054 $key = substr($key, 0, $dkLen); 1055 break; 1056 default: 1057 $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true); 1058 } 1059 break; 1060 default: 1061 throw new UnsupportedAlgorithmException($method . ' is not a supported password hashing method'); 1062 } 1063 1064 $this->setKey($key); 1065 1066 return true; 1067 } 1068 1069 /** 1070 * PKCS#12 KDF Helper Function 1071 * 1072 * As discussed here: 1073 * 1074 * {@link https://tools.ietf.org/html/rfc7292#appendix-B} 1075 * 1076 * @see self::setPassword() 1077 * @access private 1078 * @param int $n 1079 * @param \phpseclib3\Crypt\Hash $hashObj 1080 * @param string $i 1081 * @param string $d 1082 * @param int $count 1083 * @return string $a 1084 */ 1085 private static function pkcs12helper($n, $hashObj, $i, $d, $count) 1086 { 1087 static $one; 1088 if (!isset($one)) { 1089 $one = new BigInteger(1); 1090 } 1091 1092 $blockLength = $hashObj->getBlockLength() >> 3; 1093 1094 $c = ceil($n / $hashObj->getLengthInBytes()); 1095 $a = ''; 1096 for ($j = 1; $j <= $c; $j++) { 1097 $ai = $d . $i; 1098 for ($k = 0; $k < $count; $k++) { 1099 $ai = $hashObj->hash($ai); 1100 } 1101 $b = ''; 1102 while (strlen($b) < $blockLength) { 1103 $b .= $ai; 1104 } 1105 $b = substr($b, 0, $blockLength); 1106 $b = new BigInteger($b, 256); 1107 $newi = ''; 1108 for ($k = 0; $k < strlen($i); $k += $blockLength) { 1109 $temp = substr($i, $k, $blockLength); 1110 $temp = new BigInteger($temp, 256); 1111 $temp->setPrecision($blockLength << 3); 1112 $temp = $temp->add($b); 1113 $temp = $temp->add($one); 1114 $newi .= $temp->toBytes(false); 1115 } 1116 $i = $newi; 1117 $a .= $ai; 1118 } 1119 1120 return substr($a, 0, $n); 1121 } 1122 1123 /** 1124 * Encrypts a message. 1125 * 1126 * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher 1127 * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's 1128 * necessary are discussed in the following 1129 * URL: 1130 * 1131 * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html} 1132 * 1133 * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. 1134 * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that 1135 * length. 1136 * 1137 * {@internal Could, but not must, extend by the child Crypt_* class} 1138 * 1139 * @see self::decrypt() 1140 * @access public 1141 * @param string $plaintext 1142 * @return string $ciphertext 1143 */ 1144 public function encrypt($plaintext) 1145 { 1146 if ($this->paddable) { 1147 $plaintext = $this->pad($plaintext); 1148 } 1149 1150 $this->setup(); 1151 1152 if ($this->mode == self::MODE_GCM) { 1153 $oldIV = $this->iv; 1154 Strings::increment_str($this->iv); 1155 $cipher = new static('ctr'); 1156 $cipher->setKey($this->key); 1157 $cipher->setIV($this->iv); 1158 $ciphertext = $cipher->encrypt($plaintext); 1159 1160 $s = $this->ghash( 1161 self::nullPad128($this->aad) . 1162 self::nullPad128($ciphertext) . 1163 self::len64($this->aad) . 1164 self::len64($ciphertext) 1165 ); 1166 $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV; 1167 $this->newtag = $cipher->encrypt($s); 1168 return $ciphertext; 1169 } 1170 1171 if (isset($this->poly1305Key)) { 1172 $cipher = clone $this; 1173 unset($cipher->poly1305Key); 1174 $this->usePoly1305 = false; 1175 $ciphertext = $cipher->encrypt($plaintext); 1176 $this->newtag = $this->poly1305($ciphertext); 1177 return $ciphertext; 1178 } 1179 1180 if ($this->engine === self::ENGINE_OPENSSL) { 1181 switch ($this->mode) { 1182 case self::MODE_STREAM: 1183 return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 1184 case self::MODE_ECB: 1185 return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 1186 case self::MODE_CBC: 1187 $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV); 1188 if ($this->continuousBuffer) { 1189 $this->encryptIV = substr($result, -$this->block_size); 1190 } 1191 return $result; 1192 case self::MODE_CTR: 1193 return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer); 1194 case self::MODE_CFB: 1195 // cfb loosely routines inspired by openssl's: 1196 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} 1197 $ciphertext = ''; 1198 if ($this->continuousBuffer) { 1199 $iv = &$this->encryptIV; 1200 $pos = &$this->enbuffer['pos']; 1201 } else { 1202 $iv = $this->encryptIV; 1203 $pos = 0; 1204 } 1205 $len = strlen($plaintext); 1206 $i = 0; 1207 if ($pos) { 1208 $orig_pos = $pos; 1209 $max = $this->block_size - $pos; 1210 if ($len >= $max) { 1211 $i = $max; 1212 $len -= $max; 1213 $pos = 0; 1214 } else { 1215 $i = $len; 1216 $pos += $len; 1217 $len = 0; 1218 } 1219 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 1220 $ciphertext = substr($iv, $orig_pos) ^ $plaintext; 1221 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); 1222 $plaintext = substr($plaintext, $i); 1223 } 1224 1225 $overflow = $len % $this->block_size; 1226 1227 if ($overflow) { 1228 $ciphertext .= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); 1229 $iv = Strings::pop($ciphertext, $this->block_size); 1230 1231 $size = $len - $overflow; 1232 $block = $iv ^ substr($plaintext, -$overflow); 1233 $iv = substr_replace($iv, $block, 0, $overflow); 1234 $ciphertext .= $block; 1235 $pos = $overflow; 1236 } elseif ($len) { 1237 $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); 1238 $iv = substr($ciphertext, -$this->block_size); 1239 } 1240 1241 return $ciphertext; 1242 case self::MODE_CFB8: 1243 $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV); 1244 if ($this->continuousBuffer) { 1245 if (($len = strlen($ciphertext)) >= $this->block_size) { 1246 $this->encryptIV = substr($ciphertext, -$this->block_size); 1247 } else { 1248 $this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len); 1249 } 1250 } 1251 return $ciphertext; 1252 case self::MODE_OFB8: 1253 $ciphertext = ''; 1254 $len = strlen($plaintext); 1255 $iv = $this->encryptIV; 1256 1257 for ($i = 0; $i < $len; ++$i) { 1258 $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV); 1259 $ciphertext .= $plaintext[$i] ^ $xor; 1260 $iv = substr($iv, 1) . $xor[0]; 1261 } 1262 1263 if ($this->continuousBuffer) { 1264 $this->encryptIV = $iv; 1265 } 1266 break; 1267 case self::MODE_OFB: 1268 return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); 1269 } 1270 } 1271 1272 if ($this->engine === self::ENGINE_MCRYPT) { 1273 set_error_handler(function () { 1274 }); 1275 if ($this->enchanged) { 1276 mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV)); 1277 $this->enchanged = false; 1278 } 1279 1280 // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} 1281 // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's 1282 // rewritten CFB implementation the above outputs the same thing twice. 1283 if ($this->mode == self::MODE_CFB && $this->continuousBuffer) { 1284 $block_size = $this->block_size; 1285 $iv = &$this->encryptIV; 1286 $pos = &$this->enbuffer['pos']; 1287 $len = strlen($plaintext); 1288 $ciphertext = ''; 1289 $i = 0; 1290 if ($pos) { 1291 $orig_pos = $pos; 1292 $max = $block_size - $pos; 1293 if ($len >= $max) { 1294 $i = $max; 1295 $len -= $max; 1296 $pos = 0; 1297 } else { 1298 $i = $len; 1299 $pos += $len; 1300 $len = 0; 1301 } 1302 $ciphertext = substr($iv, $orig_pos) ^ $plaintext; 1303 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); 1304 $this->enbuffer['enmcrypt_init'] = true; 1305 } 1306 if ($len >= $block_size) { 1307 if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { 1308 if ($this->enbuffer['enmcrypt_init'] === true) { 1309 mcrypt_generic_init($this->enmcrypt, $this->key, $iv); 1310 $this->enbuffer['enmcrypt_init'] = false; 1311 } 1312 $ciphertext .= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); 1313 $iv = substr($ciphertext, -$block_size); 1314 $len %= $block_size; 1315 } else { 1316 while ($len >= $block_size) { 1317 $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); 1318 $ciphertext .= $iv; 1319 $len -= $block_size; 1320 $i += $block_size; 1321 } 1322 } 1323 } 1324 1325 if ($len) { 1326 $iv = mcrypt_generic($this->ecb, $iv); 1327 $block = $iv ^ substr($plaintext, -$len); 1328 $iv = substr_replace($iv, $block, 0, $len); 1329 $ciphertext .= $block; 1330 $pos = $len; 1331 } 1332 1333 restore_error_handler(); 1334 1335 return $ciphertext; 1336 } 1337 1338 $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); 1339 1340 if (!$this->continuousBuffer) { 1341 mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV)); 1342 } 1343 1344 restore_error_handler(); 1345 1346 return $ciphertext; 1347 } 1348 1349 if ($this->engine === self::ENGINE_EVAL) { 1350 $inline = $this->inline_crypt; 1351 return $inline('encrypt', $plaintext); 1352 } 1353 1354 $buffer = &$this->enbuffer; 1355 $block_size = $this->block_size; 1356 $ciphertext = ''; 1357 switch ($this->mode) { 1358 case self::MODE_ECB: 1359 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1360 $ciphertext .= $this->encryptBlock(substr($plaintext, $i, $block_size)); 1361 } 1362 break; 1363 case self::MODE_CBC: 1364 $xor = $this->encryptIV; 1365 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1366 $block = substr($plaintext, $i, $block_size); 1367 $block = $this->encryptBlock($block ^ $xor); 1368 $xor = $block; 1369 $ciphertext .= $block; 1370 } 1371 if ($this->continuousBuffer) { 1372 $this->encryptIV = $xor; 1373 } 1374 break; 1375 case self::MODE_CTR: 1376 $xor = $this->encryptIV; 1377 if (strlen($buffer['ciphertext'])) { 1378 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1379 $block = substr($plaintext, $i, $block_size); 1380 if (strlen($block) > strlen($buffer['ciphertext'])) { 1381 $buffer['ciphertext'] .= $this->encryptBlock($xor); 1382 Strings::increment_str($xor); 1383 } 1384 $key = Strings::shift($buffer['ciphertext'], $block_size); 1385 $ciphertext .= $block ^ $key; 1386 } 1387 } else { 1388 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1389 $block = substr($plaintext, $i, $block_size); 1390 $key = $this->encryptBlock($xor); 1391 Strings::increment_str($xor); 1392 $ciphertext .= $block ^ $key; 1393 } 1394 } 1395 if ($this->continuousBuffer) { 1396 $this->encryptIV = $xor; 1397 if ($start = strlen($plaintext) % $block_size) { 1398 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; 1399 } 1400 } 1401 break; 1402 case self::MODE_CFB: 1403 // cfb loosely routines inspired by openssl's: 1404 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} 1405 if ($this->continuousBuffer) { 1406 $iv = &$this->encryptIV; 1407 $pos = &$buffer['pos']; 1408 } else { 1409 $iv = $this->encryptIV; 1410 $pos = 0; 1411 } 1412 $len = strlen($plaintext); 1413 $i = 0; 1414 if ($pos) { 1415 $orig_pos = $pos; 1416 $max = $block_size - $pos; 1417 if ($len >= $max) { 1418 $i = $max; 1419 $len -= $max; 1420 $pos = 0; 1421 } else { 1422 $i = $len; 1423 $pos += $len; 1424 $len = 0; 1425 } 1426 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 1427 $ciphertext = substr($iv, $orig_pos) ^ $plaintext; 1428 $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); 1429 } 1430 while ($len >= $block_size) { 1431 $iv = $this->encryptBlock($iv) ^ substr($plaintext, $i, $block_size); 1432 $ciphertext .= $iv; 1433 $len -= $block_size; 1434 $i += $block_size; 1435 } 1436 if ($len) { 1437 $iv = $this->encryptBlock($iv); 1438 $block = $iv ^ substr($plaintext, $i); 1439 $iv = substr_replace($iv, $block, 0, $len); 1440 $ciphertext .= $block; 1441 $pos = $len; 1442 } 1443 break; 1444 case self::MODE_CFB8: 1445 $ciphertext = ''; 1446 $len = strlen($plaintext); 1447 $iv = $this->encryptIV; 1448 1449 for ($i = 0; $i < $len; ++$i) { 1450 $ciphertext .= ($c = $plaintext[$i] ^ $this->encryptBlock($iv)); 1451 $iv = substr($iv, 1) . $c; 1452 } 1453 1454 if ($this->continuousBuffer) { 1455 if ($len >= $block_size) { 1456 $this->encryptIV = substr($ciphertext, -$block_size); 1457 } else { 1458 $this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len); 1459 } 1460 } 1461 break; 1462 case self::MODE_OFB8: 1463 $ciphertext = ''; 1464 $len = strlen($plaintext); 1465 $iv = $this->encryptIV; 1466 1467 for ($i = 0; $i < $len; ++$i) { 1468 $xor = $this->encryptBlock($iv); 1469 $ciphertext .= $plaintext[$i] ^ $xor; 1470 $iv = substr($iv, 1) . $xor[0]; 1471 } 1472 1473 if ($this->continuousBuffer) { 1474 $this->encryptIV = $iv; 1475 } 1476 break; 1477 case self::MODE_OFB: 1478 $xor = $this->encryptIV; 1479 if (strlen($buffer['xor'])) { 1480 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1481 $block = substr($plaintext, $i, $block_size); 1482 if (strlen($block) > strlen($buffer['xor'])) { 1483 $xor = $this->encryptBlock($xor); 1484 $buffer['xor'] .= $xor; 1485 } 1486 $key = Strings::shift($buffer['xor'], $block_size); 1487 $ciphertext .= $block ^ $key; 1488 } 1489 } else { 1490 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1491 $xor = $this->encryptBlock($xor); 1492 $ciphertext .= substr($plaintext, $i, $block_size) ^ $xor; 1493 } 1494 $key = $xor; 1495 } 1496 if ($this->continuousBuffer) { 1497 $this->encryptIV = $xor; 1498 if ($start = strlen($plaintext) % $block_size) { 1499 $buffer['xor'] = substr($key, $start) . $buffer['xor']; 1500 } 1501 } 1502 break; 1503 case self::MODE_STREAM: 1504 $ciphertext = $this->encryptBlock($plaintext); 1505 break; 1506 } 1507 1508 return $ciphertext; 1509 } 1510 1511 /** 1512 * Decrypts a message. 1513 * 1514 * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until 1515 * it is. 1516 * 1517 * {@internal Could, but not must, extend by the child Crypt_* class} 1518 * 1519 * @see self::encrypt() 1520 * @access public 1521 * @param string $ciphertext 1522 * @return string $plaintext 1523 * @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size 1524 */ 1525 public function decrypt($ciphertext) 1526 { 1527 if ($this->paddable && strlen($ciphertext) % $this->block_size) { 1528 throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')'); 1529 } 1530 $this->setup(); 1531 1532 if ($this->mode == self::MODE_GCM || isset($this->poly1305Key)) { 1533 if ($this->oldtag === false) { 1534 throw new InsufficientSetupException('Authentication Tag has not been set'); 1535 } 1536 1537 if (isset($this->poly1305Key)) { 1538 $newtag = $this->poly1305($ciphertext); 1539 } else { 1540 $oldIV = $this->iv; 1541 Strings::increment_str($this->iv); 1542 $cipher = new static('ctr'); 1543 $cipher->setKey($this->key); 1544 $cipher->setIV($this->iv); 1545 $plaintext = $cipher->decrypt($ciphertext); 1546 1547 $s = $this->ghash( 1548 self::nullPad128($this->aad) . 1549 self::nullPad128($ciphertext) . 1550 self::len64($this->aad) . 1551 self::len64($ciphertext) 1552 ); 1553 $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV; 1554 $newtag = $cipher->encrypt($s); 1555 } 1556 if ($this->oldtag != substr($newtag, 0, strlen($newtag))) { 1557 $cipher = clone $this; 1558 unset($cipher->poly1305Key); 1559 $this->usePoly1305 = false; 1560 $plaintext = $cipher->decrypt($ciphertext); 1561 $this->oldtag = false; 1562 throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match'); 1563 } 1564 $this->oldtag = false; 1565 return $plaintext; 1566 } 1567 1568 if ($this->engine === self::ENGINE_OPENSSL) { 1569 switch ($this->mode) { 1570 case self::MODE_STREAM: 1571 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 1572 break; 1573 case self::MODE_ECB: 1574 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 1575 break; 1576 case self::MODE_CBC: 1577 $offset = $this->block_size; 1578 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV); 1579 if ($this->continuousBuffer) { 1580 $this->decryptIV = substr($ciphertext, -$offset, $this->block_size); 1581 } 1582 break; 1583 case self::MODE_CTR: 1584 $plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer); 1585 break; 1586 case self::MODE_CFB: 1587 // cfb loosely routines inspired by openssl's: 1588 // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} 1589 $plaintext = ''; 1590 if ($this->continuousBuffer) { 1591 $iv = &$this->decryptIV; 1592 $pos = &$this->buffer['pos']; 1593 } else { 1594 $iv = $this->decryptIV; 1595 $pos = 0; 1596 } 1597 $len = strlen($ciphertext); 1598 $i = 0; 1599 if ($pos) { 1600 $orig_pos = $pos; 1601 $max = $this->block_size - $pos; 1602 if ($len >= $max) { 1603 $i = $max; 1604 $len -= $max; 1605 $pos = 0; 1606 } else { 1607 $i = $len; 1608 $pos += $len; 1609 $len = 0; 1610 } 1611 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize 1612 $plaintext = substr($iv, $orig_pos) ^ $ciphertext; 1613 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); 1614 $ciphertext = substr($ciphertext, $i); 1615 } 1616 $overflow = $len % $this->block_size; 1617 if ($overflow) { 1618 $plaintext .= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); 1619 if ($len - $overflow) { 1620 $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow); 1621 } 1622 $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); 1623 $plaintext .= $iv ^ substr($ciphertext, -$overflow); 1624 $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow); 1625 $pos = $overflow; 1626 } elseif ($len) { 1627 $plaintext .= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); 1628 $iv = substr($ciphertext, -$this->block_size); 1629 } 1630 break; 1631 case self::MODE_CFB8: 1632 $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV); 1633 if ($this->continuousBuffer) { 1634 if (($len = strlen($ciphertext)) >= $this->block_size) { 1635 $this->decryptIV = substr($ciphertext, -$this->block_size); 1636 } else { 1637 $this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len); 1638 } 1639 } 1640 break; 1641 case self::MODE_OFB8: 1642 $plaintext = ''; 1643 $len = strlen($ciphertext); 1644 $iv = $this->decryptIV; 1645 1646 for ($i = 0; $i < $len; ++$i) { 1647 $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV); 1648 $plaintext .= $ciphertext[$i] ^ $xor; 1649 $iv = substr($iv, 1) . $xor[0]; 1650 } 1651 1652 if ($this->continuousBuffer) { 1653 $this->decryptIV = $iv; 1654 } 1655 break; 1656 case self::MODE_OFB: 1657 $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer); 1658 } 1659 1660 return $this->paddable ? $this->unpad($plaintext) : $plaintext; 1661 } 1662 1663 if ($this->engine === self::ENGINE_MCRYPT) { 1664 set_error_handler(function () { 1665 }); 1666 $block_size = $this->block_size; 1667 if ($this->dechanged) { 1668 mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV)); 1669 $this->dechanged = false; 1670 } 1671 1672 if ($this->mode == self::MODE_CFB && $this->continuousBuffer) { 1673 $iv = &$this->decryptIV; 1674 $pos = &$this->debuffer['pos']; 1675 $len = strlen($ciphertext); 1676 $plaintext = ''; 1677 $i = 0; 1678 if ($pos) { 1679 $orig_pos = $pos; 1680 $max = $block_size - $pos; 1681 if ($len >= $max) { 1682 $i = $max; 1683 $len -= $max; 1684 $pos = 0; 1685 } else { 1686 $i = $len; 1687 $pos += $len; 1688 $len = 0; 1689 } 1690 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 1691 $plaintext = substr($iv, $orig_pos) ^ $ciphertext; 1692 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); 1693 } 1694 if ($len >= $block_size) { 1695 $cb = substr($ciphertext, $i, $len - $len % $block_size); 1696 $plaintext .= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; 1697 $iv = substr($cb, -$block_size); 1698 $len %= $block_size; 1699 } 1700 if ($len) { 1701 $iv = mcrypt_generic($this->ecb, $iv); 1702 $plaintext .= $iv ^ substr($ciphertext, -$len); 1703 $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); 1704 $pos = $len; 1705 } 1706 1707 restore_error_handler(); 1708 1709 return $plaintext; 1710 } 1711 1712 $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); 1713 1714 if (!$this->continuousBuffer) { 1715 mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV)); 1716 } 1717 1718 restore_error_handler(); 1719 1720 return $this->paddable ? $this->unpad($plaintext) : $plaintext; 1721 } 1722 1723 if ($this->engine === self::ENGINE_EVAL) { 1724 $inline = $this->inline_crypt; 1725 return $inline('decrypt', $ciphertext); 1726 } 1727 1728 $block_size = $this->block_size; 1729 1730 $buffer = &$this->debuffer; 1731 $plaintext = ''; 1732 switch ($this->mode) { 1733 case self::MODE_ECB: 1734 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { 1735 $plaintext .= $this->decryptBlock(substr($ciphertext, $i, $block_size)); 1736 } 1737 break; 1738 case self::MODE_CBC: 1739 $xor = $this->decryptIV; 1740 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { 1741 $block = substr($ciphertext, $i, $block_size); 1742 $plaintext .= $this->decryptBlock($block) ^ $xor; 1743 $xor = $block; 1744 } 1745 if ($this->continuousBuffer) { 1746 $this->decryptIV = $xor; 1747 } 1748 break; 1749 case self::MODE_CTR: 1750 $xor = $this->decryptIV; 1751 if (strlen($buffer['ciphertext'])) { 1752 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { 1753 $block = substr($ciphertext, $i, $block_size); 1754 if (strlen($block) > strlen($buffer['ciphertext'])) { 1755 $buffer['ciphertext'] .= $this->encryptBlock($xor); 1756 Strings::increment_str($xor); 1757 } 1758 $key = Strings::shift($buffer['ciphertext'], $block_size); 1759 $plaintext .= $block ^ $key; 1760 } 1761 } else { 1762 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { 1763 $block = substr($ciphertext, $i, $block_size); 1764 $key = $this->encryptBlock($xor); 1765 Strings::increment_str($xor); 1766 $plaintext .= $block ^ $key; 1767 } 1768 } 1769 if ($this->continuousBuffer) { 1770 $this->decryptIV = $xor; 1771 if ($start = strlen($ciphertext) % $block_size) { 1772 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; 1773 } 1774 } 1775 break; 1776 case self::MODE_CFB: 1777 if ($this->continuousBuffer) { 1778 $iv = &$this->decryptIV; 1779 $pos = &$buffer['pos']; 1780 } else { 1781 $iv = $this->decryptIV; 1782 $pos = 0; 1783 } 1784 $len = strlen($ciphertext); 1785 $i = 0; 1786 if ($pos) { 1787 $orig_pos = $pos; 1788 $max = $block_size - $pos; 1789 if ($len >= $max) { 1790 $i = $max; 1791 $len -= $max; 1792 $pos = 0; 1793 } else { 1794 $i = $len; 1795 $pos += $len; 1796 $len = 0; 1797 } 1798 // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 1799 $plaintext = substr($iv, $orig_pos) ^ $ciphertext; 1800 $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); 1801 } 1802 while ($len >= $block_size) { 1803 $iv = $this->encryptBlock($iv); 1804 $cb = substr($ciphertext, $i, $block_size); 1805 $plaintext .= $iv ^ $cb; 1806 $iv = $cb; 1807 $len -= $block_size; 1808 $i += $block_size; 1809 } 1810 if ($len) { 1811 $iv = $this->encryptBlock($iv); 1812 $plaintext .= $iv ^ substr($ciphertext, $i); 1813 $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len); 1814 $pos = $len; 1815 } 1816 break; 1817 case self::MODE_CFB8: 1818 $plaintext = ''; 1819 $len = strlen($ciphertext); 1820 $iv = $this->decryptIV; 1821 1822 for ($i = 0; $i < $len; ++$i) { 1823 $plaintext .= $ciphertext[$i] ^ $this->encryptBlock($iv); 1824 $iv = substr($iv, 1) . $ciphertext[$i]; 1825 } 1826 1827 if ($this->continuousBuffer) { 1828 if ($len >= $block_size) { 1829 $this->decryptIV = substr($ciphertext, -$block_size); 1830 } else { 1831 $this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len); 1832 } 1833 } 1834 break; 1835 case self::MODE_OFB8: 1836 $plaintext = ''; 1837 $len = strlen($ciphertext); 1838 $iv = $this->decryptIV; 1839 1840 for ($i = 0; $i < $len; ++$i) { 1841 $xor = $this->encryptBlock($iv); 1842 $plaintext .= $ciphertext[$i] ^ $xor; 1843 $iv = substr($iv, 1) . $xor[0]; 1844 } 1845 1846 if ($this->continuousBuffer) { 1847 $this->decryptIV = $iv; 1848 } 1849 break; 1850 case self::MODE_OFB: 1851 $xor = $this->decryptIV; 1852 if (strlen($buffer['xor'])) { 1853 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { 1854 $block = substr($ciphertext, $i, $block_size); 1855 if (strlen($block) > strlen($buffer['xor'])) { 1856 $xor = $this->encryptBlock($xor); 1857 $buffer['xor'] .= $xor; 1858 } 1859 $key = Strings::shift($buffer['xor'], $block_size); 1860 $plaintext .= $block ^ $key; 1861 } 1862 } else { 1863 for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { 1864 $xor = $this->encryptBlock($xor); 1865 $plaintext .= substr($ciphertext, $i, $block_size) ^ $xor; 1866 } 1867 $key = $xor; 1868 } 1869 if ($this->continuousBuffer) { 1870 $this->decryptIV = $xor; 1871 if ($start = strlen($ciphertext) % $block_size) { 1872 $buffer['xor'] = substr($key, $start) . $buffer['xor']; 1873 } 1874 } 1875 break; 1876 case self::MODE_STREAM: 1877 $plaintext = $this->decryptBlock($ciphertext); 1878 break; 1879 } 1880 return $this->paddable ? $this->unpad($plaintext) : $plaintext; 1881 } 1882 1883 /** 1884 * Get the authentication tag 1885 * 1886 * Only used in GCM or Poly1305 mode 1887 * 1888 * @see self::encrypt() 1889 * @param int $length optional 1890 * @return string 1891 * @access public 1892 * @throws \LengthException if $length isn't of a sufficient length 1893 * @throws \RuntimeException if GCM mode isn't being used 1894 */ 1895 public function getTag($length = 16) 1896 { 1897 if ($this->mode != self::MODE_GCM && !$this->usePoly1305) { 1898 throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305'); 1899 } 1900 1901 if ($this->newtag === false) { 1902 throw new \BadMethodCallException('A tag can only be returned after a round of encryption has been performed'); 1903 } 1904 1905 // the tag is 128-bits. it can't be greater than 16 bytes because that's bigger than the tag is. if it 1906 // were 0 you might as well be doing CTR and less than 4 provides minimal security that could be trivially 1907 // easily brute forced. 1908 // see https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=36 1909 // for more info 1910 if ($length < 4 || $length > 16) { 1911 throw new \LengthException('The authentication tag must be between 4 and 16 bytes long'); 1912 } 1913 1914 return $length == 16 ? 1915 $this->newtag : 1916 substr($this->newtag, 0, $length); 1917 } 1918 1919 /** 1920 * Sets the authentication tag 1921 * 1922 * Only used in GCM mode 1923 * 1924 * @see self::decrypt() 1925 * @param string $tag 1926 * @access public 1927 * @throws \LengthException if $length isn't of a sufficient length 1928 * @throws \RuntimeException if GCM mode isn't being used 1929 */ 1930 public function setTag($tag) 1931 { 1932 if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) { 1933 $this->createPoly1305Key(); 1934 } 1935 1936 if ($this->mode != self::MODE_GCM && !$this->usePoly1305) { 1937 throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305'); 1938 } 1939 1940 $length = strlen($tag); 1941 if ($length < 4 || $length > 16) { 1942 throw new \LengthException('The authentication tag must be between 4 and 16 bytes long'); 1943 } 1944 $this->oldtag = $tag; 1945 } 1946 1947 /** 1948 * Get the IV 1949 * 1950 * mcrypt requires an IV even if ECB is used 1951 * 1952 * @see self::encrypt() 1953 * @see self::decrypt() 1954 * @param string $iv 1955 * @return string 1956 * @access private 1957 */ 1958 protected function getIV($iv) 1959 { 1960 return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv; 1961 } 1962 1963 /** 1964 * OpenSSL CTR Processor 1965 * 1966 * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream 1967 * for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() 1968 * and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this 1969 * function will emulate CTR with ECB when necessary. 1970 * 1971 * @see self::encrypt() 1972 * @see self::decrypt() 1973 * @param string $plaintext 1974 * @param string $encryptIV 1975 * @param array $buffer 1976 * @return string 1977 * @access private 1978 */ 1979 private function openssl_ctr_process($plaintext, &$encryptIV, &$buffer) 1980 { 1981 $ciphertext = ''; 1982 1983 $block_size = $this->block_size; 1984 $key = $this->key; 1985 1986 if ($this->openssl_emulate_ctr) { 1987 $xor = $encryptIV; 1988 if (strlen($buffer['ciphertext'])) { 1989 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 1990 $block = substr($plaintext, $i, $block_size); 1991 if (strlen($block) > strlen($buffer['ciphertext'])) { 1992 $buffer['ciphertext'] .= openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 1993 } 1994 Strings::increment_str($xor); 1995 $otp = Strings::shift($buffer['ciphertext'], $block_size); 1996 $ciphertext .= $block ^ $otp; 1997 } 1998 } else { 1999 for ($i = 0; $i < strlen($plaintext); $i += $block_size) { 2000 $block = substr($plaintext, $i, $block_size); 2001 $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 2002 Strings::increment_str($xor); 2003 $ciphertext .= $block ^ $otp; 2004 } 2005 } 2006 if ($this->continuousBuffer) { 2007 $encryptIV = $xor; 2008 if ($start = strlen($plaintext) % $block_size) { 2009 $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; 2010 } 2011 } 2012 2013 return $ciphertext; 2014 } 2015 2016 if (strlen($buffer['ciphertext'])) { 2017 $ciphertext = $plaintext ^ Strings::shift($buffer['ciphertext'], strlen($plaintext)); 2018 $plaintext = substr($plaintext, strlen($ciphertext)); 2019 2020 if (!strlen($plaintext)) { 2021 return $ciphertext; 2022 } 2023 } 2024 2025 $overflow = strlen($plaintext) % $block_size; 2026 if ($overflow) { 2027 $plaintext2 = Strings::pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2 2028 $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); 2029 $temp = Strings::pop($encrypted, $block_size); 2030 $ciphertext .= $encrypted . ($plaintext2 ^ $temp); 2031 if ($this->continuousBuffer) { 2032 $buffer['ciphertext'] = substr($temp, $overflow); 2033 $encryptIV = $temp; 2034 } 2035 } elseif (!strlen($buffer['ciphertext'])) { 2036 $ciphertext .= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); 2037 $temp = Strings::pop($ciphertext, $block_size); 2038 if ($this->continuousBuffer) { 2039 $encryptIV = $temp; 2040 } 2041 } 2042 if ($this->continuousBuffer) { 2043 $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 2044 if ($overflow) { 2045 Strings::increment_str($encryptIV); 2046 } 2047 } 2048 2049 return $ciphertext; 2050 } 2051 2052 /** 2053 * OpenSSL OFB Processor 2054 * 2055 * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream 2056 * for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() 2057 * and SymmetricKey::decrypt(). 2058 * 2059 * @see self::encrypt() 2060 * @see self::decrypt() 2061 * @param string $plaintext 2062 * @param string $encryptIV 2063 * @param array $buffer 2064 * @return string 2065 * @access private 2066 */ 2067 private function openssl_ofb_process($plaintext, &$encryptIV, &$buffer) 2068 { 2069 if (strlen($buffer['xor'])) { 2070 $ciphertext = $plaintext ^ $buffer['xor']; 2071 $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext)); 2072 $plaintext = substr($plaintext, strlen($ciphertext)); 2073 } else { 2074 $ciphertext = ''; 2075 } 2076 2077 $block_size = $this->block_size; 2078 2079 $len = strlen($plaintext); 2080 $key = $this->key; 2081 $overflow = $len % $block_size; 2082 2083 if (strlen($plaintext)) { 2084 if ($overflow) { 2085 $ciphertext .= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); 2086 $xor = Strings::pop($ciphertext, $block_size); 2087 if ($this->continuousBuffer) { 2088 $encryptIV = $xor; 2089 } 2090 $ciphertext .= Strings::shift($xor, $overflow) ^ substr($plaintext, -$overflow); 2091 if ($this->continuousBuffer) { 2092 $buffer['xor'] = $xor; 2093 } 2094 } else { 2095 $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); 2096 if ($this->continuousBuffer) { 2097 $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size); 2098 } 2099 } 2100 } 2101 2102 return $ciphertext; 2103 } 2104 2105 /** 2106 * phpseclib <-> OpenSSL Mode Mapper 2107 * 2108 * May need to be overwritten by classes extending this one in some cases 2109 * 2110 * @return string 2111 * @access private 2112 */ 2113 protected function openssl_translate_mode() 2114 { 2115 switch ($this->mode) { 2116 case self::MODE_ECB: 2117 return 'ecb'; 2118 case self::MODE_CBC: 2119 return 'cbc'; 2120 case self::MODE_CTR: 2121 case self::MODE_GCM: 2122 return 'ctr'; 2123 case self::MODE_CFB: 2124 return 'cfb'; 2125 case self::MODE_CFB8: 2126 return 'cfb8'; 2127 case self::MODE_OFB: 2128 return 'ofb'; 2129 } 2130 } 2131 2132 /** 2133 * Pad "packets". 2134 * 2135 * Block ciphers working by encrypting between their specified [$this->]block_size at a time 2136 * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to 2137 * pad the input so that it is of the proper length. 2138 * 2139 * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH, 2140 * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping 2141 * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is 2142 * transmitted separately) 2143 * 2144 * @see self::disablePadding() 2145 * @access public 2146 */ 2147 public function enablePadding() 2148 { 2149 $this->padding = true; 2150 } 2151 2152 /** 2153 * Do not pad packets. 2154 * 2155 * @see self::enablePadding() 2156 * @access public 2157 */ 2158 public function disablePadding() 2159 { 2160 $this->padding = false; 2161 } 2162 2163 /** 2164 * Treat consecutive "packets" as if they are a continuous buffer. 2165 * 2166 * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets 2167 * will yield different outputs: 2168 * 2169 * <code> 2170 * echo $rijndael->encrypt(substr($plaintext, 0, 16)); 2171 * echo $rijndael->encrypt(substr($plaintext, 16, 16)); 2172 * </code> 2173 * <code> 2174 * echo $rijndael->encrypt($plaintext); 2175 * </code> 2176 * 2177 * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates 2178 * another, as demonstrated with the following: 2179 * 2180 * <code> 2181 * $rijndael->encrypt(substr($plaintext, 0, 16)); 2182 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); 2183 * </code> 2184 * <code> 2185 * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); 2186 * </code> 2187 * 2188 * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different 2189 * outputs. The reason is due to the fact that the initialization vector's change after every encryption / 2190 * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. 2191 * 2192 * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\*() object changes after each 2193 * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that 2194 * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), 2195 * however, they are also less intuitive and more likely to cause you problems. 2196 * 2197 * {@internal Could, but not must, extend by the child Crypt_* class} 2198 * 2199 * @see self::disableContinuousBuffer() 2200 * @access public 2201 */ 2202 public function enableContinuousBuffer() 2203 { 2204 if ($this->mode == self::MODE_ECB) { 2205 return; 2206 } 2207 2208 if ($this->mode == self::MODE_GCM) { 2209 throw new \BadMethodCallException('This mode does not run in continuous mode'); 2210 } 2211 2212 $this->continuousBuffer = true; 2213 2214 $this->setEngine(); 2215 } 2216 2217 /** 2218 * Treat consecutive packets as if they are a discontinuous buffer. 2219 * 2220 * The default behavior. 2221 * 2222 * {@internal Could, but not must, extend by the child Crypt_* class} 2223 * 2224 * @see self::enableContinuousBuffer() 2225 * @access public 2226 */ 2227 public function disableContinuousBuffer() 2228 { 2229 if ($this->mode == self::MODE_ECB) { 2230 return; 2231 } 2232 if (!$this->continuousBuffer) { 2233 return; 2234 } 2235 2236 $this->continuousBuffer = false; 2237 2238 $this->setEngine(); 2239 } 2240 2241 /** 2242 * Test for engine validity 2243 * 2244 * @see self::__construct() 2245 * @param int $engine 2246 * @access private 2247 * @return bool 2248 */ 2249 protected function isValidEngineHelper($engine) 2250 { 2251 switch ($engine) { 2252 case self::ENGINE_OPENSSL: 2253 $this->openssl_emulate_ctr = false; 2254 $result = $this->cipher_name_openssl && 2255 extension_loaded('openssl'); 2256 if (!$result) { 2257 return false; 2258 } 2259 2260 $methods = openssl_get_cipher_methods(); 2261 if (in_array($this->cipher_name_openssl, $methods)) { 2262 return true; 2263 } 2264 // not all of openssl's symmetric cipher's support ctr. for those 2265 // that don't we'll emulate it 2266 switch ($this->mode) { 2267 case self::MODE_CTR: 2268 if (in_array($this->cipher_name_openssl_ecb, $methods)) { 2269 $this->openssl_emulate_ctr = true; 2270 return true; 2271 } 2272 } 2273 return false; 2274 case self::ENGINE_MCRYPT: 2275 set_error_handler(function () { 2276 }); 2277 $result = $this->cipher_name_mcrypt && 2278 extension_loaded('mcrypt') && 2279 in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()); 2280 restore_error_handler(); 2281 return $result; 2282 case self::ENGINE_EVAL: 2283 return method_exists($this, 'setupInlineCrypt'); 2284 case self::ENGINE_INTERNAL: 2285 return true; 2286 } 2287 2288 return false; 2289 } 2290 2291 /** 2292 * Test for engine validity 2293 * 2294 * @see self::__construct() 2295 * @param string $engine 2296 * @access public 2297 * @return bool 2298 */ 2299 public function isValidEngine($engine) 2300 { 2301 static $reverseMap; 2302 if (!isset($reverseMap)) { 2303 $reverseMap = array_map('strtolower', self::ENGINE_MAP); 2304 $reverseMap = array_flip($reverseMap); 2305 } 2306 $engine = strtolower($engine); 2307 if (!isset($reverseMap[$engine])) { 2308 return false; 2309 } 2310 2311 return $this->isValidEngineHelper($reverseMap[$engine]); 2312 } 2313 2314 /** 2315 * Sets the preferred crypt engine 2316 * 2317 * Currently, $engine could be: 2318 * 2319 * - libsodium[very fast] 2320 * 2321 * - OpenSSL [very fast] 2322 * 2323 * - mcrypt [fast] 2324 * 2325 * - Eval [slow] 2326 * 2327 * - PHP [slowest] 2328 * 2329 * If the preferred crypt engine is not available the fastest available one will be used 2330 * 2331 * @see self::__construct() 2332 * @param string $engine 2333 * @access public 2334 */ 2335 public function setPreferredEngine($engine) 2336 { 2337 static $reverseMap; 2338 if (!isset($reverseMap)) { 2339 $reverseMap = array_map('strtolower', self::ENGINE_MAP); 2340 $reverseMap = array_flip($reverseMap); 2341 } 2342 $engine = strtolower($engine); 2343 $this->preferredEngine = isset($reverseMap[$engine]) ? $reverseMap[$engine] : self::ENGINE_LIBSODIUM; 2344 2345 $this->setEngine(); 2346 } 2347 2348 /** 2349 * Returns the engine currently being utilized 2350 * 2351 * @see self::setEngine() 2352 * @access public 2353 */ 2354 public function getEngine() 2355 { 2356 return self::ENGINE_MAP[$this->engine]; 2357 } 2358 2359 /** 2360 * Sets the engine as appropriate 2361 * 2362 * @see self::__construct() 2363 * @access private 2364 */ 2365 protected function setEngine() 2366 { 2367 $this->engine = null; 2368 2369 $candidateEngines = [ 2370 self::ENGINE_LIBSODIUM, 2371 self::ENGINE_OPENSSL_GCM, 2372 self::ENGINE_OPENSSL, 2373 self::ENGINE_MCRYPT, 2374 self::ENGINE_EVAL 2375 ]; 2376 if (isset($this->preferredEngine)) { 2377 $temp = [$this->preferredEngine]; 2378 $candidateEngines = array_merge( 2379 $temp, 2380 array_diff($candidateEngines, $temp) 2381 ); 2382 } 2383 foreach ($candidateEngines as $engine) { 2384 if ($this->isValidEngineHelper($engine)) { 2385 $this->engine = $engine; 2386 break; 2387 } 2388 } 2389 if (!$this->engine) { 2390 $this->engine = self::ENGINE_INTERNAL; 2391 } 2392 2393 if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) { 2394 set_error_handler(function () { 2395 }); 2396 // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed, 2397 // (re)open them with the module named in $this->cipher_name_mcrypt 2398 mcrypt_module_close($this->enmcrypt); 2399 mcrypt_module_close($this->demcrypt); 2400 $this->enmcrypt = null; 2401 $this->demcrypt = null; 2402 2403 if ($this->ecb) { 2404 mcrypt_module_close($this->ecb); 2405 $this->ecb = null; 2406 } 2407 restore_error_handler(); 2408 } 2409 2410 $this->changed = $this->nonIVChanged = true; 2411 } 2412 2413 /** 2414 * Encrypts a block 2415 * 2416 * Note: Must be extended by the child \phpseclib3\Crypt\* class 2417 * 2418 * @access private 2419 * @param string $in 2420 * @return string 2421 */ 2422 abstract protected function encryptBlock($in); 2423 2424 /** 2425 * Decrypts a block 2426 * 2427 * Note: Must be extended by the child \phpseclib3\Crypt\* class 2428 * 2429 * @access private 2430 * @param string $in 2431 * @return string 2432 */ 2433 abstract protected function decryptBlock($in); 2434 2435 /** 2436 * Setup the key (expansion) 2437 * 2438 * Only used if $engine == self::ENGINE_INTERNAL 2439 * 2440 * Note: Must extend by the child \phpseclib3\Crypt\* class 2441 * 2442 * @see self::setup() 2443 * @access private 2444 */ 2445 abstract protected function setupKey(); 2446 2447 /** 2448 * Setup the self::ENGINE_INTERNAL $engine 2449 * 2450 * (re)init, if necessary, the internal cipher $engine and flush all $buffers 2451 * Used (only) if $engine == self::ENGINE_INTERNAL 2452 * 2453 * _setup() will be called each time if $changed === true 2454 * typically this happens when using one or more of following public methods: 2455 * 2456 * - setKey() 2457 * 2458 * - setIV() 2459 * 2460 * - disableContinuousBuffer() 2461 * 2462 * - First run of encrypt() / decrypt() with no init-settings 2463 * 2464 * {@internal setup() is always called before en/decryption.} 2465 * 2466 * {@internal Could, but not must, extend by the child Crypt_* class} 2467 * 2468 * @see self::setKey() 2469 * @see self::setIV() 2470 * @see self::disableContinuousBuffer() 2471 * @access private 2472 */ 2473 protected function setup() 2474 { 2475 if (!$this->changed) { 2476 return; 2477 } 2478 2479 $this->changed = false; 2480 2481 if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) { 2482 $this->createPoly1305Key(); 2483 } 2484 2485 $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true]; 2486 //$this->newtag = $this->oldtag = false; 2487 2488 if ($this->usesNonce()) { 2489 if ($this->nonce === false) { 2490 throw new InsufficientSetupException('No nonce has been defined'); 2491 } 2492 if ($this->mode == self::MODE_GCM && !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) { 2493 $this->setupGCM(); 2494 } 2495 } else { 2496 $this->iv = $this->origIV; 2497 } 2498 2499 if ($this->iv === false && !in_array($this->mode, [self::MODE_STREAM, self::MODE_ECB])) { 2500 if ($this->mode != self::MODE_GCM || !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) { 2501 throw new InsufficientSetupException('No IV has been defined'); 2502 } 2503 } 2504 2505 if ($this->key === false) { 2506 throw new InsufficientSetupException('No key has been defined'); 2507 } 2508 2509 $this->encryptIV = $this->decryptIV = $this->iv; 2510 2511 switch ($this->engine) { 2512 case self::ENGINE_MCRYPT: 2513 $this->enchanged = $this->dechanged = true; 2514 2515 set_error_handler(function () { 2516 }); 2517 2518 if (!isset($this->enmcrypt)) { 2519 static $mcrypt_modes = [ 2520 self::MODE_CTR => 'ctr', 2521 self::MODE_ECB => MCRYPT_MODE_ECB, 2522 self::MODE_CBC => MCRYPT_MODE_CBC, 2523 self::MODE_CFB => 'ncfb', 2524 self::MODE_CFB8 => MCRYPT_MODE_CFB, 2525 self::MODE_OFB => MCRYPT_MODE_NOFB, 2526 self::MODE_OFB8 => MCRYPT_MODE_OFB, 2527 self::MODE_STREAM => MCRYPT_MODE_STREAM, 2528 ]; 2529 2530 $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); 2531 $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); 2532 2533 // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() 2534 // to workaround mcrypt's broken ncfb implementation in buffered mode 2535 // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} 2536 if ($this->mode == self::MODE_CFB) { 2537 $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); 2538 } 2539 } // else should mcrypt_generic_deinit be called? 2540 2541 if ($this->mode == self::MODE_CFB) { 2542 mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); 2543 } 2544 2545 restore_error_handler(); 2546 2547 break; 2548 case self::ENGINE_INTERNAL: 2549 $this->setupKey(); 2550 break; 2551 case self::ENGINE_EVAL: 2552 if ($this->nonIVChanged) { 2553 $this->setupKey(); 2554 $this->setupInlineCrypt(); 2555 } 2556 } 2557 2558 $this->nonIVChanged = false; 2559 } 2560 2561 /** 2562 * Pads a string 2563 * 2564 * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize. 2565 * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to 2566 * chr($this->block_size - (strlen($text) % $this->block_size) 2567 * 2568 * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless 2569 * and padding will, hence forth, be enabled. 2570 * 2571 * @see self::unpad() 2572 * @param string $text 2573 * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size 2574 * @access private 2575 * @return string 2576 */ 2577 protected function pad($text) 2578 { 2579 $length = strlen($text); 2580 2581 if (!$this->padding) { 2582 if ($length % $this->block_size == 0) { 2583 return $text; 2584 } else { 2585 throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding."); 2586 } 2587 } 2588 2589 $pad = $this->block_size - ($length % $this->block_size); 2590 2591 return str_pad($text, $length + $pad, chr($pad)); 2592 } 2593 2594 /** 2595 * Unpads a string. 2596 * 2597 * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong 2598 * and false will be returned. 2599 * 2600 * @see self::pad() 2601 * @param string $text 2602 * @throws \LengthException if the ciphertext's length is not a multiple of the block size 2603 * @access private 2604 * @return string 2605 */ 2606 protected function unpad($text) 2607 { 2608 if (!$this->padding) { 2609 return $text; 2610 } 2611 2612 $length = ord($text[strlen($text) - 1]); 2613 2614 if (!$length || $length > $this->block_size) { 2615 throw new BadDecryptionException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})"); 2616 } 2617 2618 return substr($text, 0, -$length); 2619 } 2620 2621 /** 2622 * Setup the performance-optimized function for de/encrypt() 2623 * 2624 * Stores the created (or existing) callback function-name 2625 * in $this->inline_crypt 2626 * 2627 * Internally for phpseclib developers: 2628 * 2629 * _setupInlineCrypt() would be called only if: 2630 * 2631 * - $this->engine === self::ENGINE_EVAL 2632 * 2633 * - each time on _setup(), after(!) _setupKey() 2634 * 2635 * 2636 * This ensures that _setupInlineCrypt() has always a 2637 * full ready2go initializated internal cipher $engine state 2638 * where, for example, the keys already expanded, 2639 * keys/block_size calculated and such. 2640 * 2641 * It is, each time if called, the responsibility of _setupInlineCrypt(): 2642 * 2643 * - to set $this->inline_crypt to a valid and fully working callback function 2644 * as a (faster) replacement for encrypt() / decrypt() 2645 * 2646 * - NOT to create unlimited callback functions (for memory reasons!) 2647 * no matter how often _setupInlineCrypt() would be called. At some 2648 * point of amount they must be generic re-useable. 2649 * 2650 * - the code of _setupInlineCrypt() it self, 2651 * and the generated callback code, 2652 * must be, in following order: 2653 * - 100% safe 2654 * - 100% compatible to encrypt()/decrypt() 2655 * - using only php5+ features/lang-constructs/php-extensions if 2656 * compatibility (down to php4) or fallback is provided 2657 * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-) 2658 * - >= 10% faster than encrypt()/decrypt() [which is, by the way, 2659 * the reason for the existence of _setupInlineCrypt() :-)] 2660 * - memory-nice 2661 * - short (as good as possible) 2662 * 2663 * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code. 2664 * - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib3\Crypt\* class. 2665 * - The following variable names are reserved: 2666 * - $_* (all variable names prefixed with an underscore) 2667 * - $self (object reference to it self. Do not use $this, but $self instead) 2668 * - $in (the content of $in has to en/decrypt by the generated code) 2669 * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only 2670 * 2671 * {@internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()} 2672 * 2673 * @see self::setup() 2674 * @see self::createInlineCryptFunction() 2675 * @see self::encrypt() 2676 * @see self::decrypt() 2677 * @access private 2678 */ 2679 //protected function setupInlineCrypt(); 2680 2681 /** 2682 * Creates the performance-optimized function for en/decrypt() 2683 * 2684 * Internally for phpseclib developers: 2685 * 2686 * _createInlineCryptFunction(): 2687 * 2688 * - merge the $cipher_code [setup'ed by _setupInlineCrypt()] 2689 * with the current [$this->]mode of operation code 2690 * 2691 * - create the $inline function, which called by encrypt() / decrypt() 2692 * as its replacement to speed up the en/decryption operations. 2693 * 2694 * - return the name of the created $inline callback function 2695 * 2696 * - used to speed up en/decryption 2697 * 2698 * 2699 * 2700 * The main reason why can speed up things [up to 50%] this way are: 2701 * 2702 * - using variables more effective then regular. 2703 * (ie no use of expensive arrays but integers $k_0, $k_1 ... 2704 * or even, for example, the pure $key[] values hardcoded) 2705 * 2706 * - avoiding 1000's of function calls of ie _encryptBlock() 2707 * but inlining the crypt operations. 2708 * in the mode of operation for() loop. 2709 * 2710 * - full loop unroll the (sometimes key-dependent) rounds 2711 * avoiding this way ++$i counters and runtime-if's etc... 2712 * 2713 * The basic code architectur of the generated $inline en/decrypt() 2714 * lambda function, in pseudo php, is: 2715 * 2716 * <code> 2717 * +----------------------------------------------------------------------------------------------+ 2718 * | callback $inline = create_function: | 2719 * | lambda_function_0001_crypt_ECB($action, $text) | 2720 * | { | 2721 * | INSERT PHP CODE OF: | 2722 * | $cipher_code['init_crypt']; // general init code. | 2723 * | // ie: $sbox'es declarations used for | 2724 * | // encrypt and decrypt'ing. | 2725 * | | 2726 * | switch ($action) { | 2727 * | case 'encrypt': | 2728 * | INSERT PHP CODE OF: | 2729 * | $cipher_code['init_encrypt']; // encrypt sepcific init code. | 2730 * | ie: specified $key or $box | 2731 * | declarations for encrypt'ing. | 2732 * | | 2733 * | foreach ($ciphertext) { | 2734 * | $in = $block_size of $ciphertext; | 2735 * | | 2736 * | INSERT PHP CODE OF: | 2737 * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: | 2738 * | // strlen($in) == $this->block_size | 2739 * | // here comes the cipher algorithm in action | 2740 * | // for encryption. | 2741 * | // $cipher_code['encrypt_block'] has to | 2742 * | // encrypt the content of the $in variable | 2743 * | | 2744 * | $plaintext .= $in; | 2745 * | } | 2746 * | return $plaintext; | 2747 * | | 2748 * | case 'decrypt': | 2749 * | INSERT PHP CODE OF: | 2750 * | $cipher_code['init_decrypt']; // decrypt sepcific init code | 2751 * | ie: specified $key or $box | 2752 * | declarations for decrypt'ing. | 2753 * | foreach ($plaintext) { | 2754 * | $in = $block_size of $plaintext; | 2755 * | | 2756 * | INSERT PHP CODE OF: | 2757 * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always | 2758 * | // strlen($in) == $this->block_size | 2759 * | // here comes the cipher algorithm in action | 2760 * | // for decryption. | 2761 * | // $cipher_code['decrypt_block'] has to | 2762 * | // decrypt the content of the $in variable | 2763 * | $ciphertext .= $in; | 2764 * | } | 2765 * | return $ciphertext; | 2766 * | } | 2767 * | } | 2768 * +----------------------------------------------------------------------------------------------+ 2769 * </code> 2770 * 2771 * See also the \phpseclib3\Crypt\*::_setupInlineCrypt()'s for 2772 * productive inline $cipher_code's how they works. 2773 * 2774 * Structure of: 2775 * <code> 2776 * $cipher_code = [ 2777 * 'init_crypt' => (string) '', // optional 2778 * 'init_encrypt' => (string) '', // optional 2779 * 'init_decrypt' => (string) '', // optional 2780 * 'encrypt_block' => (string) '', // required 2781 * 'decrypt_block' => (string) '' // required 2782 * ]; 2783 * </code> 2784 * 2785 * @see self::setupInlineCrypt() 2786 * @see self::encrypt() 2787 * @see self::decrypt() 2788 * @param array $cipher_code 2789 * @access private 2790 * @return string (the name of the created callback function) 2791 */ 2792 protected function createInlineCryptFunction($cipher_code) 2793 { 2794 $block_size = $this->block_size; 2795 2796 // optional 2797 $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : ''; 2798 $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : ''; 2799 $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : ''; 2800 // required 2801 $encrypt_block = $cipher_code['encrypt_block']; 2802 $decrypt_block = $cipher_code['decrypt_block']; 2803 2804 // Generating mode of operation inline code, 2805 // merged with the $cipher_code algorithm 2806 // for encrypt- and decryption. 2807 switch ($this->mode) { 2808 case self::MODE_ECB: 2809 $encrypt = $init_encrypt . ' 2810 $_ciphertext = ""; 2811 $_plaintext_len = strlen($_text); 2812 2813 for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { 2814 $in = substr($_text, $_i, ' . $block_size . '); 2815 ' . $encrypt_block . ' 2816 $_ciphertext.= $in; 2817 } 2818 2819 return $_ciphertext; 2820 '; 2821 2822 $decrypt = $init_decrypt . ' 2823 $_plaintext = ""; 2824 $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0)); 2825 $_ciphertext_len = strlen($_text); 2826 2827 for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { 2828 $in = substr($_text, $_i, ' . $block_size . '); 2829 ' . $decrypt_block . ' 2830 $_plaintext.= $in; 2831 } 2832 2833 return $this->unpad($_plaintext); 2834 '; 2835 break; 2836 case self::MODE_CTR: 2837 $encrypt = $init_encrypt . ' 2838 $_ciphertext = ""; 2839 $_plaintext_len = strlen($_text); 2840 $_xor = $this->encryptIV; 2841 $_buffer = &$this->enbuffer; 2842 if (strlen($_buffer["ciphertext"])) { 2843 for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { 2844 $_block = substr($_text, $_i, ' . $block_size . '); 2845 if (strlen($_block) > strlen($_buffer["ciphertext"])) { 2846 $in = $_xor; 2847 ' . $encrypt_block . ' 2848 \phpseclib3\Common\Functions\Strings::increment_str($_xor); 2849 $_buffer["ciphertext"].= $in; 2850 } 2851 $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["ciphertext"], ' . $block_size . '); 2852 $_ciphertext.= $_block ^ $_key; 2853 } 2854 } else { 2855 for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { 2856 $_block = substr($_text, $_i, ' . $block_size . '); 2857 $in = $_xor; 2858 ' . $encrypt_block . ' 2859 \phpseclib3\Common\Functions\Strings::increment_str($_xor); 2860 $_key = $in; 2861 $_ciphertext.= $_block ^ $_key; 2862 } 2863 } 2864 if ($this->continuousBuffer) { 2865 $this->encryptIV = $_xor; 2866 if ($_start = $_plaintext_len % ' . $block_size . ') { 2867 $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; 2868 } 2869 } 2870 2871 return $_ciphertext; 2872 '; 2873 2874 $decrypt = $init_encrypt . ' 2875 $_plaintext = ""; 2876 $_ciphertext_len = strlen($_text); 2877 $_xor = $this->decryptIV; 2878 $_buffer = &$this->debuffer; 2879 2880 if (strlen($_buffer["ciphertext"])) { 2881 for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { 2882 $_block = substr($_text, $_i, ' . $block_size . '); 2883 if (strlen($_block) > strlen($_buffer["ciphertext"])) { 2884 $in = $_xor; 2885 ' . $encrypt_block . ' 2886 \phpseclib3\Common\Functions\Strings::increment_str($_xor); 2887 $_buffer["ciphertext"].= $in; 2888 } 2889 $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["ciphertext"], ' . $block_size . '); 2890 $_plaintext.= $_block ^ $_key; 2891 } 2892 } else { 2893 for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { 2894 $_block = substr($_text, $_i, ' . $block_size . '); 2895 $in = $_xor; 2896 ' . $encrypt_block . ' 2897 \phpseclib3\Common\Functions\Strings::increment_str($_xor); 2898 $_key = $in; 2899 $_plaintext.= $_block ^ $_key; 2900 } 2901 } 2902 if ($this->continuousBuffer) { 2903 $this->decryptIV = $_xor; 2904 if ($_start = $_ciphertext_len % ' . $block_size . ') { 2905 $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; 2906 } 2907 } 2908 2909 return $_plaintext; 2910 '; 2911 break; 2912 case self::MODE_CFB: 2913 $encrypt = $init_encrypt . ' 2914 $_ciphertext = ""; 2915 $_buffer = &$this->enbuffer; 2916 2917 if ($this->continuousBuffer) { 2918 $_iv = &$this->encryptIV; 2919 $_pos = &$_buffer["pos"]; 2920 } else { 2921 $_iv = $this->encryptIV; 2922 $_pos = 0; 2923 } 2924 $_len = strlen($_text); 2925 $_i = 0; 2926 if ($_pos) { 2927 $_orig_pos = $_pos; 2928 $_max = ' . $block_size . ' - $_pos; 2929 if ($_len >= $_max) { 2930 $_i = $_max; 2931 $_len-= $_max; 2932 $_pos = 0; 2933 } else { 2934 $_i = $_len; 2935 $_pos+= $_len; 2936 $_len = 0; 2937 } 2938 $_ciphertext = substr($_iv, $_orig_pos) ^ $_text; 2939 $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i); 2940 } 2941 while ($_len >= ' . $block_size . ') { 2942 $in = $_iv; 2943 ' . $encrypt_block . '; 2944 $_iv = $in ^ substr($_text, $_i, ' . $block_size . '); 2945 $_ciphertext.= $_iv; 2946 $_len-= ' . $block_size . '; 2947 $_i+= ' . $block_size . '; 2948 } 2949 if ($_len) { 2950 $in = $_iv; 2951 ' . $encrypt_block . ' 2952 $_iv = $in; 2953 $_block = $_iv ^ substr($_text, $_i); 2954 $_iv = substr_replace($_iv, $_block, 0, $_len); 2955 $_ciphertext.= $_block; 2956 $_pos = $_len; 2957 } 2958 return $_ciphertext; 2959 '; 2960 2961 $decrypt = $init_encrypt . ' 2962 $_plaintext = ""; 2963 $_buffer = &$this->debuffer; 2964 2965 if ($this->continuousBuffer) { 2966 $_iv = &$this->decryptIV; 2967 $_pos = &$_buffer["pos"]; 2968 } else { 2969 $_iv = $this->decryptIV; 2970 $_pos = 0; 2971 } 2972 $_len = strlen($_text); 2973 $_i = 0; 2974 if ($_pos) { 2975 $_orig_pos = $_pos; 2976 $_max = ' . $block_size . ' - $_pos; 2977 if ($_len >= $_max) { 2978 $_i = $_max; 2979 $_len-= $_max; 2980 $_pos = 0; 2981 } else { 2982 $_i = $_len; 2983 $_pos+= $_len; 2984 $_len = 0; 2985 } 2986 $_plaintext = substr($_iv, $_orig_pos) ^ $_text; 2987 $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i); 2988 } 2989 while ($_len >= ' . $block_size . ') { 2990 $in = $_iv; 2991 ' . $encrypt_block . ' 2992 $_iv = $in; 2993 $cb = substr($_text, $_i, ' . $block_size . '); 2994 $_plaintext.= $_iv ^ $cb; 2995 $_iv = $cb; 2996 $_len-= ' . $block_size . '; 2997 $_i+= ' . $block_size . '; 2998 } 2999 if ($_len) { 3000 $in = $_iv; 3001 ' . $encrypt_block . ' 3002 $_iv = $in; 3003 $_plaintext.= $_iv ^ substr($_text, $_i); 3004 $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len); 3005 $_pos = $_len; 3006 } 3007 3008 return $_plaintext; 3009 '; 3010 break; 3011 case self::MODE_CFB8: 3012 $encrypt = $init_encrypt . ' 3013 $_ciphertext = ""; 3014 $_len = strlen($_text); 3015 $_iv = $this->encryptIV; 3016 3017 for ($_i = 0; $_i < $_len; ++$_i) { 3018 $in = $_iv; 3019 ' . $encrypt_block . ' 3020 $_ciphertext .= ($_c = $_text[$_i] ^ $in); 3021 $_iv = substr($_iv, 1) . $_c; 3022 } 3023 3024 if ($this->continuousBuffer) { 3025 if ($_len >= ' . $block_size . ') { 3026 $this->encryptIV = substr($_ciphertext, -' . $block_size . '); 3027 } else { 3028 $this->encryptIV = substr($this->encryptIV, $_len - ' . $block_size . ') . substr($_ciphertext, -$_len); 3029 } 3030 } 3031 3032 return $_ciphertext; 3033 '; 3034 $decrypt = $init_encrypt . ' 3035 $_plaintext = ""; 3036 $_len = strlen($_text); 3037 $_iv = $this->decryptIV; 3038 3039 for ($_i = 0; $_i < $_len; ++$_i) { 3040 $in = $_iv; 3041 ' . $encrypt_block . ' 3042 $_plaintext .= $_text[$_i] ^ $in; 3043 $_iv = substr($_iv, 1) . $_text[$_i]; 3044 } 3045 3046 if ($this->continuousBuffer) { 3047 if ($_len >= ' . $block_size . ') { 3048 $this->decryptIV = substr($_text, -' . $block_size . '); 3049 } else { 3050 $this->decryptIV = substr($this->decryptIV, $_len - ' . $block_size . ') . substr($_text, -$_len); 3051 } 3052 } 3053 3054 return $_plaintext; 3055 '; 3056 break; 3057 case self::MODE_OFB8: 3058 $encrypt = $init_encrypt . ' 3059 $_ciphertext = ""; 3060 $_len = strlen($_text); 3061 $_iv = $this->encryptIV; 3062 3063 for ($_i = 0; $_i < $_len; ++$_i) { 3064 $in = $_iv; 3065 ' . $encrypt_block . ' 3066 $_ciphertext.= $_text[$_i] ^ $in; 3067 $_iv = substr($_iv, 1) . $in[0]; 3068 } 3069 3070 if ($this->continuousBuffer) { 3071 $this->encryptIV = $_iv; 3072 } 3073 3074 return $_ciphertext; 3075 '; 3076 $decrypt = $init_encrypt . ' 3077 $_plaintext = ""; 3078 $_len = strlen($_text); 3079 $_iv = $this->decryptIV; 3080 3081 for ($_i = 0; $_i < $_len; ++$_i) { 3082 $in = $_iv; 3083 ' . $encrypt_block . ' 3084 $_plaintext.= $_text[$_i] ^ $in; 3085 $_iv = substr($_iv, 1) . $in[0]; 3086 } 3087 3088 if ($this->continuousBuffer) { 3089 $this->decryptIV = $_iv; 3090 } 3091 3092 return $_plaintext; 3093 '; 3094 break; 3095 case self::MODE_OFB: 3096 $encrypt = $init_encrypt . ' 3097 $_ciphertext = ""; 3098 $_plaintext_len = strlen($_text); 3099 $_xor = $this->encryptIV; 3100 $_buffer = &$this->enbuffer; 3101 3102 if (strlen($_buffer["xor"])) { 3103 for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { 3104 $_block = substr($_text, $_i, ' . $block_size . '); 3105 if (strlen($_block) > strlen($_buffer["xor"])) { 3106 $in = $_xor; 3107 ' . $encrypt_block . ' 3108 $_xor = $in; 3109 $_buffer["xor"].= $_xor; 3110 } 3111 $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["xor"], ' . $block_size . '); 3112 $_ciphertext.= $_block ^ $_key; 3113 } 3114 } else { 3115 for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { 3116 $in = $_xor; 3117 ' . $encrypt_block . ' 3118 $_xor = $in; 3119 $_ciphertext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor; 3120 } 3121 $_key = $_xor; 3122 } 3123 if ($this->continuousBuffer) { 3124 $this->encryptIV = $_xor; 3125 if ($_start = $_plaintext_len % ' . $block_size . ') { 3126 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; 3127 } 3128 } 3129 return $_ciphertext; 3130 '; 3131 3132 $decrypt = $init_encrypt . ' 3133 $_plaintext = ""; 3134 $_ciphertext_len = strlen($_text); 3135 $_xor = $this->decryptIV; 3136 $_buffer = &$this->debuffer; 3137 3138 if (strlen($_buffer["xor"])) { 3139 for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { 3140 $_block = substr($_text, $_i, ' . $block_size . '); 3141 if (strlen($_block) > strlen($_buffer["xor"])) { 3142 $in = $_xor; 3143 ' . $encrypt_block . ' 3144 $_xor = $in; 3145 $_buffer["xor"].= $_xor; 3146 } 3147 $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["xor"], ' . $block_size . '); 3148 $_plaintext.= $_block ^ $_key; 3149 } 3150 } else { 3151 for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { 3152 $in = $_xor; 3153 ' . $encrypt_block . ' 3154 $_xor = $in; 3155 $_plaintext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor; 3156 } 3157 $_key = $_xor; 3158 } 3159 if ($this->continuousBuffer) { 3160 $this->decryptIV = $_xor; 3161 if ($_start = $_ciphertext_len % ' . $block_size . ') { 3162 $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; 3163 } 3164 } 3165 return $_plaintext; 3166 '; 3167 break; 3168 case self::MODE_STREAM: 3169 $encrypt = $init_encrypt . ' 3170 $_ciphertext = ""; 3171 ' . $encrypt_block . ' 3172 return $_ciphertext; 3173 '; 3174 $decrypt = $init_decrypt . ' 3175 $_plaintext = ""; 3176 ' . $decrypt_block . ' 3177 return $_plaintext; 3178 '; 3179 break; 3180 // case self::MODE_CBC: 3181 default: 3182 $encrypt = $init_encrypt . ' 3183 $_ciphertext = ""; 3184 $_plaintext_len = strlen($_text); 3185 3186 $in = $this->encryptIV; 3187 3188 for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { 3189 $in = substr($_text, $_i, ' . $block_size . ') ^ $in; 3190 ' . $encrypt_block . ' 3191 $_ciphertext.= $in; 3192 } 3193 3194 if ($this->continuousBuffer) { 3195 $this->encryptIV = $in; 3196 } 3197 3198 return $_ciphertext; 3199 '; 3200 3201 $decrypt = $init_decrypt . ' 3202 $_plaintext = ""; 3203 $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0)); 3204 $_ciphertext_len = strlen($_text); 3205 3206 $_iv = $this->decryptIV; 3207 3208 for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { 3209 $in = $_block = substr($_text, $_i, ' . $block_size . '); 3210 ' . $decrypt_block . ' 3211 $_plaintext.= $in ^ $_iv; 3212 $_iv = $_block; 3213 } 3214 3215 if ($this->continuousBuffer) { 3216 $this->decryptIV = $_iv; 3217 } 3218 3219 return $this->unpad($_plaintext); 3220 '; 3221 break; 3222 } 3223 3224 // Before discrediting this, please read the following: 3225 // @see https://github.com/phpseclib/phpseclib/issues/1293 3226 // @see https://github.com/phpseclib/phpseclib/pull/1143 3227 eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};'); 3228 3229 return \Closure::bind($func, $this, static::class); 3230 } 3231 3232 /** 3233 * Convert float to int 3234 * 3235 * On ARM CPUs converting floats to ints doesn't always work 3236 * 3237 * @access private 3238 * @param string $x 3239 * @return int 3240 */ 3241 protected static function safe_intval($x) 3242 { 3243 switch (true) { 3244 case is_int($x): 3245 // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding" 3246 case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM': 3247 return $x; 3248 } 3249 return (fmod($x, 0x80000000) & 0x7FFFFFFF) | 3250 ((fmod(floor($x / 0x80000000), 2) & 1) << 31); 3251 } 3252 3253 /** 3254 * eval()'able string for in-line float to int 3255 * 3256 * @access private 3257 * @return string 3258 */ 3259 protected static function safe_intval_inline() 3260 { 3261 switch (true) { 3262 case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8: 3263 case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM': 3264 return '%s'; 3265 break; 3266 default: 3267 $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | '; 3268 return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))'; 3269 } 3270 } 3271 3272 /** 3273 * Sets up GCM parameters 3274 * 3275 * See steps 1-2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=23 3276 * for more info 3277 * 3278 * @access private 3279 */ 3280 private function setupGCM() 3281 { 3282 // don't keep on re-calculating $this->h 3283 if (!$this->h || $this->h->key != $this->key) { 3284 $cipher = new static('ecb'); 3285 $cipher->setKey($this->key); 3286 $cipher->disablePadding(); 3287 3288 $this->h = self::$gcmField->newInteger( 3289 Strings::switchEndianness($cipher->encrypt("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) 3290 ); 3291 $this->h->key = $this->key; 3292 } 3293 3294 if (strlen($this->nonce) == 12) { 3295 $this->iv = $this->nonce . "\0\0\0\1"; 3296 } else { 3297 $this->iv = $this->ghash( 3298 self::nullPad128($this->nonce) . str_repeat("\0", 8) . self::len64($this->nonce) 3299 ); 3300 } 3301 } 3302 3303 /** 3304 * Performs GHASH operation 3305 * 3306 * See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=20 3307 * for more info 3308 * 3309 * @see self::decrypt() 3310 * @see self::encrypt() 3311 * @access private 3312 * @param string $x 3313 * @return string 3314 */ 3315 private function ghash($x) 3316 { 3317 $h = $this->h; 3318 $y = ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"]; 3319 $x = str_split($x, 16); 3320 $n = 0; 3321 // the switchEndianness calls are necessary because the multiplication algorithm in BinaryField/Integer 3322 // interprets strings as polynomials in big endian order whereas in GCM they're interpreted in little 3323 // endian order per https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=19. 3324 // big endian order is what binary field elliptic curves use per http://www.secg.org/sec1-v2.pdf#page=18. 3325 3326 // we could switchEndianness here instead of in the while loop but doing so in the while loop seems like it 3327 // might be slightly more performant 3328 //$x = Strings::switchEndianness($x); 3329 foreach ($x as $xn) { 3330 $xn = Strings::switchEndianness($xn); 3331 $t = $y[$n] ^ $xn; 3332 $temp = self::$gcmField->newInteger($t); 3333 $y[++$n] = $temp->multiply($h)->toBytes(); 3334 $y[$n] = substr($y[$n], 1); 3335 } 3336 $y[$n] = Strings::switchEndianness($y[$n]); 3337 return $y[$n]; 3338 } 3339 3340 /** 3341 * Returns the bit length of a string in a packed format 3342 * 3343 * @see self::decrypt() 3344 * @see self::encrypt() 3345 * @see self::setupGCM() 3346 * @access private 3347 * @param string $str 3348 * @return string 3349 */ 3350 private static function len64($str) 3351 { 3352 return "\0\0\0\0" . pack('N', 8 * strlen($str)); 3353 } 3354 3355 /** 3356 * NULL pads a string to be a multiple of 128 3357 * 3358 * @see self::decrypt() 3359 * @see self::encrypt() 3360 * @see self::setupGCM() 3361 * @access private 3362 * @param string $str 3363 * @return string 3364 */ 3365 protected static function nullPad128($str) 3366 { 3367 $len = strlen($str); 3368 return $str . str_repeat("\0", 16 * ceil($len / 16) - $len); 3369 } 3370 3371 /** 3372 * Calculates Poly1305 MAC 3373 * 3374 * On my system ChaCha20, with libsodium, takes 0.5s. With this custom Poly1305 implementation 3375 * it takes 1.2s. 3376 * 3377 * @see self::decrypt() 3378 * @see self::encrypt() 3379 * @access private 3380 * @param string $text 3381 * @return string 3382 */ 3383 protected function poly1305($text) 3384 { 3385 $s = $this->poly1305Key; // strlen($this->poly1305Key) == 32 3386 $r = Strings::shift($s, 16); 3387 $r = strrev($r); 3388 $r &= "\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xff"; 3389 $s = strrev($s); 3390 3391 $r = self::$poly1305Field->newInteger(new BigInteger($r, 256)); 3392 $s = self::$poly1305Field->newInteger(new BigInteger($s, 256)); 3393 $a = self::$poly1305Field->newInteger(new BigInteger()); 3394 3395 $blocks = str_split($text, 16); 3396 foreach ($blocks as $block) { 3397 $n = strrev($block . chr(1)); 3398 $n = self::$poly1305Field->newInteger(new BigInteger($n, 256)); 3399 $a = $a->add($n); 3400 $a = $a->multiply($r); 3401 } 3402 $r = $a->toBigInteger()->add($s->toBigInteger()); 3403 $mask = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; 3404 return strrev($r->toBytes()) & $mask; 3405 } 3406 3407 /** 3408 * Return the mode 3409 * 3410 * You can do $obj instanceof AES or whatever to get the cipher but you can't do that to get the mode 3411 * 3412 * @access public 3413 * @return string 3414 */ 3415 public function getMode() 3416 { 3417 return array_flip(self::MODE_MAP)[$this->mode]; 3418 } 3419} 3420