1<?php 2 3/** 4 * Wrapper around hash() and hash_hmac() functions supporting truncated hashes 5 * such as sha256-96. Any hash algorithm returned by hash_algos() (and 6 * truncated versions thereof) are supported. 7 * 8 * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will 9 * return the HMAC as opposed to the hash. 10 * 11 * Here's a short example of how to use this library: 12 * <code> 13 * <?php 14 * include 'vendor/autoload.php'; 15 * 16 * $hash = new \phpseclib3\Crypt\Hash('sha512'); 17 * 18 * $hash->setKey('abcdefg'); 19 * 20 * echo base64_encode($hash->hash('abcdefg')); 21 * ?> 22 * </code> 23 * 24 * @author Jim Wigginton <terrafrost@php.net> 25 * @copyright 2015 Jim Wigginton 26 * @author Andreas Fischer <bantu@phpbb.com> 27 * @copyright 2015 Andreas Fischer 28 * @license http://www.opensource.org/licenses/mit-license.html MIT License 29 * @link http://phpseclib.sourceforge.net 30 */ 31 32namespace phpseclib3\Crypt; 33 34use phpseclib3\Common\Functions\Strings; 35use phpseclib3\Exception\InsufficientSetupException; 36use phpseclib3\Exception\UnsupportedAlgorithmException; 37use phpseclib3\Math\BigInteger; 38use phpseclib3\Math\PrimeField; 39 40/** 41 * @author Jim Wigginton <terrafrost@php.net> 42 * @author Andreas Fischer <bantu@phpbb.com> 43 */ 44class Hash 45{ 46 /** 47 * Padding Types 48 * 49 */ 50 const PADDING_KECCAK = 1; 51 52 /** 53 * Padding Types 54 * 55 */ 56 const PADDING_SHA3 = 2; 57 58 /** 59 * Padding Types 60 * 61 */ 62 const PADDING_SHAKE = 3; 63 64 /** 65 * Padding Type 66 * 67 * Only used by SHA3 68 * 69 * @var int 70 */ 71 private $paddingType = 0; 72 73 /** 74 * Hash Parameter 75 * 76 * @see self::setHash() 77 * @var int 78 */ 79 private $hashParam; 80 81 /** 82 * Byte-length of hash output (Internal HMAC) 83 * 84 * @see self::setHash() 85 * @var int 86 */ 87 private $length; 88 89 /** 90 * Hash Algorithm 91 * 92 * @see self::setHash() 93 * @var string 94 */ 95 private $algo; 96 97 /** 98 * Key 99 * 100 * @see self::setKey() 101 * @var string 102 */ 103 private $key = false; 104 105 /** 106 * Nonce 107 * 108 * @see self::setNonce() 109 * @var string 110 */ 111 private $nonce = false; 112 113 /** 114 * Hash Parameters 115 * 116 * @var array 117 */ 118 private $parameters = []; 119 120 /** 121 * Computed Key 122 * 123 * @see self::_computeKey() 124 * @var string 125 */ 126 private $computedKey = false; 127 128 /** 129 * Outer XOR (Internal HMAC) 130 * 131 * Used only for sha512 132 * 133 * @see self::hash() 134 * @var string 135 */ 136 private $opad; 137 138 /** 139 * Inner XOR (Internal HMAC) 140 * 141 * Used only for sha512 142 * 143 * @see self::hash() 144 * @var string 145 */ 146 private $ipad; 147 148 /** 149 * Recompute AES Key 150 * 151 * Used only for umac 152 * 153 * @see self::hash() 154 * @var boolean 155 */ 156 private $recomputeAESKey; 157 158 /** 159 * umac cipher object 160 * 161 * @see self::hash() 162 * @var AES 163 */ 164 private $c; 165 166 /** 167 * umac pad 168 * 169 * @see self::hash() 170 * @var string 171 */ 172 private $pad; 173 174 /** 175 * Block Size 176 * 177 * @var int 178 */ 179 private $blockSize; 180 181 /**#@+ 182 * UMAC variables 183 * 184 * @var PrimeField 185 */ 186 private static $factory36; 187 private static $factory64; 188 private static $factory128; 189 private static $offset64; 190 private static $offset128; 191 private static $marker64; 192 private static $marker128; 193 private static $maxwordrange64; 194 private static $maxwordrange128; 195 /**#@-*/ 196 197 /**#@+ 198 * AES_CMAC variables 199 * 200 * @var string 201 */ 202 private $k1; 203 private $k2; 204 /**#@-*/ 205 206 /** 207 * Default Constructor. 208 * 209 * @param string $hash 210 */ 211 public function __construct($hash = 'sha256') 212 { 213 $this->setHash($hash); 214 } 215 216 /** 217 * Sets the key for HMACs 218 * 219 * Keys can be of any length. 220 * 221 * @param string $key 222 */ 223 public function setKey($key = false) 224 { 225 $this->key = $key; 226 $this->computeKey(); 227 $this->recomputeAESKey = true; 228 } 229 230 /** 231 * Sets the nonce for UMACs 232 * 233 * Keys can be of any length. 234 * 235 * @param string $nonce 236 */ 237 public function setNonce($nonce = false) 238 { 239 switch (true) { 240 case !is_string($nonce): 241 case strlen($nonce) > 0 && strlen($nonce) <= 16: 242 $this->recomputeAESKey = true; 243 $this->nonce = $nonce; 244 return; 245 } 246 247 throw new \LengthException('The nonce length must be between 1 and 16 bytes, inclusive'); 248 } 249 250 /** 251 * Pre-compute the key used by the HMAC 252 * 253 * Quoting http://tools.ietf.org/html/rfc2104#section-2, "Applications that use keys longer than B bytes 254 * will first hash the key using H and then use the resultant L byte string as the actual key to HMAC." 255 * 256 * As documented in https://www.reddit.com/r/PHP/comments/9nct2l/symfonypolyfill_hash_pbkdf2_correct_fix_for/ 257 * when doing an HMAC multiple times it's faster to compute the hash once instead of computing it during 258 * every call 259 * 260 */ 261 private function computeKey() 262 { 263 if ($this->key === false) { 264 $this->computedKey = false; 265 return; 266 } 267 268 if (strlen($this->key) <= $this->getBlockLengthInBytes()) { 269 $this->computedKey = $this->key; 270 return; 271 } 272 273 $this->computedKey = is_array($this->algo) ? 274 call_user_func($this->algo, $this->key) : 275 hash($this->algo, $this->key, true); 276 } 277 278 /** 279 * Gets the hash function. 280 * 281 * As set by the constructor or by the setHash() method. 282 * 283 * @return string 284 */ 285 public function getHash() 286 { 287 return $this->hashParam; 288 } 289 290 /** 291 * Sets the hash function. 292 * 293 * @param string $hash 294 */ 295 public function setHash($hash) 296 { 297 $oldHash = $this->hashParam; 298 $this->hashParam = $hash = strtolower(str_replace('/', '-', $hash)); 299 switch ($hash) { 300 case 'umac-32': 301 case 'umac-64': 302 case 'umac-96': 303 case 'umac-128': 304 if ($oldHash != $this->hashParam) { 305 $this->recomputeAESKey = true; 306 } 307 $this->blockSize = 128; 308 $this->length = abs(substr($hash, -3)) >> 3; 309 $this->algo = 'umac'; 310 return; 311 case 'aes_cmac': 312 if ($oldHash != $this->hashParam) { 313 $this->recomputeAESKey = true; 314 } 315 $this->blockSize = 128; 316 $this->length = 16; 317 $this->algo = 'aes_cmac'; 318 return; 319 case 'md2-96': 320 case 'md5-96': 321 case 'sha1-96': 322 case 'sha224-96': 323 case 'sha256-96': 324 case 'sha384-96': 325 case 'sha512-96': 326 case 'sha512-224-96': 327 case 'sha512-256-96': 328 $hash = substr($hash, 0, -3); 329 $this->length = 12; // 96 / 8 = 12 330 break; 331 case 'md2': 332 case 'md5': 333 $this->length = 16; 334 break; 335 case 'sha1': 336 $this->length = 20; 337 break; 338 case 'sha224': 339 case 'sha512-224': 340 case 'sha3-224': 341 $this->length = 28; 342 break; 343 case 'keccak256': 344 $this->paddingType = self::PADDING_KECCAK; 345 // fall-through 346 case 'sha256': 347 case 'sha512-256': 348 case 'sha3-256': 349 $this->length = 32; 350 break; 351 case 'sha384': 352 case 'sha3-384': 353 $this->length = 48; 354 break; 355 case 'sha512': 356 case 'sha3-512': 357 $this->length = 64; 358 break; 359 default: 360 if (preg_match('#^(shake(?:128|256))-(\d+)$#', $hash, $matches)) { 361 $this->paddingType = self::PADDING_SHAKE; 362 $hash = $matches[1]; 363 $this->length = $matches[2] >> 3; 364 } else { 365 throw new UnsupportedAlgorithmException( 366 "$hash is not a supported algorithm" 367 ); 368 } 369 } 370 371 switch ($hash) { 372 case 'md2': 373 case 'md2-96': 374 $this->blockSize = 128; 375 break; 376 case 'md5-96': 377 case 'sha1-96': 378 case 'sha224-96': 379 case 'sha256-96': 380 case 'md5': 381 case 'sha1': 382 case 'sha224': 383 case 'sha256': 384 $this->blockSize = 512; 385 break; 386 case 'sha3-224': 387 $this->blockSize = 1152; // 1600 - 2*224 388 break; 389 case 'sha3-256': 390 case 'shake256': 391 case 'keccak256': 392 $this->blockSize = 1088; // 1600 - 2*256 393 break; 394 case 'sha3-384': 395 $this->blockSize = 832; // 1600 - 2*384 396 break; 397 case 'sha3-512': 398 $this->blockSize = 576; // 1600 - 2*512 399 break; 400 case 'shake128': 401 $this->blockSize = 1344; // 1600 - 2*128 402 break; 403 default: 404 $this->blockSize = 1024; 405 } 406 407 if (in_array(substr($hash, 0, 5), ['sha3-', 'shake', 'kecca'])) { 408 // PHP 7.1.0 introduced support for "SHA3 fixed mode algorithms": 409 // http://php.net/ChangeLog-7.php#7.1.0 410 if (version_compare(PHP_VERSION, '7.1.0') < 0 || substr($hash, 0, 5) != 'sha3-') { 411 //preg_match('#(\d+)$#', $hash, $matches); 412 //$this->parameters['capacity'] = 2 * $matches[1]; // 1600 - $this->blockSize 413 //$this->parameters['rate'] = 1600 - $this->parameters['capacity']; // == $this->blockSize 414 if (!$this->paddingType) { 415 $this->paddingType = self::PADDING_SHA3; 416 } 417 $this->parameters = [ 418 'capacity' => 1600 - $this->blockSize, 419 'rate' => $this->blockSize, 420 'length' => $this->length, 421 'padding' => $this->paddingType 422 ]; 423 $hash = ['phpseclib3\Crypt\Hash', PHP_INT_SIZE == 8 ? 'sha3_64' : 'sha3_32']; 424 } 425 } 426 427 if ($hash == 'sha512-224' || $hash == 'sha512-256') { 428 // PHP 7.1.0 introduced sha512/224 and sha512/256 support: 429 // http://php.net/ChangeLog-7.php#7.1.0 430 if (version_compare(PHP_VERSION, '7.1.0') < 0) { 431 // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24 432 $initial = $hash == 'sha512-256' ? 433 [ 434 '22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD', 435 '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2' 436 ] : 437 [ 438 '8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF', 439 '0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1' 440 ]; 441 for ($i = 0; $i < 8; $i++) { 442 if (PHP_INT_SIZE == 8) { 443 list(, $initial[$i]) = unpack('J', pack('H*', $initial[$i])); 444 } else { 445 $initial[$i] = new BigInteger($initial[$i], 16); 446 $initial[$i]->setPrecision(64); 447 } 448 } 449 450 $this->parameters = compact('initial'); 451 452 $hash = ['phpseclib3\Crypt\Hash', PHP_INT_SIZE == 8 ? 'sha512_64' : 'sha512']; 453 } 454 } 455 456 if (is_array($hash)) { 457 $b = $this->blockSize >> 3; 458 $this->ipad = str_repeat(chr(0x36), $b); 459 $this->opad = str_repeat(chr(0x5C), $b); 460 } 461 462 // PHP's built in hash function does sha3-256 but sha512/256 so we'll update those accordingly 463 switch ($hash) { 464 case 'sha512-224': 465 $hash = 'sha512/224'; 466 break; 467 case 'sha512-256': 468 $hash = 'sha512/256'; 469 } 470 471 $this->algo = $hash; 472 473 $this->computeKey(); 474 } 475 476 /** 477 * KDF: Key-Derivation Function 478 * 479 * The key-derivation function generates pseudorandom bits used to key the hash functions. 480 * 481 * @param int $index a non-negative integer less than 2^64 482 * @param int $numbytes a non-negative integer less than 2^64 483 * @return string string of length numbytes bytes 484 */ 485 private function kdf($index, $numbytes) 486 { 487 $this->c->setIV(pack('N4', 0, $index, 0, 1)); 488 489 return $this->c->encrypt(str_repeat("\0", $numbytes)); 490 } 491 492 /** 493 * PDF Algorithm 494 * 495 * @return string string of length taglen bytes. 496 */ 497 private function pdf() 498 { 499 $k = $this->key; 500 $nonce = $this->nonce; 501 $taglen = $this->length; 502 503 // 504 // Extract and zero low bit(s) of Nonce if needed 505 // 506 if ($taglen <= 8) { 507 $last = strlen($nonce) - 1; 508 $mask = $taglen == 4 ? "\3" : "\1"; 509 $index = $nonce[$last] & $mask; 510 $nonce[$last] = $nonce[$last] ^ $index; 511 } 512 513 // 514 // Make Nonce BLOCKLEN bytes by appending zeroes if needed 515 // 516 $nonce = str_pad($nonce, 16, "\0"); 517 518 // 519 // Generate subkey, encipher and extract indexed substring 520 // 521 $kp = $this->kdf(0, 16); 522 $c = new AES('ctr'); 523 $c->disablePadding(); 524 $c->setKey($kp); 525 $c->setIV($nonce); 526 $t = $c->encrypt("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); 527 528 // we could use ord() but per https://paragonie.com/blog/2016/06/constant-time-encoding-boring-cryptography-rfc-4648-and-you 529 // unpack() doesn't leak timing info 530 return $taglen <= 8 ? 531 substr($t, unpack('C', $index)[1] * $taglen, $taglen) : 532 substr($t, 0, $taglen); 533 } 534 535 /** 536 * UHASH Algorithm 537 * 538 * @param string $m string of length less than 2^67 bits. 539 * @param int $taglen the integer 4, 8, 12 or 16. 540 * @return string string of length taglen bytes. 541 */ 542 private function uhash($m, $taglen) 543 { 544 // 545 // One internal iteration per 4 bytes of output 546 // 547 $iters = $taglen >> 2; 548 549 // 550 // Define total key needed for all iterations using KDF. 551 // L1Key reuses most key material between iterations. 552 // 553 //$L1Key = $this->kdf(1, 1024 + ($iters - 1) * 16); 554 $L1Key = $this->kdf(1, (1024 + ($iters - 1)) * 16); 555 $L2Key = $this->kdf(2, $iters * 24); 556 $L3Key1 = $this->kdf(3, $iters * 64); 557 $L3Key2 = $this->kdf(4, $iters * 4); 558 559 // 560 // For each iteration, extract key and do three-layer hash. 561 // If bytelength(M) <= 1024, then skip L2-HASH. 562 // 563 $y = ''; 564 for ($i = 0; $i < $iters; $i++) { 565 $L1Key_i = substr($L1Key, $i * 16, 1024); 566 $L2Key_i = substr($L2Key, $i * 24, 24); 567 $L3Key1_i = substr($L3Key1, $i * 64, 64); 568 $L3Key2_i = substr($L3Key2, $i * 4, 4); 569 570 $a = self::L1Hash($L1Key_i, $m); 571 $b = strlen($m) <= 1024 ? "\0\0\0\0\0\0\0\0$a" : self::L2Hash($L2Key_i, $a); 572 $c = self::L3Hash($L3Key1_i, $L3Key2_i, $b); 573 $y .= $c; 574 } 575 576 return $y; 577 } 578 579 /** 580 * L1-HASH Algorithm 581 * 582 * The first-layer hash breaks the message into 1024-byte chunks and 583 * hashes each with a function called NH. Concatenating the results 584 * forms a string, which is up to 128 times shorter than the original. 585 * 586 * @param string $k string of length 1024 bytes. 587 * @param string $m string of length less than 2^67 bits. 588 * @return string string of length (8 * ceil(bitlength(M)/8192)) bytes. 589 */ 590 private static function L1Hash($k, $m) 591 { 592 // 593 // Break M into 1024 byte chunks (final chunk may be shorter) 594 // 595 $m = str_split($m, 1024); 596 597 // 598 // For each chunk, except the last: endian-adjust, NH hash 599 // and add bit-length. Use results to build Y. 600 // 601 $length = 1024 * 8; 602 $y = ''; 603 604 for ($i = 0; $i < count($m) - 1; $i++) { 605 $m[$i] = pack('N*', ...unpack('V*', $m[$i])); // ENDIAN-SWAP 606 $y .= PHP_INT_SIZE == 8 ? 607 static::nh64($k, $m[$i], $length) : 608 static::nh32($k, $m[$i], $length); 609 } 610 611 // 612 // For the last chunk: pad to 32-byte boundary, endian-adjust, 613 // NH hash and add bit-length. Concatenate the result to Y. 614 // 615 $length = count($m) ? strlen($m[$i]) : 0; 616 $pad = 32 - ($length % 32); 617 $pad = max(32, $length + $pad % 32); 618 $m[$i] = str_pad(isset($m[$i]) ? $m[$i] : '', $pad, "\0"); // zeropad 619 $m[$i] = pack('N*', ...unpack('V*', $m[$i])); // ENDIAN-SWAP 620 621 $y .= PHP_INT_SIZE == 8 ? 622 static::nh64($k, $m[$i], $length * 8) : 623 static::nh32($k, $m[$i], $length * 8); 624 625 return $y; 626 } 627 628 /** 629 * 32-bit safe 64-bit Multiply with 2x 32-bit ints 630 * 631 * @param int $x 632 * @param int $y 633 * @return string $x * $y 634 */ 635 private static function mul32_64($x, $y) 636 { 637 // see mul64() for a more detailed explanation of how this works 638 639 $x1 = ($x >> 16) & 0xFFFF; 640 $x0 = $x & 0xFFFF; 641 642 $y1 = ($y >> 16) & 0xFFFF; 643 $y0 = $y & 0xFFFF; 644 645 // the following 3x lines will possibly yield floats 646 $z2 = $x1 * $y1; 647 $z0 = $x0 * $y0; 648 $z1 = $x1 * $y0 + $x0 * $y1; 649 650 $a = intval(fmod($z0, 65536)); 651 $b = intval($z0 / 65536) + intval(fmod($z1, 65536)); 652 $c = intval($z1 / 65536) + intval(fmod($z2, 65536)) + intval($b / 65536); 653 $b = intval(fmod($b, 65536)); 654 $d = intval($z2 / 65536) + intval($c / 65536); 655 $c = intval(fmod($c, 65536)); 656 $d = intval(fmod($d, 65536)); 657 658 return pack('n4', $d, $c, $b, $a); 659 } 660 661 /** 662 * 32-bit safe 64-bit Addition with 2x 64-bit strings 663 * 664 * @param int $x 665 * @param int $y 666 * @return int $x * $y 667 */ 668 private static function add32_64($x, $y) 669 { 670 list(, $x1, $x2, $x3, $x4) = unpack('n4', $x); 671 list(, $y1, $y2, $y3, $y4) = unpack('n4', $y); 672 $a = $x4 + $y4; 673 $b = $x3 + $y3 + ($a >> 16); 674 $c = $x2 + $y2 + ($b >> 16); 675 $d = $x1 + $y1 + ($c >> 16); 676 return pack('n4', $d, $c, $b, $a); 677 } 678 679 /** 680 * 32-bit safe 32-bit Addition with 2x 32-bit strings 681 * 682 * @param int $x 683 * @param int $y 684 * @return int $x * $y 685 */ 686 private static function add32($x, $y) 687 { 688 // see add64() for a more detailed explanation of how this works 689 690 $x1 = $x & 0xFFFF; 691 $x2 = ($x >> 16) & 0xFFFF; 692 $y1 = $y & 0xFFFF; 693 $y2 = ($y >> 16) & 0xFFFF; 694 695 $a = $x1 + $y1; 696 $b = ($x2 + $y2 + ($a >> 16)) << 16; 697 $a &= 0xFFFF; 698 699 return $a | $b; 700 } 701 702 /** 703 * NH Algorithm / 32-bit safe 704 * 705 * @param string $k string of length 1024 bytes. 706 * @param string $m string with length divisible by 32 bytes. 707 * @return string string of length 8 bytes. 708 */ 709 private static function nh32($k, $m, $length) 710 { 711 // 712 // Break M and K into 4-byte chunks 713 // 714 $k = unpack('N*', $k); 715 $m = unpack('N*', $m); 716 $t = count($m); 717 718 // 719 // Perform NH hash on the chunks, pairing words for multiplication 720 // which are 4 apart to accommodate vector-parallelism. 721 // 722 $i = 1; 723 $y = "\0\0\0\0\0\0\0\0"; 724 while ($i <= $t) { 725 $temp = self::add32($m[$i], $k[$i]); 726 $temp2 = self::add32($m[$i + 4], $k[$i + 4]); 727 $y = self::add32_64($y, self::mul32_64($temp, $temp2)); 728 729 $temp = self::add32($m[$i + 1], $k[$i + 1]); 730 $temp2 = self::add32($m[$i + 5], $k[$i + 5]); 731 $y = self::add32_64($y, self::mul32_64($temp, $temp2)); 732 733 $temp = self::add32($m[$i + 2], $k[$i + 2]); 734 $temp2 = self::add32($m[$i + 6], $k[$i + 6]); 735 $y = self::add32_64($y, self::mul32_64($temp, $temp2)); 736 737 $temp = self::add32($m[$i + 3], $k[$i + 3]); 738 $temp2 = self::add32($m[$i + 7], $k[$i + 7]); 739 $y = self::add32_64($y, self::mul32_64($temp, $temp2)); 740 741 $i += 8; 742 } 743 744 return self::add32_64($y, pack('N2', 0, $length)); 745 } 746 747 /** 748 * 64-bit Multiply with 2x 32-bit ints 749 * 750 * @param int $x 751 * @param int $y 752 * @return int $x * $y 753 */ 754 private static function mul64($x, $y) 755 { 756 // since PHP doesn't implement unsigned integers we'll implement them with signed integers 757 // to do this we'll use karatsuba multiplication 758 759 $x1 = $x >> 16; 760 $x0 = $x & 0xFFFF; 761 762 $y1 = $y >> 16; 763 $y0 = $y & 0xFFFF; 764 765 $z2 = $x1 * $y1; // up to 32 bits long 766 $z0 = $x0 * $y0; // up to 32 bits long 767 $z1 = $x1 * $y0 + $x0 * $y1; // up to 33 bit long 768 // normally karatsuba multiplication calculates $z1 thusly: 769 //$z1 = ($x1 + $x0) * ($y0 + $y1) - $z2 - $z0; 770 // the idea being to eliminate one extra multiplication. for arbitrary precision math that makes sense 771 // but not for this purpose 772 773 // at this point karatsuba would normally return this: 774 //return ($z2 << 64) + ($z1 << 32) + $z0; 775 // the problem is that the output could be out of range for signed 64-bit ints, 776 // which would cause PHP to switch to floats, which would risk losing the lower few bits 777 // as such we'll OR 4x 16-bit blocks together like so: 778 /* 779 ........ | ........ | ........ | ........ 780 upper $z2 | lower $z2 | lower $z1 | lower $z0 781 | +upper $z1 | +upper $z0 | 782 + $carry | + $carry | | 783 */ 784 // technically upper $z1 is 17 bit - not 16 - but the most significant digit of that will 785 // just get added to $carry 786 787 $a = $z0 & 0xFFFF; 788 $b = ($z0 >> 16) + ($z1 & 0xFFFF); 789 $c = ($z1 >> 16) + ($z2 & 0xFFFF) + ($b >> 16); 790 $b = ($b & 0xFFFF) << 16; 791 $d = ($z2 >> 16) + ($c >> 16); 792 $c = ($c & 0xFFFF) << 32; 793 $d = ($d & 0xFFFF) << 48; 794 795 return $a | $b | $c | $d; 796 } 797 798 /** 799 * 64-bit Addition with 2x 64-bit ints 800 * 801 * @param int $x 802 * @param int $y 803 * @return int $x + $y 804 */ 805 private static function add64($x, $y) 806 { 807 // doing $x + $y risks returning a result that's out of range for signed 64-bit ints 808 // in that event PHP would convert the result to a float and precision would be lost 809 // so we'll just add 2x 32-bit ints together like so: 810 /* 811 ........ | ........ 812 upper $x | lower $x 813 +upper $y |+lower $y 814 + $carry | 815 */ 816 $x1 = $x & 0xFFFFFFFF; 817 $x2 = ($x >> 32) & 0xFFFFFFFF; 818 $y1 = $y & 0xFFFFFFFF; 819 $y2 = ($y >> 32) & 0xFFFFFFFF; 820 821 $a = $x1 + $y1; 822 $b = ($x2 + $y2 + ($a >> 32)) << 32; 823 $a &= 0xFFFFFFFF; 824 825 return $a | $b; 826 } 827 828 /** 829 * NH Algorithm / 64-bit safe 830 * 831 * @param string $k string of length 1024 bytes. 832 * @param string $m string with length divisible by 32 bytes. 833 * @return string string of length 8 bytes. 834 */ 835 private static function nh64($k, $m, $length) 836 { 837 // 838 // Break M and K into 4-byte chunks 839 // 840 $k = unpack('N*', $k); 841 $m = unpack('N*', $m); 842 $t = count($m); 843 844 // 845 // Perform NH hash on the chunks, pairing words for multiplication 846 // which are 4 apart to accommodate vector-parallelism. 847 // 848 $i = 1; 849 $y = 0; 850 while ($i <= $t) { 851 $temp = ($m[$i] + $k[$i]) & 0xFFFFFFFF; 852 $temp2 = ($m[$i + 4] + $k[$i + 4]) & 0xFFFFFFFF; 853 $y = self::add64($y, self::mul64($temp, $temp2)); 854 855 $temp = ($m[$i + 1] + $k[$i + 1]) & 0xFFFFFFFF; 856 $temp2 = ($m[$i + 5] + $k[$i + 5]) & 0xFFFFFFFF; 857 $y = self::add64($y, self::mul64($temp, $temp2)); 858 859 $temp = ($m[$i + 2] + $k[$i + 2]) & 0xFFFFFFFF; 860 $temp2 = ($m[$i + 6] + $k[$i + 6]) & 0xFFFFFFFF; 861 $y = self::add64($y, self::mul64($temp, $temp2)); 862 863 $temp = ($m[$i + 3] + $k[$i + 3]) & 0xFFFFFFFF; 864 $temp2 = ($m[$i + 7] + $k[$i + 7]) & 0xFFFFFFFF; 865 $y = self::add64($y, self::mul64($temp, $temp2)); 866 867 $i += 8; 868 } 869 870 return pack('J', self::add64($y, $length)); 871 } 872 873 /** 874 * L2-HASH: Second-Layer Hash 875 * 876 * The second-layer rehashes the L1-HASH output using a polynomial hash 877 * called POLY. If the L1-HASH output is long, then POLY is called once 878 * on a prefix of the L1-HASH output and called using different settings 879 * on the remainder. (This two-step hashing of the L1-HASH output is 880 * needed only if the message length is greater than 16 megabytes.) 881 * Careful implementation of POLY is necessary to avoid a possible 882 * timing attack (see Section 6.6 for more information). 883 * 884 * @param string $k string of length 24 bytes. 885 * @param string $m string of length less than 2^64 bytes. 886 * @return string string of length 16 bytes. 887 */ 888 private static function L2Hash($k, $m) 889 { 890 // 891 // Extract keys and restrict to special key-sets 892 // 893 $k64 = $k & "\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF"; 894 $k64 = new BigInteger($k64, 256); 895 $k128 = substr($k, 8) & "\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF"; 896 $k128 = new BigInteger($k128, 256); 897 898 // 899 // If M is no more than 2^17 bytes, hash under 64-bit prime, 900 // otherwise, hash first 2^17 bytes under 64-bit prime and 901 // remainder under 128-bit prime. 902 // 903 if (strlen($m) <= 0x20000) { // 2^14 64-bit words 904 $y = self::poly(64, self::$maxwordrange64, $k64, $m); 905 } else { 906 $m_1 = substr($m, 0, 0x20000); // 1 << 17 907 $m_2 = substr($m, 0x20000) . "\x80"; 908 $length = strlen($m_2); 909 $pad = 16 - ($length % 16); 910 $pad %= 16; 911 $m_2 = str_pad($m_2, $length + $pad, "\0"); // zeropad 912 $y = self::poly(64, self::$maxwordrange64, $k64, $m_1); 913 $y = str_pad($y, 16, "\0", STR_PAD_LEFT); 914 $y = self::poly(128, self::$maxwordrange128, $k128, $y . $m_2); 915 } 916 917 return str_pad($y, 16, "\0", STR_PAD_LEFT); 918 } 919 920 /** 921 * POLY Algorithm 922 * 923 * @param int $wordbits the integer 64 or 128. 924 * @param BigInteger $maxwordrange positive integer less than 2^wordbits. 925 * @param BigInteger $k integer in the range 0 ... prime(wordbits) - 1. 926 * @param string $m string with length divisible by (wordbits / 8) bytes. 927 * @return integer in the range 0 ... prime(wordbits) - 1. 928 */ 929 private static function poly($wordbits, $maxwordrange, $k, $m) 930 { 931 // 932 // Define constants used for fixing out-of-range words 933 // 934 $wordbytes = $wordbits >> 3; 935 if ($wordbits == 128) { 936 $factory = self::$factory128; 937 $offset = self::$offset128; 938 $marker = self::$marker128; 939 } else { 940 $factory = self::$factory64; 941 $offset = self::$offset64; 942 $marker = self::$marker64; 943 } 944 945 $k = $factory->newInteger($k); 946 947 // 948 // Break M into chunks of length wordbytes bytes 949 // 950 $m_i = str_split($m, $wordbytes); 951 952 // 953 // Each input word m is compared with maxwordrange. If not smaller 954 // then 'marker' and (m - offset), both in range, are hashed. 955 // 956 $y = $factory->newInteger(new BigInteger(1)); 957 foreach ($m_i as $m) { 958 $m = $factory->newInteger(new BigInteger($m, 256)); 959 if ($m->compare($maxwordrange) >= 0) { 960 $y = $k->multiply($y)->add($marker); 961 $y = $k->multiply($y)->add($m->subtract($offset)); 962 } else { 963 $y = $k->multiply($y)->add($m); 964 } 965 } 966 967 return $y->toBytes(); 968 } 969 970 /** 971 * L3-HASH: Third-Layer Hash 972 * 973 * The output from L2-HASH is 16 bytes long. This final hash function 974 * hashes the 16-byte string to a fixed length of 4 bytes. 975 * 976 * @param string $k1 string of length 64 bytes. 977 * @param string $k2 string of length 4 bytes. 978 * @param string $m string of length 16 bytes. 979 * @return string string of length 4 bytes. 980 */ 981 private static function L3Hash($k1, $k2, $m) 982 { 983 $factory = self::$factory36; 984 985 $y = $factory->newInteger(new BigInteger()); 986 for ($i = 0; $i < 8; $i++) { 987 $m_i = $factory->newInteger(new BigInteger(substr($m, 2 * $i, 2), 256)); 988 $k_i = $factory->newInteger(new BigInteger(substr($k1, 8 * $i, 8), 256)); 989 $y = $y->add($m_i->multiply($k_i)); 990 } 991 $y = str_pad(substr($y->toBytes(), -4), 4, "\0", STR_PAD_LEFT); 992 $y = $y ^ $k2; 993 994 return $y; 995 } 996 997 /** 998 * Compute the Hash / HMAC / UMAC. 999 * 1000 * @param string $text 1001 * @return string 1002 */ 1003 public function hash($text) 1004 { 1005 $algo = $this->algo; 1006 // https://www.rfc-editor.org/rfc/rfc4493.html 1007 // https://en.wikipedia.org/wiki/One-key_MAC 1008 if ($algo == 'aes_cmac') { 1009 $constZero = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 1010 if ($this->recomputeAESKey) { 1011 if (!is_string($this->key)) { 1012 throw new InsufficientSetupException('No key has been set'); 1013 } 1014 if (strlen($this->key) != 16) { 1015 throw new \LengthException('Key must be 16 bytes long'); 1016 } 1017 // Algorithm Generate_Subkey 1018 $constRb = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x87"; 1019 $this->c = new AES('ecb'); 1020 $this->c->setKey($this->key); 1021 $this->c->disablePadding(); 1022 $l = $this->c->encrypt($constZero); 1023 $msb = ($l & "\x80") == "\x80"; 1024 $l = new BigInteger($l, 256); 1025 $l->setPrecision(128); 1026 $l = $l->bitwise_leftShift(1)->toBytes(); 1027 // make it constant time 1028 $k1 = $msb ? $l ^ $constRb : $l | $constZero; 1029 1030 $msb = ($k1 & "\x80") == "\x80"; 1031 $k2 = new BigInteger($k1, 256); 1032 $k2->setPrecision(128); 1033 $k2 = $k2->bitwise_leftShift(1)->toBytes(); 1034 // make it constant time 1035 $k2 = $msb ? $k2 ^ $constRb : $k2 | $constZero; 1036 1037 $this->k1 = $k1; 1038 $this->k2 = $k2; 1039 } 1040 1041 $len = strlen($text); 1042 $const_Bsize = 16; 1043 $M = strlen($text) ? str_split($text, $const_Bsize) : ['']; 1044 1045 // Step 2 1046 $n = ceil($len / $const_Bsize); 1047 // Step 3 1048 if ($n == 0) { 1049 $n = 1; 1050 $flag = false; 1051 } else { 1052 $flag = $len % $const_Bsize == 0; 1053 } 1054 // Step 4 1055 $M_last = $flag ? 1056 $M[$n - 1] ^ $k1 : 1057 self::OMAC_padding($M[$n - 1], $const_Bsize) ^ $k2; 1058 // Step 5 1059 $x = $constZero; 1060 // Step 6 1061 $c = &$this->c; 1062 for ($i = 0; $i < $n - 1; $i++) { 1063 $y = $x ^ $M[$i]; 1064 $x = $c->encrypt($y); 1065 } 1066 $y = $M_last ^ $x; 1067 return $c->encrypt($y); 1068 } 1069 if ($algo == 'umac') { 1070 if ($this->recomputeAESKey) { 1071 if (!is_string($this->nonce)) { 1072 throw new InsufficientSetupException('No nonce has been set'); 1073 } 1074 if (!is_string($this->key)) { 1075 throw new InsufficientSetupException('No key has been set'); 1076 } 1077 if (strlen($this->key) != 16) { 1078 throw new \LengthException('Key must be 16 bytes long'); 1079 } 1080 1081 if (!isset(self::$maxwordrange64)) { 1082 $one = new BigInteger(1); 1083 1084 $prime36 = new BigInteger("\x00\x00\x00\x0F\xFF\xFF\xFF\xFB", 256); 1085 self::$factory36 = new PrimeField($prime36); 1086 1087 $prime64 = new BigInteger("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC5", 256); 1088 self::$factory64 = new PrimeField($prime64); 1089 1090 $prime128 = new BigInteger("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x61", 256); 1091 self::$factory128 = new PrimeField($prime128); 1092 1093 self::$offset64 = new BigInteger("\1\0\0\0\0\0\0\0\0", 256); 1094 self::$offset64 = self::$factory64->newInteger(self::$offset64->subtract($prime64)); 1095 self::$offset128 = new BigInteger("\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 256); 1096 self::$offset128 = self::$factory128->newInteger(self::$offset128->subtract($prime128)); 1097 1098 self::$marker64 = self::$factory64->newInteger($prime64->subtract($one)); 1099 self::$marker128 = self::$factory128->newInteger($prime128->subtract($one)); 1100 1101 $maxwordrange64 = $one->bitwise_leftShift(64)->subtract($one->bitwise_leftShift(32)); 1102 self::$maxwordrange64 = self::$factory64->newInteger($maxwordrange64); 1103 1104 $maxwordrange128 = $one->bitwise_leftShift(128)->subtract($one->bitwise_leftShift(96)); 1105 self::$maxwordrange128 = self::$factory128->newInteger($maxwordrange128); 1106 } 1107 1108 $this->c = new AES('ctr'); 1109 $this->c->disablePadding(); 1110 $this->c->setKey($this->key); 1111 1112 $this->pad = $this->pdf(); 1113 1114 $this->recomputeAESKey = false; 1115 } 1116 1117 $hashedmessage = $this->uhash($text, $this->length); 1118 return $hashedmessage ^ $this->pad; 1119 } 1120 1121 if (is_array($algo)) { 1122 if (empty($this->key) || !is_string($this->key)) { 1123 return substr($algo($text, ...array_values($this->parameters)), 0, $this->length); 1124 } 1125 1126 // SHA3 HMACs are discussed at https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=30 1127 1128 $key = str_pad($this->computedKey, $b, chr(0)); 1129 $temp = $this->ipad ^ $key; 1130 $temp .= $text; 1131 $temp = substr($algo($temp, ...array_values($this->parameters)), 0, $this->length); 1132 $output = $this->opad ^ $key; 1133 $output .= $temp; 1134 $output = $algo($output, ...array_values($this->parameters)); 1135 1136 return substr($output, 0, $this->length); 1137 } 1138 1139 $output = !empty($this->key) || is_string($this->key) ? 1140 hash_hmac($algo, $text, $this->computedKey, true) : 1141 hash($algo, $text, true); 1142 1143 return strlen($output) > $this->length 1144 ? substr($output, 0, $this->length) 1145 : $output; 1146 } 1147 1148 /** 1149 * Returns the hash length (in bits) 1150 * 1151 * @return int 1152 */ 1153 public function getLength() 1154 { 1155 return $this->length << 3; 1156 } 1157 1158 /** 1159 * Returns the hash length (in bytes) 1160 * 1161 * @return int 1162 */ 1163 public function getLengthInBytes() 1164 { 1165 return $this->length; 1166 } 1167 1168 /** 1169 * Returns the block length (in bits) 1170 * 1171 * @return int 1172 */ 1173 public function getBlockLength() 1174 { 1175 return $this->blockSize; 1176 } 1177 1178 /** 1179 * Returns the block length (in bytes) 1180 * 1181 * @return int 1182 */ 1183 public function getBlockLengthInBytes() 1184 { 1185 return $this->blockSize >> 3; 1186 } 1187 1188 /** 1189 * Pads SHA3 based on the mode 1190 * 1191 * @param int $padLength 1192 * @param int $padType 1193 * @return string 1194 */ 1195 private static function sha3_pad($padLength, $padType) 1196 { 1197 switch ($padType) { 1198 case self::PADDING_KECCAK: 1199 $temp = chr(0x01) . str_repeat("\0", $padLength - 1); 1200 $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80); 1201 return $temp; 1202 case self::PADDING_SHAKE: 1203 $temp = chr(0x1F) . str_repeat("\0", $padLength - 1); 1204 $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80); 1205 return $temp; 1206 //case self::PADDING_SHA3: 1207 default: 1208 // from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=36 1209 return $padLength == 1 ? chr(0x86) : chr(0x06) . str_repeat("\0", $padLength - 2) . chr(0x80); 1210 } 1211 } 1212 1213 /** 1214 * Pure-PHP 32-bit implementation of SHA3 1215 * 1216 * Whereas BigInteger.php's 32-bit engine works on PHP 64-bit this 32-bit implementation 1217 * of SHA3 will *not* work on PHP 64-bit. This is because this implementation 1218 * employees bitwise NOTs and bitwise left shifts. And the round constants only work 1219 * on 32-bit PHP. eg. dechex(-2147483648) returns 80000000 on 32-bit PHP and 1220 * FFFFFFFF80000000 on 64-bit PHP. Sure, we could do bitwise ANDs but that would slow 1221 * things down. 1222 * 1223 * SHA512 requires BigInteger to simulate 64-bit unsigned integers because SHA2 employees 1224 * addition whereas SHA3 just employees bitwise operators. PHP64 only supports signed 1225 * 64-bit integers, which complicates addition, whereas that limitation isn't an issue 1226 * for SHA3. 1227 * 1228 * In https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=919061#page=16 KECCAK[C] is 1229 * defined as "the KECCAK instance with KECCAK-f[1600] as the underlying permutation and 1230 * capacity c". This is relevant because, altho the KECCAK standard defines a mode 1231 * (KECCAK-f[800]) designed for 32-bit machines that mode is incompatible with SHA3 1232 * 1233 * @param string $p 1234 * @param int $c 1235 * @param int $r 1236 * @param int $d 1237 * @param int $padType 1238 */ 1239 private static function sha3_32($p, $c, $r, $d, $padType) 1240 { 1241 $block_size = $r >> 3; 1242 $padLength = $block_size - (strlen($p) % $block_size); 1243 $num_ints = $block_size >> 2; 1244 1245 $p .= static::sha3_pad($padLength, $padType); 1246 1247 $n = strlen($p) / $r; // number of blocks 1248 1249 $s = [ 1250 [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], 1251 [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], 1252 [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], 1253 [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], 1254 [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]] 1255 ]; 1256 1257 $p = str_split($p, $block_size); 1258 1259 foreach ($p as $pi) { 1260 $pi = unpack('V*', $pi); 1261 $x = $y = 0; 1262 for ($i = 1; $i <= $num_ints; $i += 2) { 1263 $s[$x][$y][0] ^= $pi[$i + 1]; 1264 $s[$x][$y][1] ^= $pi[$i]; 1265 if (++$y == 5) { 1266 $y = 0; 1267 $x++; 1268 } 1269 } 1270 static::processSHA3Block32($s); 1271 } 1272 1273 $z = ''; 1274 $i = $j = 0; 1275 while (strlen($z) < $d) { 1276 $z .= pack('V2', $s[$i][$j][1], $s[$i][$j++][0]); 1277 if ($j == 5) { 1278 $j = 0; 1279 $i++; 1280 if ($i == 5) { 1281 $i = 0; 1282 static::processSHA3Block32($s); 1283 } 1284 } 1285 } 1286 1287 return $z; 1288 } 1289 1290 /** 1291 * 32-bit block processing method for SHA3 1292 * 1293 * @param array $s 1294 */ 1295 private static function processSHA3Block32(&$s) 1296 { 1297 static $rotationOffsets = [ 1298 [ 0, 1, 62, 28, 27], 1299 [36, 44, 6, 55, 20], 1300 [ 3, 10, 43, 25, 39], 1301 [41, 45, 15, 21, 8], 1302 [18, 2, 61, 56, 14] 1303 ]; 1304 1305 // the standards give these constants in hexadecimal notation. it's tempting to want to use 1306 // that same notation, here, however, we can't, because 0x80000000, on PHP32, is a positive 1307 // float - not the negative int that we need to be in PHP32. so we use -2147483648 instead 1308 static $roundConstants = [ 1309 [0, 1], 1310 [0, 32898], 1311 [-2147483648, 32906], 1312 [-2147483648, -2147450880], 1313 [0, 32907], 1314 [0, -2147483647], 1315 [-2147483648, -2147450751], 1316 [-2147483648, 32777], 1317 [0, 138], 1318 [0, 136], 1319 [0, -2147450871], 1320 [0, -2147483638], 1321 [0, -2147450741], 1322 [-2147483648, 139], 1323 [-2147483648, 32905], 1324 [-2147483648, 32771], 1325 [-2147483648, 32770], 1326 [-2147483648, 128], 1327 [0, 32778], 1328 [-2147483648, -2147483638], 1329 [-2147483648, -2147450751], 1330 [-2147483648, 32896], 1331 [0, -2147483647], 1332 [-2147483648, -2147450872] 1333 ]; 1334 1335 for ($round = 0; $round < 24; $round++) { 1336 // theta step 1337 $parity = $rotated = []; 1338 for ($i = 0; $i < 5; $i++) { 1339 $parity[] = [ 1340 $s[0][$i][0] ^ $s[1][$i][0] ^ $s[2][$i][0] ^ $s[3][$i][0] ^ $s[4][$i][0], 1341 $s[0][$i][1] ^ $s[1][$i][1] ^ $s[2][$i][1] ^ $s[3][$i][1] ^ $s[4][$i][1] 1342 ]; 1343 $rotated[] = static::rotateLeft32($parity[$i], 1); 1344 } 1345 1346 $temp = [ 1347 [$parity[4][0] ^ $rotated[1][0], $parity[4][1] ^ $rotated[1][1]], 1348 [$parity[0][0] ^ $rotated[2][0], $parity[0][1] ^ $rotated[2][1]], 1349 [$parity[1][0] ^ $rotated[3][0], $parity[1][1] ^ $rotated[3][1]], 1350 [$parity[2][0] ^ $rotated[4][0], $parity[2][1] ^ $rotated[4][1]], 1351 [$parity[3][0] ^ $rotated[0][0], $parity[3][1] ^ $rotated[0][1]] 1352 ]; 1353 for ($i = 0; $i < 5; $i++) { 1354 for ($j = 0; $j < 5; $j++) { 1355 $s[$i][$j][0] ^= $temp[$j][0]; 1356 $s[$i][$j][1] ^= $temp[$j][1]; 1357 } 1358 } 1359 1360 $st = $s; 1361 1362 // rho and pi steps 1363 for ($i = 0; $i < 5; $i++) { 1364 for ($j = 0; $j < 5; $j++) { 1365 $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft32($s[$j][$i], $rotationOffsets[$j][$i]); 1366 } 1367 } 1368 1369 // chi step 1370 for ($i = 0; $i < 5; $i++) { 1371 $s[$i][0] = [ 1372 $st[$i][0][0] ^ (~$st[$i][1][0] & $st[$i][2][0]), 1373 $st[$i][0][1] ^ (~$st[$i][1][1] & $st[$i][2][1]) 1374 ]; 1375 $s[$i][1] = [ 1376 $st[$i][1][0] ^ (~$st[$i][2][0] & $st[$i][3][0]), 1377 $st[$i][1][1] ^ (~$st[$i][2][1] & $st[$i][3][1]) 1378 ]; 1379 $s[$i][2] = [ 1380 $st[$i][2][0] ^ (~$st[$i][3][0] & $st[$i][4][0]), 1381 $st[$i][2][1] ^ (~$st[$i][3][1] & $st[$i][4][1]) 1382 ]; 1383 $s[$i][3] = [ 1384 $st[$i][3][0] ^ (~$st[$i][4][0] & $st[$i][0][0]), 1385 $st[$i][3][1] ^ (~$st[$i][4][1] & $st[$i][0][1]) 1386 ]; 1387 $s[$i][4] = [ 1388 $st[$i][4][0] ^ (~$st[$i][0][0] & $st[$i][1][0]), 1389 $st[$i][4][1] ^ (~$st[$i][0][1] & $st[$i][1][1]) 1390 ]; 1391 } 1392 1393 // iota step 1394 $s[0][0][0] ^= $roundConstants[$round][0]; 1395 $s[0][0][1] ^= $roundConstants[$round][1]; 1396 } 1397 } 1398 1399 /** 1400 * Rotate 32-bit int 1401 * 1402 * @param array $x 1403 * @param int $shift 1404 */ 1405 private static function rotateLeft32($x, $shift) 1406 { 1407 if ($shift < 32) { 1408 list($hi, $lo) = $x; 1409 } else { 1410 $shift -= 32; 1411 list($lo, $hi) = $x; 1412 } 1413 1414 $mask = -1 ^ (-1 << $shift); 1415 return [ 1416 ($hi << $shift) | (($lo >> (32 - $shift)) & $mask), 1417 ($lo << $shift) | (($hi >> (32 - $shift)) & $mask) 1418 ]; 1419 } 1420 1421 /** 1422 * Pure-PHP 64-bit implementation of SHA3 1423 * 1424 * @param string $p 1425 * @param int $c 1426 * @param int $r 1427 * @param int $d 1428 * @param int $padType 1429 */ 1430 private static function sha3_64($p, $c, $r, $d, $padType) 1431 { 1432 $block_size = $r >> 3; 1433 $padLength = $block_size - (strlen($p) % $block_size); 1434 $num_ints = $block_size >> 2; 1435 1436 $p .= static::sha3_pad($padLength, $padType); 1437 1438 $n = strlen($p) / $r; // number of blocks 1439 1440 $s = [ 1441 [0, 0, 0, 0, 0], 1442 [0, 0, 0, 0, 0], 1443 [0, 0, 0, 0, 0], 1444 [0, 0, 0, 0, 0], 1445 [0, 0, 0, 0, 0] 1446 ]; 1447 1448 $p = str_split($p, $block_size); 1449 1450 foreach ($p as $pi) { 1451 $pi = unpack('P*', $pi); 1452 $x = $y = 0; 1453 foreach ($pi as $subpi) { 1454 $s[$x][$y++] ^= $subpi; 1455 if ($y == 5) { 1456 $y = 0; 1457 $x++; 1458 } 1459 } 1460 static::processSHA3Block64($s); 1461 } 1462 1463 $z = ''; 1464 $i = $j = 0; 1465 while (strlen($z) < $d) { 1466 $z .= pack('P', $s[$i][$j++]); 1467 if ($j == 5) { 1468 $j = 0; 1469 $i++; 1470 if ($i == 5) { 1471 $i = 0; 1472 static::processSHA3Block64($s); 1473 } 1474 } 1475 } 1476 1477 return $z; 1478 } 1479 1480 /** 1481 * 64-bit block processing method for SHA3 1482 * 1483 * @param array $s 1484 */ 1485 private static function processSHA3Block64(&$s) 1486 { 1487 static $rotationOffsets = [ 1488 [ 0, 1, 62, 28, 27], 1489 [36, 44, 6, 55, 20], 1490 [ 3, 10, 43, 25, 39], 1491 [41, 45, 15, 21, 8], 1492 [18, 2, 61, 56, 14] 1493 ]; 1494 1495 static $roundConstants = [ 1496 1, 1497 32898, 1498 -9223372036854742902, 1499 -9223372034707259392, 1500 32907, 1501 2147483649, 1502 -9223372034707259263, 1503 -9223372036854743031, 1504 138, 1505 136, 1506 2147516425, 1507 2147483658, 1508 2147516555, 1509 -9223372036854775669, 1510 -9223372036854742903, 1511 -9223372036854743037, 1512 -9223372036854743038, 1513 -9223372036854775680, 1514 32778, 1515 -9223372034707292150, 1516 -9223372034707259263, 1517 -9223372036854742912, 1518 2147483649, 1519 -9223372034707259384 1520 ]; 1521 1522 for ($round = 0; $round < 24; $round++) { 1523 // theta step 1524 $parity = []; 1525 for ($i = 0; $i < 5; $i++) { 1526 $parity[] = $s[0][$i] ^ $s[1][$i] ^ $s[2][$i] ^ $s[3][$i] ^ $s[4][$i]; 1527 } 1528 $temp = [ 1529 $parity[4] ^ static::rotateLeft64($parity[1], 1), 1530 $parity[0] ^ static::rotateLeft64($parity[2], 1), 1531 $parity[1] ^ static::rotateLeft64($parity[3], 1), 1532 $parity[2] ^ static::rotateLeft64($parity[4], 1), 1533 $parity[3] ^ static::rotateLeft64($parity[0], 1) 1534 ]; 1535 for ($i = 0; $i < 5; $i++) { 1536 for ($j = 0; $j < 5; $j++) { 1537 $s[$i][$j] ^= $temp[$j]; 1538 } 1539 } 1540 1541 $st = $s; 1542 1543 // rho and pi steps 1544 for ($i = 0; $i < 5; $i++) { 1545 for ($j = 0; $j < 5; $j++) { 1546 $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft64($s[$j][$i], $rotationOffsets[$j][$i]); 1547 } 1548 } 1549 1550 // chi step 1551 for ($i = 0; $i < 5; $i++) { 1552 $s[$i] = [ 1553 $st[$i][0] ^ (~$st[$i][1] & $st[$i][2]), 1554 $st[$i][1] ^ (~$st[$i][2] & $st[$i][3]), 1555 $st[$i][2] ^ (~$st[$i][3] & $st[$i][4]), 1556 $st[$i][3] ^ (~$st[$i][4] & $st[$i][0]), 1557 $st[$i][4] ^ (~$st[$i][0] & $st[$i][1]) 1558 ]; 1559 } 1560 1561 // iota step 1562 $s[0][0] ^= $roundConstants[$round]; 1563 } 1564 } 1565 1566 /** 1567 * Left rotate 64-bit int 1568 * 1569 * @param int $x 1570 * @param int $shift 1571 */ 1572 private static function rotateLeft64($x, $shift) 1573 { 1574 $mask = -1 ^ (-1 << $shift); 1575 return ($x << $shift) | (($x >> (64 - $shift)) & $mask); 1576 } 1577 1578 /** 1579 * Right rotate 64-bit int 1580 * 1581 * @param int $x 1582 * @param int $shift 1583 */ 1584 private static function rotateRight64($x, $shift) 1585 { 1586 $mask = -1 ^ (-1 << (64 - $shift)); 1587 return (($x >> $shift) & $mask) | ($x << (64 - $shift)); 1588 } 1589 1590 /** 1591 * Pure-PHP implementation of SHA512 1592 * 1593 * @param string $m 1594 * @param array $hash 1595 * @return string 1596 */ 1597 private static function sha512($m, $hash) 1598 { 1599 static $k; 1600 1601 if (!isset($k)) { 1602 // Initialize table of round constants 1603 // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) 1604 $k = [ 1605 '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', 1606 '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 1607 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', 1608 '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 1609 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', 1610 '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', 1611 '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 1612 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', 1613 '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', 1614 '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 1615 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 1616 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', 1617 '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', 1618 '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', 1619 '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', 1620 '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 1621 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', 1622 '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', 1623 '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', 1624 '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' 1625 ]; 1626 1627 for ($i = 0; $i < 80; $i++) { 1628 $k[$i] = new BigInteger($k[$i], 16); 1629 } 1630 } 1631 1632 // Pre-processing 1633 $length = strlen($m); 1634 // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 1635 $m .= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); 1636 $m[$length] = chr(0x80); 1637 // we don't support hashing strings 512MB long 1638 $m .= pack('N4', 0, 0, 0, $length << 3); 1639 1640 // Process the message in successive 1024-bit chunks 1641 $chunks = str_split($m, 128); 1642 foreach ($chunks as $chunk) { 1643 $w = []; 1644 for ($i = 0; $i < 16; $i++) { 1645 $temp = new BigInteger(Strings::shift($chunk, 8), 256); 1646 $temp->setPrecision(64); 1647 $w[] = $temp; 1648 } 1649 1650 // Extend the sixteen 32-bit words into eighty 32-bit words 1651 for ($i = 16; $i < 80; $i++) { 1652 $temp = [ 1653 $w[$i - 15]->bitwise_rightRotate(1), 1654 $w[$i - 15]->bitwise_rightRotate(8), 1655 $w[$i - 15]->bitwise_rightShift(7) 1656 ]; 1657 $s0 = $temp[0]->bitwise_xor($temp[1]); 1658 $s0 = $s0->bitwise_xor($temp[2]); 1659 $temp = [ 1660 $w[$i - 2]->bitwise_rightRotate(19), 1661 $w[$i - 2]->bitwise_rightRotate(61), 1662 $w[$i - 2]->bitwise_rightShift(6) 1663 ]; 1664 $s1 = $temp[0]->bitwise_xor($temp[1]); 1665 $s1 = $s1->bitwise_xor($temp[2]); 1666 $w[$i] = clone $w[$i - 16]; 1667 $w[$i] = $w[$i]->add($s0); 1668 $w[$i] = $w[$i]->add($w[$i - 7]); 1669 $w[$i] = $w[$i]->add($s1); 1670 } 1671 1672 // Initialize hash value for this chunk 1673 $a = clone $hash[0]; 1674 $b = clone $hash[1]; 1675 $c = clone $hash[2]; 1676 $d = clone $hash[3]; 1677 $e = clone $hash[4]; 1678 $f = clone $hash[5]; 1679 $g = clone $hash[6]; 1680 $h = clone $hash[7]; 1681 1682 // Main loop 1683 for ($i = 0; $i < 80; $i++) { 1684 $temp = [ 1685 $a->bitwise_rightRotate(28), 1686 $a->bitwise_rightRotate(34), 1687 $a->bitwise_rightRotate(39) 1688 ]; 1689 $s0 = $temp[0]->bitwise_xor($temp[1]); 1690 $s0 = $s0->bitwise_xor($temp[2]); 1691 $temp = [ 1692 $a->bitwise_and($b), 1693 $a->bitwise_and($c), 1694 $b->bitwise_and($c) 1695 ]; 1696 $maj = $temp[0]->bitwise_xor($temp[1]); 1697 $maj = $maj->bitwise_xor($temp[2]); 1698 $t2 = $s0->add($maj); 1699 1700 $temp = [ 1701 $e->bitwise_rightRotate(14), 1702 $e->bitwise_rightRotate(18), 1703 $e->bitwise_rightRotate(41) 1704 ]; 1705 $s1 = $temp[0]->bitwise_xor($temp[1]); 1706 $s1 = $s1->bitwise_xor($temp[2]); 1707 $temp = [ 1708 $e->bitwise_and($f), 1709 $g->bitwise_and($e->bitwise_not()) 1710 ]; 1711 $ch = $temp[0]->bitwise_xor($temp[1]); 1712 $t1 = $h->add($s1); 1713 $t1 = $t1->add($ch); 1714 $t1 = $t1->add($k[$i]); 1715 $t1 = $t1->add($w[$i]); 1716 1717 $h = clone $g; 1718 $g = clone $f; 1719 $f = clone $e; 1720 $e = $d->add($t1); 1721 $d = clone $c; 1722 $c = clone $b; 1723 $b = clone $a; 1724 $a = $t1->add($t2); 1725 } 1726 1727 // Add this chunk's hash to result so far 1728 $hash = [ 1729 $hash[0]->add($a), 1730 $hash[1]->add($b), 1731 $hash[2]->add($c), 1732 $hash[3]->add($d), 1733 $hash[4]->add($e), 1734 $hash[5]->add($f), 1735 $hash[6]->add($g), 1736 $hash[7]->add($h) 1737 ]; 1738 } 1739 1740 // Produce the final hash value (big-endian) 1741 // (\phpseclib3\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) 1742 $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . 1743 $hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes(); 1744 1745 return $temp; 1746 } 1747 1748 /** 1749 * Pure-PHP implementation of SHA512 1750 * 1751 * @param string $m 1752 * @param array $hash 1753 * @return string 1754 */ 1755 private static function sha512_64($m, $hash) 1756 { 1757 static $k; 1758 1759 if (!isset($k)) { 1760 // Initialize table of round constants 1761 // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) 1762 $k = [ 1763 '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', 1764 '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 1765 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', 1766 '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 1767 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', 1768 '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', 1769 '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 1770 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', 1771 '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', 1772 '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 1773 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 1774 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', 1775 '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', 1776 '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', 1777 '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', 1778 '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 1779 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', 1780 '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', 1781 '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', 1782 '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' 1783 ]; 1784 1785 for ($i = 0; $i < 80; $i++) { 1786 list(, $k[$i]) = unpack('J', pack('H*', $k[$i])); 1787 } 1788 } 1789 1790 // Pre-processing 1791 $length = strlen($m); 1792 // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 1793 $m .= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); 1794 $m[$length] = chr(0x80); 1795 // we don't support hashing strings 512MB long 1796 $m .= pack('N4', 0, 0, 0, $length << 3); 1797 1798 // Process the message in successive 1024-bit chunks 1799 $chunks = str_split($m, 128); 1800 foreach ($chunks as $chunk) { 1801 $w = []; 1802 for ($i = 0; $i < 16; $i++) { 1803 list(, $w[]) = unpack('J', Strings::shift($chunk, 8)); 1804 } 1805 1806 // Extend the sixteen 32-bit words into eighty 32-bit words 1807 for ($i = 16; $i < 80; $i++) { 1808 $temp = [ 1809 self::rotateRight64($w[$i - 15], 1), 1810 self::rotateRight64($w[$i - 15], 8), 1811 ($w[$i - 15] >> 7) & 0x01FFFFFFFFFFFFFF, 1812 ]; 1813 $s0 = $temp[0] ^ $temp[1] ^ $temp[2]; 1814 $temp = [ 1815 self::rotateRight64($w[$i - 2], 19), 1816 self::rotateRight64($w[$i - 2], 61), 1817 ($w[$i - 2] >> 6) & 0x03FFFFFFFFFFFFFF, 1818 ]; 1819 $s1 = $temp[0] ^ $temp[1] ^ $temp[2]; 1820 1821 $w[$i] = $w[$i - 16]; 1822 $w[$i] = self::add64($w[$i], $s0); 1823 $w[$i] = self::add64($w[$i], $w[$i - 7]); 1824 $w[$i] = self::add64($w[$i], $s1); 1825 } 1826 1827 // Initialize hash value for this chunk 1828 list($a, $b, $c, $d, $e, $f, $g, $h) = $hash; 1829 1830 // Main loop 1831 for ($i = 0; $i < 80; $i++) { 1832 $temp = [ 1833 self::rotateRight64($a, 28), 1834 self::rotateRight64($a, 34), 1835 self::rotateRight64($a, 39), 1836 ]; 1837 $s0 = $temp[0] ^ $temp[1] ^ $temp[2]; 1838 $temp = [$a & $b, $a & $c, $b & $c]; 1839 $maj = $temp[0] ^ $temp[1] ^ $temp[2]; 1840 $t2 = self::add64($s0, $maj); 1841 1842 $temp = [ 1843 self::rotateRight64($e, 14), 1844 self::rotateRight64($e, 18), 1845 self::rotateRight64($e, 41), 1846 ]; 1847 $s1 = $temp[0] ^ $temp[1] ^ $temp[2]; 1848 $ch = ($e & $f) ^ ($g & ~$e); 1849 $t1 = self::add64($h, $s1); 1850 $t1 = self::add64($t1, $ch); 1851 $t1 = self::add64($t1, $k[$i]); 1852 $t1 = self::add64($t1, $w[$i]); 1853 1854 $h = $g; 1855 $g = $f; 1856 $f = $e; 1857 $e = self::add64($d, $t1); 1858 $d = $c; 1859 $c = $b; 1860 $b = $a; 1861 $a = self::add64($t1, $t2); 1862 } 1863 1864 // Add this chunk's hash to result so far 1865 $hash = [ 1866 self::add64($hash[0], $a), 1867 self::add64($hash[1], $b), 1868 self::add64($hash[2], $c), 1869 self::add64($hash[3], $d), 1870 self::add64($hash[4], $e), 1871 self::add64($hash[5], $f), 1872 self::add64($hash[6], $g), 1873 self::add64($hash[7], $h), 1874 ]; 1875 } 1876 1877 // Produce the final hash value (big-endian) 1878 // (\phpseclib3\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) 1879 return pack('J*', ...$hash); 1880 } 1881 1882 /** 1883 * OMAC Padding 1884 * 1885 * @link https://www.rfc-editor.org/rfc/rfc4493.html#section-2.4 1886 */ 1887 private static function OMAC_padding($m, $length) 1888 { 1889 $count = $length - strlen($m) - 1; 1890 return "$m\x80" . str_repeat("\0", $count); 1891 } 1892 1893 /** 1894 * __toString() magic method 1895 */ 1896 public function __toString() 1897 { 1898 return $this->getHash(); 1899 } 1900} 1901