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