Issues (365)

src/Library/libraries/phpseclib/Crypt/Hash.php (6 issues)

1
<?php
2
3
/**
4
 * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
5
 *
6
 * Uses hash() or mhash() if available and an internal implementation, otherwise.  Currently supports the following:
7
 *
8
 * sha256, sha256-96, sha384, and sha512, sha512-96
9
 *
10
 * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
11
 * the hash.  If no valid algorithm is provided, sha256 will be used.
12
 *
13
 * PHP version 5
14
 *
15
 * {@internal The variable names are the same as those in
16
 * {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
17
 *
18
 * Here's a short example of how to use this library:
19
 * <code>
20
 * <?php
21
 *    include 'vendor/autoload.php';
22
 *
23
 *    $hash = new \phpseclib\Crypt\Hash('sha256');
24
 *
25
 *    $hash->setKey('abcdefg');
26
 *
27
 *    echo base64_encode($hash->hash('abcdefg'));
28
 * ?>
29
 * </code>
30
 *
31
 * @category  Crypt
32
 * @package   Hash
33
 * @author    Jim Wigginton <[email protected]>
34
 * @copyright 2007 Jim Wigginton
35
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
36
 * @link      http://phpseclib.sourceforge.net
37
 */
38
39
namespace phpseclib\Crypt;
40
41
use phpseclib\Math\BigInteger;
42
43
/**
44
 * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
45
 *
46
 * @package Hash
47
 * @author  Jim Wigginton <[email protected]>
48
 * @access  public
49
 */
