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