[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/phpseclib/phpseclib/phpseclib/Crypt/ -> Hash.php (source)

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


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer