PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / extra / hub-connector / lib / PHPSecLib / Crypt / Hash.php

Hash.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at extra/hub-connector/lib/PHPSecLib/Crypt/Hash.php

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