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