PageRenderTime 68ms CodeModel.GetById 2ms app.highlight 58ms RepoModel.GetById 1ms app.codeStats 1ms

/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php

https://github.com/AmaniYunge/greenWeb
PHP | 845 lines | 491 code | 69 blank | 285 comment | 37 complexity | fa8ac79d826596d8e92f1cc5e256a119 MD5 | raw file
  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 * md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
  9 *
 10 * If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
 11 * the hash.  If no valid algorithm is provided, sha1 will be used.
 12 *
 13 * PHP versions 4 and 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('Crypt/Hash.php');
 22 *
 23 *    $hash = new Crypt_Hash('sha1');
 24 *
 25 *    $hash->setKey('abcdefg');
 26 *
 27 *    echo base64_encode($hash->hash('abcdefg'));
 28 * ?>
 29 * </code>
 30 *
 31 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
 32 * of this software and associated documentation files (the "Software"), to deal
 33 * in the Software without restriction, including without limitation the rights
 34 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 35 * copies of the Software, and to permit persons to whom the Software is
 36 * furnished to do so, subject to the following conditions:
 37 *
 38 * The above copyright notice and this permission notice shall be included in
 39 * all copies or substantial portions of the Software.
 40 *
 41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 44 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 45 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 46 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 47 * THE SOFTWARE.
 48 *
 49 * @category  Crypt
 50 * @package   Crypt_Hash
 51 * @author    Jim Wigginton <terrafrost@php.net>
 52 * @copyright MMVII Jim Wigginton
 53 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 54 * @link      http://phpseclib.sourceforge.net
 55 */
 56
 57/**#@+
 58 * @access private
 59 * @see Crypt_Hash::Crypt_Hash()
 60 */
 61/**
 62 * Toggles the internal implementation
 63 */
 64define('CRYPT_HASH_MODE_INTERNAL', 1);
 65/**
 66 * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
 67 */
 68define('CRYPT_HASH_MODE_MHASH',    2);
 69/**
 70 * Toggles the hash() implementation, which works on PHP 5.1.2+.
 71 */
 72define('CRYPT_HASH_MODE_HASH',     3);
 73/**#@-*/
 74
 75/**
 76 * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
 77 *
 78 * @package Crypt_Hash
 79 * @author  Jim Wigginton <terrafrost@php.net>
 80 * @version 0.1.0
 81 * @access  public
 82 */
 83class Crypt_Hash
 84{
 85    /**
 86     * Hash Parameter
 87     *
 88     * @see Crypt_Hash::setHash()
 89     * @var Integer
 90     * @access private
 91     */
 92    var $hashParam;
 93
 94    /**
 95     * Byte-length of compression blocks / key (Internal HMAC)
 96     *
 97     * @see Crypt_Hash::setAlgorithm()
 98     * @var Integer
 99     * @access private
100     */
101    var $b;
102
103    /**
104     * Byte-length of hash output (Internal HMAC)
105     *
106     * @see Crypt_Hash::setHash()
107     * @var Integer
108     * @access private
109     */
110    var $l = false;
111
112    /**
113     * Hash Algorithm
114     *
115     * @see Crypt_Hash::setHash()
116     * @var String
117     * @access private
118     */
119    var $hash;
120
121    /**
122     * Key
123     *
124     * @see Crypt_Hash::setKey()
125     * @var String
126     * @access private
127     */
128    var $key = false;
129
130    /**
131     * Outer XOR (Internal HMAC)
132     *
133     * @see Crypt_Hash::setKey()
134     * @var String
135     * @access private
136     */
137    var $opad;
138
139    /**
140     * Inner XOR (Internal HMAC)
141     *
142     * @see Crypt_Hash::setKey()
143     * @var String
144     * @access private
145     */
146    var $ipad;
147
148    /**
149     * Default Constructor.
150     *
151     * @param optional String $hash
152     * @return Crypt_Hash
153     * @access public
154     */
155    function Crypt_Hash($hash = 'sha1')
156    {
157        if ( !defined('CRYPT_HASH_MODE') ) {
158            switch (true) {
159                case extension_loaded('hash'):
160                    define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
161                    break;
162                case extension_loaded('mhash'):
163                    define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
164                    break;
165                default:
166                    define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
167            }
168        }
169
170        $this->setHash($hash);
171    }
172
173    /**
174     * Sets the key for HMACs
175     *
176     * Keys can be of any length.
177     *
178     * @access public
179     * @param optional String $key
180     */
181    function setKey($key = false)
182    {
183        $this->key = $key;
184    }
185
186    /**
187     * Gets the hash function.
188     *
189     * As set by the constructor or by the setHash() method.
190     *
191     * @access public
192     * @return String
193     */
194    function getHash()
195    {
196        return $this->hashParam;
197    }
198
199    /**
200     * Sets the hash function.
201     *
202     * @access public
203     * @param String $hash
204     */
205    function setHash($hash)
206    {
207        $this->hashParam = $hash = strtolower($hash);
208        switch ($hash) {
209            case 'md5-96':
210            case 'sha1-96':
211                $this->l = 12; // 96 / 8 = 12
212                break;
213            case 'md2':
214            case 'md5':
215                $this->l = 16;
216                break;
217            case 'sha1':
218                $this->l = 20;
219                break;
220            case 'sha256':
221                $this->l = 32;
222                break;
223            case 'sha384':
224                $this->l = 48;
225                break;
226            case 'sha512':
227                $this->l = 64;
228        }
229
230        switch ($hash) {
231            case 'md2':
232                $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
233                    CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
234                break;
235            case 'sha384':
236            case 'sha512':
237                $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
238                break;
239            default:
240                $mode = CRYPT_HASH_MODE;
241        }
242
243        switch ( $mode ) {
244            case CRYPT_HASH_MODE_MHASH:
245                switch ($hash) {
246                    case 'md5':
247                    case 'md5-96':
248                        $this->hash = MHASH_MD5;
249                        break;
250                    case 'sha256':
251                        $this->hash = MHASH_SHA256;
252                        break;
253                    case 'sha1':
254                    case 'sha1-96':
255                    default:
256                        $this->hash = MHASH_SHA1;
257                }
258                return;
259            case CRYPT_HASH_MODE_HASH:
260                switch ($hash) {
261                    case 'md5':
262                    case 'md5-96':
263                        $this->hash = 'md5';
264                        return;
265                    case 'md2':
266                    case 'sha256':
267                    case 'sha384':
268                    case 'sha512':
269                        $this->hash = $hash;
270                        return;
271                    case 'sha1':
272                    case 'sha1-96':
273                    default:
274                        $this->hash = 'sha1';
275                }
276                return;
277        }
278
279        switch ($hash) {
280            case 'md2':
281                 $this->b = 16;
282                 $this->hash = array($this, '_md2');
283                 break;
284            case 'md5':
285            case 'md5-96':
286                 $this->b = 64;
287                 $this->hash = array($this, '_md5');
288                 break;
289            case 'sha256':
290                 $this->b = 64;
291                 $this->hash = array($this, '_sha256');
292                 break;
293            case 'sha384':
294            case 'sha512':
295                 $this->b = 128;
296                 $this->hash = array($this, '_sha512');
297                 break;
298            case 'sha1':
299            case 'sha1-96':
300            default:
301                 $this->b = 64;
302                 $this->hash = array($this, '_sha1');
303        }
304
305        $this->ipad = str_repeat(chr(0x36), $this->b);
306        $this->opad = str_repeat(chr(0x5C), $this->b);
307    }
308
309    /**
310     * Compute the HMAC.
311     *
312     * @access public
313     * @param String $text
314     * @return String
315     */
316    function hash($text)
317    {
318        $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
319
320        if (!empty($this->key) || is_string($this->key)) {
321            switch ( $mode ) {
322                case CRYPT_HASH_MODE_MHASH:
323                    $output = mhash($this->hash, $text, $this->key);
324                    break;
325                case CRYPT_HASH_MODE_HASH:
326                    $output = hash_hmac($this->hash, $text, $this->key, true);
327                    break;
328                case CRYPT_HASH_MODE_INTERNAL:
329                    /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
330                        resultant L byte string as the actual key to HMAC."
331
332                        -- http://tools.ietf.org/html/rfc2104#section-2 */
333                    $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
334
335                    $key    = str_pad($key, $this->b, chr(0));      // step 1
336                    $temp   = $this->ipad ^ $key;                   // step 2
337                    $temp  .= $text;                                // step 3
338                    $temp   = call_user_func($this->hash, $temp);   // step 4
339                    $output = $this->opad ^ $key;                   // step 5
340                    $output.= $temp;                                // step 6
341                    $output = call_user_func($this->hash, $output); // step 7
342            }
343        } else {
344            switch ( $mode ) {
345                case CRYPT_HASH_MODE_MHASH:
346                    $output = mhash($this->hash, $text);
347                    break;
348                case CRYPT_HASH_MODE_HASH:
349                    $output = hash($this->hash, $text, true);
350                    break;
351                case CRYPT_HASH_MODE_INTERNAL:
352                    $output = call_user_func($this->hash, $text);
353            }
354        }
355
356        return substr($output, 0, $this->l);
357    }
358
359    /**
360     * Returns the hash length (in bytes)
361     *
362     * @access public
363     * @return Integer
364     */
365    function getLength()
366    {
367        return $this->l;
368    }
369
370    /**
371     * Wrapper for MD5
372     *
373     * @access private
374     * @param String $m
375     */
376    function _md5($m)
377    {
378        return pack('H*', md5($m));
379    }
380
381    /**
382     * Wrapper for SHA1
383     *
384     * @access private
385     * @param String $m
386     */
387    function _sha1($m)
388    {
389        return pack('H*', sha1($m));
390    }
391
392    /**
393     * Pure-PHP implementation of MD2
394     *
395     * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
396     *
397     * @access private
398     * @param String $m
399     */
400    function _md2($m)
401    {
402        static $s = array(
403             41,  46,  67, 201, 162, 216, 124,   1,  61,  54,  84, 161, 236, 240, 6,
404             19,  98, 167,   5, 243, 192, 199, 115, 140, 152, 147,  43, 217, 188,
405             76, 130, 202,  30, 155,  87,  60, 253, 212, 224,  22, 103,  66, 111, 24,
406            138,  23, 229,  18, 190,  78, 196, 214, 218, 158, 222,  73, 160, 251,
407            245, 142, 187,  47, 238, 122, 169, 104, 121, 145,  21, 178,   7,  63,
408            148, 194,  16, 137,  11,  34,  95,  33, 128, 127,  93, 154,  90, 144, 50,
409             39,  53,  62, 204, 231, 191, 247, 151,   3, 255,  25,  48, 179,  72, 165,
410            181, 209, 215,  94, 146,  42, 172,  86, 170, 198,  79, 184,  56, 210,
411            150, 164, 125, 182, 118, 252, 107, 226, 156, 116,   4, 241,  69, 157,
412            112,  89, 100, 113, 135,  32, 134,  91, 207, 101, 230,  45, 168,   2, 27,
413             96,  37, 173, 174, 176, 185, 246,  28,  70,  97, 105,  52,  64, 126, 15,
414             85,  71, 163,  35, 221,  81, 175,  58, 195,  92, 249, 206, 186, 197,
415            234,  38,  44,  83,  13, 110, 133,  40, 132,   9, 211, 223, 205, 244, 65,
416            129,  77,  82, 106, 220,  55, 200, 108, 193, 171, 250,  36, 225, 123,
417              8,  12, 189, 177,  74, 120, 136, 149, 139, 227,  99, 232, 109, 233,
418            203, 213, 254,  59,   0,  29,  57, 242, 239, 183,  14, 102,  88, 208, 228,
419            166, 119, 114, 248, 235, 117,  75,  10,  49,  68,  80, 180, 143, 237,
420             31,  26, 219, 153, 141,  51, 159,  17, 131, 20
421        );
422
423        // Step 1. Append Padding Bytes
424        $pad = 16 - (strlen($m) & 0xF);
425        $m.= str_repeat(chr($pad), $pad);
426
427        $length = strlen($m);
428
429        // Step 2. Append Checksum
430        $c = str_repeat(chr(0), 16);
431        $l = chr(0);
432        for ($i = 0; $i < $length; $i+= 16) {
433            for ($j = 0; $j < 16; $j++) {
434                // RFC1319 incorrectly states that C[j] should be set to S[c xor L]
435                //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
436                // per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
437                $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
438                $l = $c[$j];
439            }
440        }
441        $m.= $c;
442
443        $length+= 16;
444
445        // Step 3. Initialize MD Buffer
446        $x = str_repeat(chr(0), 48);
447
448        // Step 4. Process Message in 16-Byte Blocks
449        for ($i = 0; $i < $length; $i+= 16) {
450            for ($j = 0; $j < 16; $j++) {
451                $x[$j + 16] = $m[$i + $j];
452                $x[$j + 32] = $x[$j + 16] ^ $x[$j];
453            }
454            $t = chr(0);
455            for ($j = 0; $j < 18; $j++) {
456                for ($k = 0; $k < 48; $k++) {
457                    $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
458                    //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
459                }
460                $t = chr(ord($t) + $j);
461            }
462        }
463
464        // Step 5. Output
465        return substr($x, 0, 16);
466    }
467
468    /**
469     * Pure-PHP implementation of SHA256
470     *
471     * 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}.
472     *
473     * @access private
474     * @param String $m
475     */
476    function _sha256($m)
477    {
478        if (extension_loaded('suhosin')) {
479            return pack('H*', sha256($m));
480        }
481
482        // Initialize variables
483        $hash = array(
484            0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
485        );
486        // Initialize table of round constants
487        // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
488        static $k = array(
489            0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
490            0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
491            0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
492            0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
493            0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
494            0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
495            0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
496            0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
497        );
498
499        // Pre-processing
500        $length = strlen($m);
501        // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
502        $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
503        $m[$length] = chr(0x80);
504        // we don't support hashing strings 512MB long
505        $m.= pack('N2', 0, $length << 3);
506
507        // Process the message in successive 512-bit chunks
508        $chunks = str_split($m, 64);
509        foreach ($chunks as $chunk) {
510            $w = array();
511            for ($i = 0; $i < 16; $i++) {
512                extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
513                $w[] = $temp;
514            }
515
516            // Extend the sixteen 32-bit words into sixty-four 32-bit words
517            for ($i = 16; $i < 64; $i++) {
518                $s0 = $this->_rightRotate($w[$i - 15],  7) ^
519                      $this->_rightRotate($w[$i - 15], 18) ^
520                      $this->_rightShift( $w[$i - 15],  3);
521                $s1 = $this->_rightRotate($w[$i - 2], 17) ^
522                      $this->_rightRotate($w[$i - 2], 19) ^
523                      $this->_rightShift( $w[$i - 2], 10);
524                $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
525
526            }
527
528            // Initialize hash value for this chunk
529            list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
530
531            // Main loop
532            for ($i = 0; $i < 64; $i++) {
533                $s0 = $this->_rightRotate($a,  2) ^
534                      $this->_rightRotate($a, 13) ^
535                      $this->_rightRotate($a, 22);
536                $maj = ($a & $b) ^
537                       ($a & $c) ^
538                       ($b & $c);
539                $t2 = $this->_add($s0, $maj);
540
541                $s1 = $this->_rightRotate($e,  6) ^
542                      $this->_rightRotate($e, 11) ^
543                      $this->_rightRotate($e, 25);
544                $ch = ($e & $f) ^
545                      ($this->_not($e) & $g);
546                $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
547
548                $h = $g;
549                $g = $f;
550                $f = $e;
551                $e = $this->_add($d, $t1);
552                $d = $c;
553                $c = $b;
554                $b = $a;
555                $a = $this->_add($t1, $t2);
556            }
557
558            // Add this chunk's hash to result so far
559            $hash = array(
560                $this->_add($hash[0], $a),
561                $this->_add($hash[1], $b),
562                $this->_add($hash[2], $c),
563                $this->_add($hash[3], $d),
564                $this->_add($hash[4], $e),
565                $this->_add($hash[5], $f),
566                $this->_add($hash[6], $g),
567                $this->_add($hash[7], $h)
568            );
569        }
570
571        // Produce the final hash value (big-endian)
572        return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
573    }
574
575    /**
576     * Pure-PHP implementation of SHA384 and SHA512
577     *
578     * @access private
579     * @param String $m
580     */
581    function _sha512($m)
582    {
583        if (!class_exists('Math_BigInteger')) {
584            include_once 'Math/BigInteger.php';
585        }
586
587        static $init384, $init512, $k;
588
589        if (!isset($k)) {
590            // Initialize variables
591            $init384 = array( // initial values for SHA384
592                'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
593                '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
594            );
595            $init512 = array( // initial values for SHA512
596                '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
597                '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
598            );
599
600            for ($i = 0; $i < 8; $i++) {
601                $init384[$i] = new Math_BigInteger($init384[$i], 16);
602                $init384[$i]->setPrecision(64);
603                $init512[$i] = new Math_BigInteger($init512[$i], 16);
604                $init512[$i]->setPrecision(64);
605            }
606
607            // Initialize table of round constants
608            // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
609            $k = array(
610                '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
611                '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
612                'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
613                '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
614                'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
615                '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
616                '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
617                'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
618                '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
619                '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
620                'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
621                'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
622                '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
623                '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
624                '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
625                '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
626                'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
627                '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
628                '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
629                '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
630            );
631
632            for ($i = 0; $i < 80; $i++) {
633                $k[$i] = new Math_BigInteger($k[$i], 16);
634            }
635        }
636
637        $hash = $this->l == 48 ? $init384 : $init512;
638
639        // Pre-processing
640        $length = strlen($m);
641        // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
642        $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
643        $m[$length] = chr(0x80);
644        // we don't support hashing strings 512MB long
645        $m.= pack('N4', 0, 0, 0, $length << 3);
646
647        // Process the message in successive 1024-bit chunks
648        $chunks = str_split($m, 128);
649        foreach ($chunks as $chunk) {
650            $w = array();
651            for ($i = 0; $i < 16; $i++) {
652                $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
653                $temp->setPrecision(64);
654                $w[] = $temp;
655            }
656
657            // Extend the sixteen 32-bit words into eighty 32-bit words
658            for ($i = 16; $i < 80; $i++) {
659                $temp = array(
660                          $w[$i - 15]->bitwise_rightRotate(1),
661                          $w[$i - 15]->bitwise_rightRotate(8),
662                          $w[$i - 15]->bitwise_rightShift(7)
663                );
664                $s0 = $temp[0]->bitwise_xor($temp[1]);
665                $s0 = $s0->bitwise_xor($temp[2]);
666                $temp = array(
667                          $w[$i - 2]->bitwise_rightRotate(19),
668                          $w[$i - 2]->bitwise_rightRotate(61),
669                          $w[$i - 2]->bitwise_rightShift(6)
670                );
671                $s1 = $temp[0]->bitwise_xor($temp[1]);
672                $s1 = $s1->bitwise_xor($temp[2]);
673                $w[$i] = $w[$i - 16]->copy();
674                $w[$i] = $w[$i]->add($s0);
675                $w[$i] = $w[$i]->add($w[$i - 7]);
676                $w[$i] = $w[$i]->add($s1);
677            }
678
679            // Initialize hash value for this chunk
680            $a = $hash[0]->copy();
681            $b = $hash[1]->copy();
682            $c = $hash[2]->copy();
683            $d = $hash[3]->copy();
684            $e = $hash[4]->copy();
685            $f = $hash[5]->copy();
686            $g = $hash[6]->copy();
687            $h = $hash[7]->copy();
688
689            // Main loop
690            for ($i = 0; $i < 80; $i++) {
691                $temp = array(
692                    $a->bitwise_rightRotate(28),
693                    $a->bitwise_rightRotate(34),
694                    $a->bitwise_rightRotate(39)
695                );
696                $s0 = $temp[0]->bitwise_xor($temp[1]);
697                $s0 = $s0->bitwise_xor($temp[2]);
698                $temp = array(
699                    $a->bitwise_and($b),
700                    $a->bitwise_and($c),
701                    $b->bitwise_and($c)
702                );
703                $maj = $temp[0]->bitwise_xor($temp[1]);
704                $maj = $maj->bitwise_xor($temp[2]);
705                $t2 = $s0->add($maj);
706
707                $temp = array(
708                    $e->bitwise_rightRotate(14),
709                    $e->bitwise_rightRotate(18),
710                    $e->bitwise_rightRotate(41)
711                );
712                $s1 = $temp[0]->bitwise_xor($temp[1]);
713                $s1 = $s1->bitwise_xor($temp[2]);
714                $temp = array(
715                    $e->bitwise_and($f),
716                    $g->bitwise_and($e->bitwise_not())
717                );
718                $ch = $temp[0]->bitwise_xor($temp[1]);
719                $t1 = $h->add($s1);
720                $t1 = $t1->add($ch);
721                $t1 = $t1->add($k[$i]);
722                $t1 = $t1->add($w[$i]);
723
724                $h = $g->copy();
725                $g = $f->copy();
726                $f = $e->copy();
727                $e = $d->add($t1);
728                $d = $c->copy();
729                $c = $b->copy();
730                $b = $a->copy();
731                $a = $t1->add($t2);
732            }
733
734            // Add this chunk's hash to result so far
735            $hash = array(
736                $hash[0]->add($a),
737                $hash[1]->add($b),
738                $hash[2]->add($c),
739                $hash[3]->add($d),
740                $hash[4]->add($e),
741                $hash[5]->add($f),
742                $hash[6]->add($g),
743                $hash[7]->add($h)
744            );
745        }
746
747        // Produce the final hash value (big-endian)
748        // (Crypt_Hash::hash() trims the output for hashes but not for HMACs.  as such, we trim the output here)
749        $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
750                $hash[4]->toBytes() . $hash[5]->toBytes();
751        if ($this->l != 48) {
752            $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
753        }
754
755        return $temp;
756    }
757
758    /**
759     * Right Rotate
760     *
761     * @access private
762     * @param Integer $int
763     * @param Integer $amt
764     * @see _sha256()
765     * @return Integer
766     */
767    function _rightRotate($int, $amt)
768    {
769        $invamt = 32 - $amt;
770        $mask = (1 << $invamt) - 1;
771        return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
772    }
773
774    /**
775     * Right Shift
776     *
777     * @access private
778     * @param Integer $int
779     * @param Integer $amt
780     * @see _sha256()
781     * @return Integer
782     */
783    function _rightShift($int, $amt)
784    {
785        $mask = (1 << (32 - $amt)) - 1;
786        return ($int >> $amt) & $mask;
787    }
788
789    /**
790     * Not
791     *
792     * @access private
793     * @param Integer $int
794     * @see _sha256()
795     * @return Integer
796     */
797    function _not($int)
798    {
799        return ~$int & 0xFFFFFFFF;
800    }
801
802    /**
803     * Add
804     *
805     * _sha256() adds multiple unsigned 32-bit integers.  Since PHP doesn't support unsigned integers and since the
806     * possibility of overflow exists, care has to be taken.  Math_BigInteger() could be used but this should be faster.
807     *
808     * @param Integer $...
809     * @return Integer
810     * @see _sha256()
811     * @access private
812     */
813    function _add()
814    {
815        static $mod;
816        if (!isset($mod)) {
817            $mod = pow(2, 32);
818        }
819
820        $result = 0;
821        $arguments = func_get_args();
822        foreach ($arguments as $argument) {
823            $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
824        }
825
826        return fmod($result, $mod);
827    }
828
829    /**
830     * String Shift
831     *
832     * Inspired by array_shift
833     *
834     * @param String $string
835     * @param optional Integer $index
836     * @return String
837     * @access private
838     */
839    function _string_shift(&$string, $index = 1)
840    {
841        $substr = substr($string, 0, $index);
842        $string = substr($string, $index);
843        return $substr;
844    }
845}