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