1<?php
2
3/**
4 * Wrapper around hash() and hash_hmac() functions supporting truncated hashes
5 * such as sha256-96.  Any hash algorithm returned by hash_algos() (and
6 * truncated versions thereof) are supported.
7 *
8 * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will
9 * return the HMAC as opposed to the hash.
10 *
11 * Here's a short example of how to use this library:
12 * <code>
13 * <?php
14 *    include 'vendor/autoload.php';
15 *
16 *    $hash = new \phpseclib3\Crypt\Hash('sha512');
17 *
18 *    $hash->setKey('abcdefg');
19 *
20 *    echo base64_encode($hash->hash('abcdefg'));
21 * ?>
22 * </code>
23 *
24 * @author    Jim Wigginton <terrafrost@php.net>
25 * @copyright 2015 Jim Wigginton
26 * @author    Andreas Fischer <bantu@phpbb.com>
27 * @copyright 2015 Andreas Fischer
28 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
29 * @link      http://phpseclib.sourceforge.net
30 */
31
32namespace phpseclib3\Crypt;
33
34use phpseclib3\Common\Functions\Strings;
35use phpseclib3\Exception\InsufficientSetupException;
36use phpseclib3\Exception\UnsupportedAlgorithmException;
37use phpseclib3\Math\BigInteger;
38use phpseclib3\Math\PrimeField;
39
40/**
41 * @author  Jim Wigginton <terrafrost@php.net>
42 * @author  Andreas Fischer <bantu@phpbb.com>
43 */
44class Hash
45{
46    /**
47     * Padding Types
48     *
49     */
50    const PADDING_KECCAK = 1;
51
52    /**
53     * Padding Types
54     *
55     */
56    const PADDING_SHA3 = 2;
57
58    /**
59     * Padding Types
60     *
61     */
62    const PADDING_SHAKE = 3;
63
64    /**
65     * Padding Type
66     *
67     * Only used by SHA3
68     *
69     * @var int
70     */
71    private $paddingType = 0;
72
73    /**
74     * Hash Parameter
75     *
76     * @see self::setHash()
77     * @var int
78     */
79    private $hashParam;
80
81    /**
82     * Byte-length of hash output (Internal HMAC)
83     *
84     * @see self::setHash()
85     * @var int
86     */
87    private $length;
88
89    /**
90     * Hash Algorithm
91     *
92     * @see self::setHash()
93     * @var string
94     */
95    private $algo;
96
97    /**
98     * Key
99     *
100     * @see self::setKey()
101     * @var string
102     */
103    private $key = false;
104
105    /**
106     * Nonce
107     *
108     * @see self::setNonce()
109     * @var string
110     */
111    private $nonce = false;
112
113    /**
114     * Hash Parameters
115     *
116     * @var array
117     */
118    private $parameters = [];
119
120    /**
121     * Computed Key
122     *
123     * @see self::_computeKey()
124     * @var string
125     */
126    private $computedKey = false;
127
128    /**
129     * Outer XOR (Internal HMAC)
130     *
131     * Used only for sha512
132     *
133     * @see self::hash()
134     * @var string
135     */
136    private $opad;
137
138    /**
139     * Inner XOR (Internal HMAC)
140     *
141     * Used only for sha512
142     *
143     * @see self::hash()
144     * @var string
145     */
146    private $ipad;
147
148    /**
149     * Recompute AES Key
150     *
151     * Used only for umac
152     *
153     * @see self::hash()
154     * @var boolean
155     */
156    private $recomputeAESKey;
157
158    /**
159     * umac cipher object
160     *
161     * @see self::hash()
162     * @var AES
163     */
164    private $c;
165
166    /**
167     * umac pad
168     *
169     * @see self::hash()
170     * @var string
171     */
172    private $pad;
173
174    /**
175     * Block Size
176     *
177     * @var int
178     */
179    private $blockSize;
180
181    /**#@+
182     * UMAC variables
183     *
184     * @var PrimeField
185     */
186    private static $factory36;
187    private static $factory64;
188    private static $factory128;
189    private static $offset64;
190    private static $offset128;
191    private static $marker64;
192    private static $marker128;
193    private static $maxwordrange64;
194    private static $maxwordrange128;
195    /**#@-*/
196
197    /**
198     * 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