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