[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

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