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