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