[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/phpseclib/ -> Crypt_Hash.php (source)

   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  }