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