Subversion Repositories oidplus

Rev

Rev 846 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
827 daniel-mar 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
 *
874 daniel-mar 24
 * @category  Crypt
25
 * @package   Hash
827 daniel-mar 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
 
34
namespace phpseclib3\Crypt;
35
 
36
use phpseclib3\Common\Functions\Strings;
37
use phpseclib3\Exception\InsufficientSetupException;
38
use phpseclib3\Exception\UnsupportedAlgorithmException;
39
use phpseclib3\Math\BigInteger;
40
use phpseclib3\Math\PrimeField;
41
 
42
/**
874 daniel-mar 43
 * @package Hash
827 daniel-mar 44
 * @author  Jim Wigginton <terrafrost@php.net>
45
 * @author  Andreas Fischer <bantu@phpbb.com>
874 daniel-mar 46
 * @access  public
827 daniel-mar 47
 */
48
class Hash
49
{
50
    /**
51
     * Padding Types
52
     *
874 daniel-mar 53
     * @access private
827 daniel-mar 54
     */
55
    const PADDING_KECCAK = 1;
56
 
57
    /**
58
     * Padding Types
59
     *
874 daniel-mar 60
     * @access private
827 daniel-mar 61
     */
62
    const PADDING_SHA3 = 2;
63
 
64
    /**
65
     * Padding Types
66
     *
874 daniel-mar 67
     * @access private
827 daniel-mar 68
     */
69
    const PADDING_SHAKE = 3;
70
 
71
    /**
72
     * Padding Type
73
     *
74
     * Only used by SHA3
75
     *
76
     * @var int
874 daniel-mar 77
     * @access private
827 daniel-mar 78
     */
79
    private $paddingType = 0;
80
 
81
    /**
82
     * Hash Parameter
83
     *
84
     * @see self::setHash()
85
     * @var int
874 daniel-mar 86
     * @access private
827 daniel-mar 87
     */
88
    private $hashParam;
89
 
90
    /**
91
     * Byte-length of hash output (Internal HMAC)
92
     *
93
     * @see self::setHash()
94
     * @var int
874 daniel-mar 95
     * @access private
827 daniel-mar 96
     */
97
    private $length;
98
 
99
    /**
100
     * Hash Algorithm
101
     *
102
     * @see self::setHash()
103
     * @var string
874 daniel-mar 104
     * @access private
827 daniel-mar 105
     */
106
    private $algo;
107
 
108
    /**
109
     * Key
110
     *
111
     * @see self::setKey()
112
     * @var string
874 daniel-mar 113
     * @access private
827 daniel-mar 114
     */
115
    private $key = false;
116
 
117
    /**
118
     * Nonce
119
     *
120
     * @see self::setNonce()
121
     * @var string
874 daniel-mar 122
     * @access private
827 daniel-mar 123
     */
124
    private $nonce = false;
125
 
126
    /**
127
     * Hash Parameters
128
     *
129
     * @var array
874 daniel-mar 130
     * @access private
827 daniel-mar 131
     */
132
    private $parameters = [];
133
 
134
    /**
135
     * Computed Key
136
     *
137
     * @see self::_computeKey()
138
     * @var string
874 daniel-mar 139
     * @access private
827 daniel-mar 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
874 daniel-mar 150
     * @access private
827 daniel-mar 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
874 daniel-mar 161
     * @access private
827 daniel-mar 162
     */
163
    private $ipad;
164
 
165
    /**
166
     * Recompute AES Key
167
     *
168
     * Used only for umac
169
     *
170
     * @see self::hash()
171
     * @var boolean
874 daniel-mar 172
     * @access private
827 daniel-mar 173
     */
174
    private $recomputeAESKey;
175
 
176
    /**
177
     * umac cipher object
178
     *
179
     * @see self::hash()
180
     * @var \phpseclib3\Crypt\AES
874 daniel-mar 181
     * @access private
827 daniel-mar 182
     */
183
    private $c;
184
 
185
    /**
186
     * umac pad
187
     *
188
     * @see self::hash()
189
     * @var string
874 daniel-mar 190
     * @access private
827 daniel-mar 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
874 daniel-mar 214
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 226
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 241
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 267
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 291
     * @access public
827 daniel-mar 292
     * @return string
293
     */
294
    public function getHash()
295
    {
296
        return $this->hashParam;
297
    }
298
 
299
    /**
300
     * Sets the hash function.
301
     *
874 daniel-mar 302
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 796
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 885
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 896
     * @access public
827 daniel-mar 897
     * @return int
898
     */
899
    public function getLengthInBytes()
900
    {
901
        return $this->length;
902
    }
903
 
904
    /**
905
     * Returns the block length (in bits)
906
     *
874 daniel-mar 907
     * @access public
827 daniel-mar 908
     * @return int
909
     */
910
    public function getBlockLength()
911
    {
912
        return $this->blockSize;
913
    }
914
 
915
    /**
916
     * Returns the block length (in bytes)
917
     *
874 daniel-mar 918
     * @access public
827 daniel-mar 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
     *
874 daniel-mar 929
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 972
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 1033
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 1143
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 1165
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 1225
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 1312
     * @access private
827 daniel-mar 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
     *
874 daniel-mar 1324
     * @access private
827 daniel-mar 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
}