50
class Hash
51
{
52
    /**#@+
53
     * @access private
54
     * @see \phpseclib\Crypt\Hash::__construct()
55
     */
56
    /**
57
     * Toggles the internal implementation
58
     */
59
    public const MODE_INTERNAL = 1;
60
    /**
61
     * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
62
     */
63
    public const MODE_MHASH = 2;
64
    /**
65
     * Toggles the hash() implementation, which works on PHP 5.1.2+.
66
     */
67
    public const MODE_HASH = 3;
68
    /**#@-*/
69
70
    /**
71
     * Hash Parameter
72
     *
73
     * @see self::setHash()
74
     * @var int
75
     * @access private
76
     */
77
    public $hashParam;
78
79
    /**
80
     * Byte-length of compression blocks / key (Internal HMAC)
81
     *
82
     * @see self::setAlgorithm()
83
     * @var int
84
     * @access private
85
     */
86
    public $b;
87
88
    /**
89
     * Byte-length of hash output (Internal HMAC)
90
     *
91
     * @see self::setHash()
92
     * @var int
93
     * @access private
94
     */
95
    public $l = false;
96
97
    /**
98
     * Hash Algorithm
99
     *
100
     * @see self::setHash()
101
     * @var string
102
     * @access private
103
     */
104
    public $hash;
105
106
    /**
107
     * Key
108
     *
109
     * @see self::setKey()
110
     * @var string
111
     * @access private
112
     */
113
    public $key = false;
114
115
    /**
116
     * Outer XOR (Internal HMAC)
117
     *
118
     * @see self::setKey()
119
     * @var string
120
     * @access private
121
     */
122
    public $opad;
123
124
    /**
125
     * Inner XOR (Internal HMAC)
126
     *
127
     * @see self::setKey()
128
     * @var string
129
     * @access private
130
     */
131
    public $ipad;
132
133
    /**
134
     * Default Constructor.
135
     *
136
     * @param string $hash
137
     * @return \phpseclib\Crypt\Hash
138
     * @access public
139
     */
140
    public function __construct($hash = 'sha256')
141
    {
142
        if (!defined('CRYPT_HASH_MODE')) {
143
            switch (true) {
144
                case extension_loaded('hash'):
145
                    define('CRYPT_HASH_MODE', self::MODE_HASH);
146
                    break;
147
                case extension_loaded('mhash'):
148
                    define('CRYPT_HASH_MODE', self::MODE_MHASH);
149
                    break;
150
                default:
151
                    define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
152
            }
153
        }
154
155
        $this->setHash($hash);
156
    }
157
158
    /**
159
     * Sets the key for HMACs
160
     *
161
     * Keys can be of any length.
162
     *
163
     * @access public
164
     * @param string $key
165
     */
166
    public function setKey($key = false)
167
    {
168
        $this->key = $key;
0 ignored issues
show
Documentation Bug introduced by
It seems like $key can also be of type false. However, the property $key is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
169
    }
170
171
    /**
172
     * Gets the hash function.
173
     *
174
     * As set by the constructor or by the setHash() method.
175
     *
176
     * @access public
177
     * @return string
178
     */
179
    public function getHash()
180
    {
181
        return $this->hashParam;
182
    }
183
184
    /**
185
     * Sets the hash function.
186
     *
187
     * @access public
188
     * @param string $hash
189
     */
190
    public function setHash($hash)
191
    {
192
        $this->hashParam = $hash = strtolower($hash);
0 ignored issues
show
Documentation Bug introduced by
The property $hashParam was declared of type integer, but $hash = strtolower($hash) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
193
        switch ($hash) {
194
            case 'sha256-96':
195
            case 'sha512-96':
196
                $hash = substr($hash, 0, -3);
197
                $this->l = 12; // 96 / 8 = 12
198
                break;
199
            case 'sha256':
200
                $this->l = 32;
201
                break;
202
            case 'sha384':
203
                $this->l = 48;
204
                break;
205
            case 'sha512':
206
                $this->l = 64;
207
        }
208
209
        switch ($hash) {
210
            case 'sha384':
211
            case 'sha512':
212
                $mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
213
                break;
214
            default:
215
                $mode = CRYPT_HASH_MODE;
216
        }
217
218
        switch ($mode) {
219
            case self::MODE_MHASH:
220
                switch ($hash) {
221
                    case 'sha256':
222
                        $this->hash = MHASH_SHA256;
223
                        break;
224
                    default:
225
                        $this->hash = MHASH_SHA256;
226
                }
227
                return;
228
            case self::MODE_HASH:
229
                switch ($hash) {
230
                    case 'sha256':
231
                    case 'sha384':
232
                    case 'sha512':
233
                        $this->hash = $hash;
234
                        return;
235
                    default:
236
                        $this->hash = 'sha256';
237
                }
238
                return;
239
        }
240
241
        switch ($hash) {
242
            case 'sha256':
243
                $this->b = 64;
244
                $this->hash = array($this, '_sha256');
0 ignored issues
show
Documentation Bug introduced by
It seems like array($this, '_sha256') of type array<integer,phpseclib\Crypt\Hash|string> is incompatible with the declared type string of property $hash.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
245
                break;
246
            case 'sha384':
247
            case 'sha512':
248
                $this->b = 128;
249
                $this->hash = array($this, '_sha512');
250
                break;
251
            default:
252
                $this->b = 64;
253
                $this->hash = array($this, '_sha256');
254
        }
255
256
        $this->ipad = str_repeat(chr(0x36), $this->b);
257
        $this->opad = str_repeat(chr(0x5C), $this->b);
258
    }
259
260
    /**
261
     * Compute the HMAC.
262
     *
263
     * @access public
264
     * @param string $text
265
     * @return string
266
     */
267
    public function hash($text)
268
    {
269
        $mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
270
271
        if (!empty($this->key) || is_string($this->key)) {
272
            switch ($mode) {
273
                case self::MODE_MHASH:
274
                    $output = mhash($this->hash, $text, $this->key);
0 ignored issues
show
$this->hash of type string is incompatible with the type integer expected by parameter $hash of mhash(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

274
                    $output = mhash(/** @scrutinizer ignore-type */ $this->hash, $text, $this->key);
Loading history...
275
                    break;
276
                case self::MODE_HASH:
277
                    $output = hash_hmac($this->hash, $text, $this->key, true);
278
                    break;
279
                case self::MODE_INTERNAL:
280
                    /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
281
                        resultant L byte string as the actual key to HMAC."
282
283
                        -- http://tools.ietf.org/html/rfc2104#section-2 */
284
                    $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
285
286
                    $key    = str_pad($key, $this->b, chr(0));      // step 1
287
                    $temp   = $this->ipad ^ $key;                   // step 2
288
                    $temp  .= $text;                                // step 3
289
                    $temp   = call_user_func($this->hash, $temp);   // step 4
290
                    $output = $this->opad ^ $key;                   // step 5
291
                    $output.= $temp;                                // step 6
292
                    $output = call_user_func($this->hash, $output); // step 7
293
            }
294
        } else {
295
            switch ($mode) {
296
                case self::MODE_MHASH:
297
                    $output = mhash($this->hash, $text);
298
                    break;
299
                case self::MODE_HASH:
300
                    $output = hash($this->hash, $text, true);
301
                    break;
302
                case self::MODE_INTERNAL:
303
                    $output = call_user_func($this->hash, $text);
304
            }
305
        }
306
307
        return substr($output, 0, $this->l);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $output does not seem to be defined for all execution paths leading up to this point.
Loading history...
308
    }
309
310
    /**
311
     * Returns the hash length (in bytes)
312
     *
313
     * @access public
314
     * @return int
315
     */
316
    public function getLength()
317
    {
318
        return $this->l;
319
    }
320
321
    /**
322
     * Pure-PHP implementation of SHA256
323
     *
324
     * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
325
     *
326
     * @access private
327
     * @param string $m
328
     */
329
    public function _sha256($m)
330
    {
331
        if (extension_loaded('suhosin')) {
332
            return pack('H*', sha256($m));
333
        }
334
335
        // Initialize variables
336
        $hash = array(
337
            0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
338
        );
339
        // Initialize table of round constants
340
        // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
341
        static $k = array(
342
            0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
343
            0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
344
            0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
345
            0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
346
            0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
347
            0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
348
            0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
349
            0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
350
        );
351
352
        // Pre-processing
353
        $length = strlen($m);
354
        // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
355
        $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
356
        $m[$length] = chr(0x80);
357
        // we don't support hashing strings 512MB long
358
        $m.= pack('N2', 0, $length << 3);
359
360
        // Process the message in successive 512-bit chunks
361
        $chunks = str_split($m, 64);
362
        foreach ($chunks as $chunk) {
363
            $w = array();
364
            for ($i = 0; $i < 16; $i++) {
365
                extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
0 ignored issues
show
It seems like unpack('Ntemp', $this->_string_shift($chunk, 4)) can also be of type false; however, parameter $var_array of extract() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

365
                extract(/** @scrutinizer ignore-type */ unpack('Ntemp', $this->_string_shift($chunk, 4)));
Loading history...
366
                $w[] = $temp;
367
            }
368
369
            // Extend the sixteen 32-bit words into sixty-four 32-bit words
370
            for ($i = 16; $i < 64; $i++) {
371
                // @codingStandardsIgnoreStart
372
                $s0 = $this->_rightRotate($w[$i - 15], 7) ^
373
                      $this->_rightRotate($w[$i - 15], 18) ^
374
                      $this->_rightShift($w[$i - 15], 3);
375
                $s1 = $this->_rightRotate($w[$i - 2], 17) ^
376
                      $this->_rightRotate($w[$i - 2], 19) ^
377
                      $this->_rightShift($w[$i - 2], 10);
378
                // @codingStandardsIgnoreEnd
379
                $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
380
            }
381
382
            // Initialize hash value for this chunk
383
            list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
384
385
            // Main loop
386
            for ($i = 0; $i < 64; $i++) {
387
                $s0 = $this->_rightRotate($a, 2) ^
388
                      $this->_rightRotate($a, 13) ^
389
                      $this->_rightRotate($a, 22);
390
                $maj = ($a & $b) ^
391
                       ($a & $c) ^
392
                       ($b & $c);
393
                $t2 = $this->_add($s0, $maj);
394
395
                $s1 = $this->_rightRotate($e, 6) ^
396
                      $this->_rightRotate($e, 11) ^
397
                      $this->_rightRotate($e, 25);
398
                $ch = ($e & $f) ^
399
                      ($this->_not($e) & $g);
400
                $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
401
402
                $h = $g;
403
                $g = $f;
404
                $f = $e;
405
                $e = $this->_add($d, $t1);
406
                $d = $c;
407
                $c = $b;
408
                $b = $a;
409
                $a = $this->_add($t1, $t2);
410
            }
411
412
            // Add this chunk's hash to result so far
413
            $hash = array(
414
                $this->_add($hash[0], $a),
415
                $this->_add($hash[1], $b),
416
                $this->_add($hash[2], $c),
417
                $this->_add($hash[3], $d),
418
                $this->_add($hash[4], $e),
419
                $this->_add($hash[5], $f),
420
                $this->_add($hash[6], $g),
421
                $this->_add($hash[7], $h)
422
            );
423
        }
424
425
        // Produce the final hash value (big-endian)
426
        return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
427
    }
428
429
    /**
430
     * Pure-PHP implementation of SHA384 and SHA512
431
     *
432
     * @access private
433
     * @param string $m
434
     */
435
    public function _sha512($m)
436
    {
437
        static $init384, $init512, $k;
438
439
        if (!isset($k)) {
440
            // Initialize variables
441
            $init384 = array( // initial values for SHA384
442
                'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
443
                '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
444
            );
445
            $init512 = array( // initial values for SHA512
446
                '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
447
                '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
448
            );
449
450
            for ($i = 0; $i < 8; $i++) {
451
                $init384[$i] = new BigInteger($init384[$i], 16);
452
                $init384[$i]->setPrecision(64);
453
                $init512[$i] = new BigInteger($init512[$i], 16);
454
                $init512[$i]->setPrecision(64);
455
            }
456
457
            // Initialize table of round constants
458
            // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
459
            $k = array(
460
                '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
461
                '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
462
                'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
463
                '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
464
                'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
465
                '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
466
                '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
467
                'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
468
                '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
469
                '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
470
                'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
471
                'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
472
                '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
473
                '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
474
                '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
475
                '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
476
                'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
477
                '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
478
                '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
479
                '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
480
            );
481
482
            for ($i = 0; $i < 80; $i++) {
483
                $k[$i] = new BigInteger($k[$i], 16);
484
            }
485
        }
486
487
        $hash = $this->l == 48 ? $init384 : $init512;
488
489
        // Pre-processing
490
        $length = strlen($m);
491
        // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
492
        $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
493
        $m[$length] = chr(0x80);
494
        // we don't support hashing strings 512MB long
495
        $m.= pack('N4', 0, 0, 0, $length << 3);
496
497
        // Process the message in successive 1024-bit chunks
498
        $chunks = str_split($m, 128);
499
        foreach ($chunks as $chunk) {
500
            $w = array();
501
            for ($i = 0; $i < 16; $i++) {
502
                $temp = new BigInteger($this->_string_shift($chunk, 8), 256);
503
                $temp->setPrecision(64);
504
                $w[] = $temp;
505
            }
506
507
            // Extend the sixteen 32-bit words into eighty 32-bit words
508
            for ($i = 16; $i < 80; $i++) {
509
                $temp = array(
510
                          $w[$i - 15]->bitwise_rightRotate(1),
511
                          $w[$i - 15]->bitwise_rightRotate(8),
512
                          $w[$i - 15]->bitwise_rightShift(7)
513
                );
514
                $s0 = $temp[0]->bitwise_xor($temp[1]);
515
                $s0 = $s0->bitwise_xor($temp[2]);
516
                $temp = array(
517
                          $w[$i - 2]->bitwise_rightRotate(19),
518
                          $w[$i - 2]->bitwise_rightRotate(61),
519
                          $w[$i - 2]->bitwise_rightShift(6)
520
                );
521
                $s1 = $temp[0]->bitwise_xor($temp[1]);
522
                $s1 = $s1->bitwise_xor($temp[2]);
523
                $w[$i] = $w[$i - 16]->copy();
524
                $w[$i] = $w[$i]->add($s0);
525
                $w[$i] = $w[$i]->add($w[$i - 7]);
526
                $w[$i] = $w[$i]->add($s1);
527
            }
528
529
            // Initialize hash value for this chunk
530
            $a = $hash[0]->copy();
531
            $b = $hash[1]->copy();
532
            $c = $hash[2]->copy();
533
            $d = $hash[3]->copy();
534
            $e = $hash[4]->copy();
535
            $f = $hash[5]->copy();
536
            $g = $hash[6]->copy();
537
            $h = $hash[7]->copy();
538
539
            // Main loop
540
            for ($i = 0; $i < 80; $i++) {
541
                $temp = array(
542
                    $a->bitwise_rightRotate(28),
543
                    $a->bitwise_rightRotate(34),
544
                    $a->bitwise_rightRotate(39)
545
                );
546
                $s0 = $temp[0]->bitwise_xor($temp[1]);
547
                $s0 = $s0->bitwise_xor($temp[2]);
548
                $temp = array(
549
                    $a->bitwise_and($b),
550
                    $a->bitwise_and($c),
551
                    $b->bitwise_and($c)
552
                );
553
                $maj = $temp[0]->bitwise_xor($temp[1]);
554
                $maj = $maj->bitwise_xor($temp[2]);
555
                $t2 = $s0->add($maj);
556
557
                $temp = array(
558
                    $e->bitwise_rightRotate(14),
559
                    $e->bitwise_rightRotate(18),
560
                    $e->bitwise_rightRotate(41)
561
                );
562
                $s1 = $temp[0]->bitwise_xor($temp[1]);
563
                $s1 = $s1->bitwise_xor($temp[2]);
564
                $temp = array(
565
                    $e->bitwise_and($f),
566
                    $g->bitwise_and($e->bitwise_not())
567
                );
568
                $ch = $temp[0]->bitwise_xor($temp[1]);
569
                $t1 = $h->add($s1);
570
                $t1 = $t1->add($ch);
571
                $t1 = $t1->add($k[$i]);
572
                $t1 = $t1->add($w[$i]);
573
574
                $h = $g->copy();
575
                $g = $f->copy();
576
                $f = $e->copy();
577
                $e = $d->add($t1);
578
                $d = $c->copy();
579
                $c = $b->copy();
580
                $b = $a->copy();
581
                $a = $t1->add($t2);
582
            }
583
584
            // Add this chunk's hash to result so far
585
            $hash = array(
586
                $hash[0]->add($a),
587
                $hash[1]->add($b),
588
                $hash[2]->add($c),
589
                $hash[3]->add($d),
590
                $hash[4]->add($e),
591
                $hash[5]->add($f),
592
                $hash[6]->add($g),
593
                $hash[7]->add($h)
594
            );
595
        }
596
597
        // Produce the final hash value (big-endian)
598
        // (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs.  as such, we trim the output here)
599
        $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
600
                $hash[4]->toBytes() . $hash[5]->toBytes();
601
        if ($this->l != 48) {
602
            $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
603
        }
604
605
        return $temp;
606
    }
607
608
    /**
609
     * Right Rotate
610
     *
611
     * @access private
612
     * @param int $int
613
     * @param int $amt
614
     * @see self::_sha256()
615
     * @return int
616
     */
617
    public function _rightRotate($int, $amt)
618
    {
619
        $invamt = 32 - $amt;
620
        $mask = (1 << $invamt) - 1;
621
        return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
622
    }
623
624
    /**
625
     * Right Shift
626
     *
627
     * @access private
628
     * @param int $int
629
     * @param int $amt
630
     * @see self::_sha256()
631
     * @return int
632
     */
633
    public function _rightShift($int, $amt)
634
    {
635
        $mask = (1 << (32 - $amt)) - 1;
636
        return ($int >> $amt) & $mask;
637
    }
638
639
    /**
640
     * Not
641
     *
642
     * @access private
643
     * @param int $int
644
     * @see self::_sha256()
645
     * @return int
646
     */
647
    public function _not($int)
648
    {
649
        return ~$int & 0xFFFFFFFF;
650
    }
651
652
    /**
653
     * Add
654
     *
655
     * _sha256() adds multiple unsigned 32-bit integers.  Since PHP doesn't support unsigned integers and since the
656
     * possibility of overflow exists, care has to be taken.  BigInteger could be used but this should be faster.
657
     *
658
     * @param int $...
659
     * @return int
660
     * @see self::_sha256()
661
     * @access private
662
     */
663
    public function _add()
664
    {
665
        static $mod;
666
        if (!isset($mod)) {
667
            $mod = pow(2, 32);
668
        }
669
670
        $result = 0;
671
        $arguments = func_get_args();
672
        foreach ($arguments as $argument) {
673
            $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
674
        }
675
676
        return fmod($result, $mod);
677
    }
678
679
    /**
680
     * String Shift
681
     *
682
     * Inspired by array_shift
683
     *
684
     * @param string $string
685
     * @param int $index
686
     * @return string
687
     * @access private
688
     */
689
    public function _string_shift(&$string, $index = 1)
690
    {
691
        $substr = substr($string, 0, $index);
692
        $string = substr($string, $index);
693
        return $substr;
694
    }
695
}
696