/*
 *  Avis event router.
 *  
 *  Copyright (C) 2008 Matthew Phillips <avis@mattp.name>
 *
 *  This program is free software: you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  version 3 as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.avis.security;

/*
 * Modified version of SHA1 class from URL below. Removed dependence on Sun
 * JCE.
 * 
 * http://www.limewire.org/fisheye/viewrep/~raw,r=1.2/limecvs/core/com/limegroup/gnutella/SHA1.java 
 * 
 * @author Matthew Phillips
 */

/*
 * @(#)SHA1.java   1.9 2004-04-22
 * This file was freely contributed to the LimeWire project and is covered
 * by its existing GPL licence, but it may be used individually as a public
 * domain implementation of a published algorithm (see below for references).
 * It was also freely contributed to the Bitzi public domain sources.
 * @author  Philippe Verdy
 */

/**
 * Implements the SHA-1 secure hash algorithm.
 * <p>
 * The FIPS PUB 180-2 standard specifies four secure hash algorithms (SHA-1,
 * SHA-256, SHA-384 and SHA-512) for computing a condensed representation of
 * electronic data (message). When a message of any length < 2^^64 bits (for
 * SHA-1 and SHA-256) or < 2^^128 bits (for SHA-384 and SHA-512) is input to an
 * algorithm, the result is an output called a message digest. The message
 * digests range in length from 160 to 512 bits, depending on the algorithm.
 * Secure hash algorithms are typically used with other cryptographic
 * algorithms, such as digital signature algorithms and keyed-hash message
 * authentication codes, or in the generation of random numbers (bits).
 * </p>
 * 
 * <p>
 * The four hash algorithms specified in this "SHS" standard are called secure
 * because, for a given algorithm, it is computationally infeasible 1) to find a
 * message that corresponds to a given message digest, or 2) to find two
 * different messages that produce the same message digest. Any change to a
 * message will, with a very high probability, result in a different message
 * digest. This will result in a verification failure when the secure hash
 * algorithm is used with a digital signature algorithm or a keyed-hash message
 * authentication algorithm.
 * </p>
 * 
 * <p>
 * A "SHS change notice" adds a SHA-224 algorithm for interoperability, which,
 * like SHA-1 and SHA-256, operates on 512-bit blocks and 32-bit words,
 * </p>
 * 
 * <p>
 * <b>References: </b>
 * </p>
 * <ol>
 * <li>NIST FIPS PUB 180-2, "Secure Hash Signature Standard (SHS) with change
 * notice", National Institute of Standards and Technology (NIST), 2002 August
 * 1, and U.S. Department of Commerce, August 26. <br>
 * <a href="http://csrc.ncsl.nist.gov/CryptoToolkit/Hash.html">
 * http://csrc.ncsl.nist.gov/CryptoToolkit/Hash.html </a>
 * <li>NIST FIPS PUB 180-1, "Secure Hash Standard", U.S. Department of
 * Commerce, May 1993. <br>
 * <a href="http://www.itl.nist.gov/div897/pubs/fip180-1.htm">
 * http://www.itl.nist.gov/div897/pubs/fip180-1.htm </a></li>
 * <li>Bruce Schneier, "Section 18.7 Secure Hash Algorithm (SHA)",
 * <cite>Applied Cryptography, 2nd edition </cite>, <br>
 * John Wiley &amp; Sons, 1996</li>
 * </ol>
 */
public final class SHA1 implements Cloneable
{

  /**
   * This implementation returns a fixed-size digest.
   */
  private static final int SHA1_LENGTH = 20; // bytes == 160 bits

  /**
   * Private context for incomplete blocks and padding bytes. INVARIANT: padding
   * must be in 0..63. When the padding reaches 64, a new block is computed, and
   * the 56 last bytes are kept in the padding history.
   */
  private byte [] pad;
  private int padding;

  /**
   * Private contextual byte count, sent in the next block, after the ending
   * padding block.
   */
  private long bytes;

  /**
   * Private context that contains the current digest key.
   */
  private int hA, hB, hC, hD, hE;

  /**
   * Creates a SHA1 object with default initial state.
   */
  public SHA1 ()
  {
    pad = new byte [64];
    engineReset ();
  }

  /**
   * Creates a SHA1 object with state (for cloning).
   * 
   * @param state
   *          the existing object to clone
   */
  public SHA1 (final SHA1 state)
  {
    this ();
    pad = state.pad.clone ();
    padding = state.padding;
    bytes = state.bytes;
    hA = state.hA;
    hB = state.hB;
    hC = state.hC;
    hD = state.hD;
    hE = state.hE;
  }

  /**
   * Clones this object.
   */
  @Override
  public Object clone ()
  {
    SHA1 that = null;
    try
    {
      that = (SHA1)super.clone ();
      that.pad = this.pad.clone ();
      that.padding = this.padding;
      that.bytes = this.bytes;
      that.hA = this.hA;
      that.hB = this.hB;
      that.hC = this.hC;
      that.hD = this.hD;
      that.hE = this.hE;
    } catch (CloneNotSupportedException e)
    {
      // not possible
    }
    return that;
  }

  /**
   * Returns the digest length in bytes.
   * 
   * Can be used to allocate your own output buffer when computing multiple
   * digests.
   * 
   * Overrides the protected abstract method of
   * <code>java.security.MessageDigestSpi</code>.
   * @return the digest length in bytes.
   */
  public int engineGetDigestLength ()
  {
    return SHA1_LENGTH;
  }

  /**
   * Initialize or reset the digest context.
   * 
   * Overrides the protected abstract method of
   * <code>java.security.MessageDigestSpi</code>.
   */
  protected void engineReset ()
  {
    int i = 60;
    do
    {
      pad [i] = (byte)0x00;
      pad [i + 1] = (byte)0x00;
      pad [i + 2] = (byte)0x00;
      pad [i + 3] = (byte)0x00;
    } while ((i -= 4) >= 0);
    padding = 0;
    bytes = 0;
    hA = 0x67452301;
    hB = 0xefcdab89;
    hC = 0x98badcfe;
    hD = 0x10325476;
    hE = 0xc3d2e1f0;
  }

  /**
   * Updates the digest using the specified byte. Requires internal buffering,
   * and may be slow.
   * 
   * Overrides the protected abstract method of java.security.MessageDigestSpi.
   * @param input
   *          the byte to use for the update.
   */
  public void engineUpdate (byte input)
  {
    bytes++;
    pad [padding] = input;
    if (++padding == 64)
    {
      computeBlock (pad, 0);
      padding = 0;
    }
  }

  /**
   * Updates the digest using the specified array of bytes, starting at the
   * specified offset.
   * 
   * Input length can be any size. May require internal buffering, if input
   * blocks are not multiple of 64 bytes.
   * 
   * Overrides the protected abstract method of java.security.MessageDigestSpi.
   * @param input
   *          the array of bytes to use for the update.
   * @param offset
   *          the offset to start from in the array of bytes.
   * @param len
   *          the number of bytes to use, starting at offset.
   */
  public void engineUpdate (byte [] input, int offset, int len)
  {
    if (offset >= 0 && len >= 0 && offset + len <= input.length)
    {
      bytes += len;
      int padlen;
      if (padding > 0 && len >= (padlen = 64 - padding))
      {
        System.arraycopy (input, offset, pad, padding, padlen);
        computeBlock (pad, 0);
        padding = 0;
        offset += padlen;
        len -= padlen;
      }
      while (len >= 64)
      {
        computeBlock (input, offset);
        offset += 64;
        len -= 64;
      }
      if (len > 0)
      {
        System.arraycopy (input, offset, pad, padding, len);
        padding += len;
      }
      return;
    }
    throw new ArrayIndexOutOfBoundsException ();
  }

  /**
   * Completes the hash computation by performing final operations such as
   * padding. Computes the final hash and returns the final value as a byte[20]
   * array. Once engineDigest has been called, the engine will be automatically
   * reset as specified in the JavaSecurity MessageDigest specification.
   * 
   * For faster operations with multiple digests, allocate your own array and
   * use engineDigest(byte[], int offset, int len).
   * 
   * Overrides the protected abstract method of java.security.MessageDigestSpi.
   * @return the length of the digest stored in the output buffer.
   */
  public byte [] engineDigest ()
  {
    byte hashvalue[] = new byte [SHA1_LENGTH];
    engineDigest (hashvalue, 0, hashvalue.length);
    return hashvalue;
  }

  /**
   * Completes the hash computation by performing final operations such as
   * padding. Once engineDigest has been called, the engine will be
   * automatically reset (see engineReset).
   * 
   * Overrides the protected abstract method of java.security.MessageDigestSpi.
   * @param hashvalue
   *          the output buffer in which to store the digest.
   * @param offset
   *          offset to start from in the output buffer
   * @param len
   *          number of bytes within buf allotted for the digest. Both this
   *          default implementation and the SUN provider do not return partial
   *          digests. The presence of this parameter is solely for consistency
   *          in our API's. If the value of this parameter is less than the
   *          actual digest length, the method will throw a DigestException.
   *          This parameter is ignored if its value is greater than or equal to
   *          the actual digest length.
   * @return the length of the digest stored in the output buffer.
   */
  public int engineDigest (byte [] hashvalue, int offset, int len)
  {
    if (len < SHA1_LENGTH)
      throw new IllegalArgumentException ("partial digests not returned");
    if (hashvalue.length - offset < SHA1_LENGTH)
      throw new IllegalArgumentException (
          "insufficient space in output buffer to store the digest");
    // Flush the trailing bytes, adding padding bytes into last blocks.
    int temp;
    // Add padding null bytes but replace the last 8 padding bytes by
    // the little-endian 64-bit digested message bit-length.
    pad [temp = padding] = (byte)0x80; // required first padding byte value!
    // Check if 8 bytes available in pad to store the total message size
    switch (temp)
    { // INVARIANT: temp must be in [0..63]
      case 56:
        pad [57] = (byte)0x00; // no break; falls thru
      case 57:
        pad [58] = (byte)0x00; // no break; falls thru
      case 58:
        pad [59] = (byte)0x00; // no break; falls thru
      case 59:
        pad [60] = (byte)0x00; // no break; falls thru
      case 60:
        pad [61] = (byte)0x00; // no break; falls thru
      case 61:
        pad [62] = (byte)0x00; // no break; falls thru
      case 62:
        pad [63] = (byte)0x00; // no break; falls thru
      case 63:
        computeBlock (pad, 0);
        // Clear the 56 first bytes of pad[].
        temp = 52;
        do
        {
          pad [temp] = (byte)0x00;
          pad [temp + 1] = (byte)0x00;
          pad [temp + 2] = (byte)0x00;
          pad [temp + 3] = (byte)0x00;
        } while ((temp -= 4) >= 0);
        break;
      case 52:
        pad [53] = (byte)0x00; // no break; falls thru
      case 53:
        pad [54] = (byte)0x00; // no break; falls thru
      case 54:
        pad [55] = (byte)0x00; // no break; falls thru
      case 55:
        break;
      default: // Clear the rest of 56 first bytes of pad[].
        switch (temp & 3)
        {
          case 3:
            temp++;
            break;
          case 2:
            pad [(temp += 2) - 1] = (byte)0x00;
            break;
          case 1:
            pad [(temp += 3) - 2] = (byte)0x00;
            pad [temp - 1] = (byte)0x00;
            break;
          case 0:
            pad [(temp += 4) - 3] = (byte)0x00;
            pad [temp - 2] = (byte)0x00;
            pad [temp - 1] = (byte)0x00;
        }
        do
        {
          pad [temp] = (byte)0x00;
          pad [temp + 1] = (byte)0x00;
          pad [temp + 2] = (byte)0x00;
          pad [temp + 3] = (byte)0x00;
        } while ((temp += 4) < 56);
    }
    // Convert the message size from bytes to bits (big endian).
    pad [56] = (byte)((temp = (int)(bytes >>> 29)) >>> 24);
    pad [57] = (byte)(temp >>> 16);
    pad [58] = (byte)(temp >>> 8);
    pad [59] = (byte)temp;
    pad [60] = (byte)((temp = (int)bytes << 3) >>> 24);
    pad [61] = (byte)(temp >>> 16);
    pad [62] = (byte)(temp >>> 8);
    pad [63] = (byte)temp;
    computeBlock (pad, 0);
    // Return the computed digest in big-endian byte order.
    hashvalue [offset] = (byte)(hA >>> 24);
    hashvalue [offset + 1] = (byte)(hA >>> 16);
    hashvalue [offset + 2] = (byte)(hA >>> 8);
    hashvalue [offset + 3] = (byte)hA;
    hashvalue [offset + 4] = (byte)(hB >>> 24);
    hashvalue [offset += 5] = (byte)(hB >>> 16);
    hashvalue [offset + 1] = (byte)(hB >>> 8);
    hashvalue [offset + 2] = (byte)hB;
    hashvalue [offset + 3] = (byte)(hC >>> 24);
    hashvalue [offset + 4] = (byte)(hC >>> 16);
    hashvalue [offset += 5] = (byte)(hC >>> 8);
    hashvalue [offset + 1] = (byte)hC;
    hashvalue [offset + 2] = (byte)(hD >>> 24);
    hashvalue [offset + 3] = (byte)(hD >>> 16);
    hashvalue [offset + 4] = (byte)(hD >>> 8);
    hashvalue [offset += 5] = (byte)hD;
    hashvalue [offset + 1] = (byte)(hE >>> 24);
    hashvalue [offset + 2] = (byte)(hE >>> 16);
    hashvalue [offset + 3] = (byte)(hE >>> 8);
    hashvalue [offset + 4] = (byte)hE;
    engineReset (); // clear the evidence
    return SHA1_LENGTH;
  }

  /**
   * Updates the digest using the specified array of bytes, starting at the
   * specified offset, but an implied length of exactly 64 bytes.
   * 
   * Requires no internal buffering, but assumes a fixed input size, in which
   * the required padding bytes may have been added.
   * 
   * @param input
   *          the array of bytes to use for the update.
   * @param offset
   *          the offset to start from in the array of bytes.
   */
  private void computeBlock (final byte [] input, int offset)
  {
    /*
     * Local temporary work variables for intermediate digests.
     */
    int a, b, c, d, e;

    /*
     * Cache the input block into the local working set of 64-bit values, in
     * big-endian byte order. Be careful when widening bytes or integers due to
     * sign extension !
     */
    int i00, i01, i02, i03, i04, i05, i06, i07, i08, i09, i10, i11, i12, i13, i14, i15;

    /*
     * Use hash schedule function Ch (rounds 0..19): Ch(x,y,z) = (x & y) ^ (~x &
     * z) = (x & (y ^ z)) ^ z, and K00 = .... = K19 = 0x5a827999.
     */
    /*
     * First pass, on big endian input (rounds 0..15).
     */
    e = hE
        + (((a = hA) << 5) | (a >>> 27))
        + 0x5a827999 // K00
        + (((b = hB) & ((c = hC) ^ (d = hD))) ^ d) // Ch(b,c,d)
        + (i00 = input [offset] << 24
            | (input [offset + 1] & 0xff) << 16
            | (input [offset + 2] & 0xff) << 8
            | (input [offset + 3] & 0xff)); // W00
    d += ((e << 5) | (e >>> 27))
        + 0x5a827999 // K01
        + ((a & ((b = (b << 30) | (b >>> 2)) ^ c)) ^ c) // Ch(a,b,c)
        + (i01 = input [offset + 4] << 24
            | (input [offset += 5] & 0xff) << 16
            | (input [offset + 1] & 0xff) << 8
            | (input [offset + 2] & 0xff)); // W01
    c += ((d << 5) | (d >>> 27))
        + 0x5a827999 // K02
        + ((e & ((a = (a << 30) | (a >>> 2)) ^ b)) ^ b) // Ch(e,a,b)
        + (i02 = input [offset + 3] << 24
            | (input [offset + 4] & 0xff) << 16
            | (input [offset += 5] & 0xff) << 8
            | (input [offset + 1] & 0xff)); // W02
    b += ((c << 5) | (c >>> 27))
        + 0x5a827999 // K03
        + ((d & ((e = (e << 30) | (e >>> 2)) ^ a)) ^ a) // Ch(d,e,a)
        + (i03 = input [offset + 2] << 24
            | (input [offset + 3] & 0xff) << 16
            | (input [offset + 4] & 0xff) << 8
            | (input [offset += 5] & 0xff)); // W03
    a += ((b << 5) | (b >>> 27))
        + 0x5a827999 // K04
        + ((c & ((d = (d << 30) | (d >>> 2)) ^ e)) ^ e) // Ch(c,d,e)
        + (i04 = input [offset + 1] << 24
            | (input [offset + 2] & 0xff) << 16
            | (input [offset + 3] & 0xff) << 8
            | (input [offset + 4] & 0xff)); // W04
    e += ((a << 5) | (a >>> 27))
        + 0x5a827999 // K05
        + ((b & ((c = (c << 30) | (c >>> 2)) ^ d)) ^ d) // Ch(b,c,d)
        + (i05 = input [offset += 5] << 24
            | (input [offset + 1] & 0xff) << 16
            | (input [offset + 2] & 0xff) << 8
            | (input [offset + 3] & 0xff)); // W05
    d += ((e << 5) | (e >>> 27))
        + 0x5a827999 // K06
        + ((a & ((b = (b << 30) | (b >>> 2)) ^ c)) ^ c) // Ch(a,b,c)
        + (i06 = input [offset + 4] << 24
            | (input [offset += 5] & 0xff) << 16
            | (input [offset + 1] & 0xff) << 8
            | (input [offset + 2] & 0xff)); // W06
    c += ((d << 5) | (d >>> 27))
        + 0x5a827999 // K07
        + ((e & ((a = (a << 30) | (a >>> 2)) ^ b)) ^ b) // Ch(e,a,b)
        + (i07 = input [offset + 3] << 24
            | (input [offset + 4] & 0xff) << 16
            | (input [offset += 5] & 0xff) << 8
            | (input [offset + 1] & 0xff)); // W07
    b += ((c << 5) | (c >>> 27))
        + 0x5a827999 // K08
        + ((d & ((e = (e << 30) | (e >>> 2)) ^ a)) ^ a) // Ch(d,e,a)
        + (i08 = input [offset + 2] << 24
            | (input [offset + 3] & 0xff) << 16
            | (input [offset + 4] & 0xff) << 8
            | (input [offset += 5] & 0xff)); // W08
    a += ((b << 5) | (b >>> 27))
        + 0x5a827999 // K09
        + ((c & ((d = (d << 30) | (d >>> 2)) ^ e)) ^ e) // Ch(c,d,e)
        + (i09 = input [offset + 1] << 24
            | (input [offset + 2] & 0xff) << 16
            | (input [offset + 3] & 0xff) << 8
            | (input [offset + 4] & 0xff)); // W09
    e += ((a << 5) | (a >>> 27))
        + 0x5a827999 // K10
        + ((b & ((c = (c << 30) | (c >>> 2)) ^ d)) ^ d) // Ch(b,c,d)
        + (i10 = input [offset += 5] << 24
            | (input [offset + 1] & 0xff) << 16
            | (input [offset + 2] & 0xff) << 8
            | (input [offset + 3] & 0xff)); // W10
    d += ((e << 5) | (e >>> 27))
        + 0x5a827999 // K11
        + ((a & ((b = (b << 30) | (b >>> 2)) ^ c)) ^ c) // Ch(a,b,c)
        + (i11 = input [offset + 4] << 24
            | (input [offset += 5] & 0xff) << 16
            | (input [offset + 1] & 0xff) << 8
            | (input [offset + 2] & 0xff)); // W11
    c += ((d << 5) | (d >>> 27))
        + 0x5a827999 // K12
        + ((e & ((a = (a << 30) | (a >>> 2)) ^ b)) ^ b) // Ch(e,a,b)
        + (i12 = input [offset + 3] << 24
            | (input [offset + 4] & 0xff) << 16
            | (input [offset += 5] & 0xff) << 8
            | (input [offset + 1] & 0xff)); // W12
    b += ((c << 5) | (c >>> 27))
        + 0x5a827999 // K13
        + ((d & ((e = (e << 30) | (e >>> 2)) ^ a)) ^ a) // Ch(d,e,a)
        + (i13 = input [offset + 2] << 24
            | (input [offset + 3] & 0xff) << 16
            | (input [offset + 4] & 0xff) << 8
            | (input [offset += 5] & 0xff)); // W13
    a += ((b << 5) | (b >>> 27))
        + 0x5a827999 // K14
        + ((c & ((d = (d << 30) | (d >>> 2)) ^ e)) ^ e) // Ch(c,d,e)
        + (i14 = input [offset + 1] << 24
            | (input [offset + 2] & 0xff) << 16
            | (input [offset + 3] & 0xff) << 8
            | (input [offset + 4] & 0xff)); // W14
    e += ((a << 5) | (a >>> 27))
        + 0x5a827999 // K15
        + ((b & ((c = (c << 30) | (c >>> 2)) ^ d)) ^ d) // Ch(b,c,d)
        + (i15 = input [offset += 5] << 24
            | (input [offset + 1] & 0xff) << 16
            | (input [offset + 2] & 0xff) << 8
            | (input [offset + 3] & 0xff)); // W15

    /*
     * Second pass, on scheduled input (rounds 16..31).
     */
    d += ((e << 5) | (e >>> 27)) + 0x5a827999 // K16
        + ((a & ((b = (b << 30) | (b >>> 2)) ^ c)) ^ c) // Ch(a,b,c)
        + (i00 = ((i00 ^= i02 ^ i08 ^ i13) << 1) | (i00 >>> 31)); // W16
    c += ((d << 5) | (d >>> 27)) + 0x5a827999 // K17
        + ((e & ((a = (a << 30) | (a >>> 2)) ^ b)) ^ b) // Ch(e,a,b)
        + (i01 = ((i01 ^= i03 ^ i09 ^ i14) << 1) | (i01 >>> 31)); // W17
    b += ((c << 5) | (c >>> 27)) + 0x5a827999 // K18
        + ((d & ((e = (e << 30) | (e >>> 2)) ^ a)) ^ a) // Ch(d,e,a)
        + (i02 = ((i02 ^= i04 ^ i10 ^ i15) << 1) | (i02 >>> 31)); // W18
    a += ((b << 5) | (b >>> 27)) + 0x5a827999 // K19
        + ((c & ((d = (d << 30) | (d >>> 2)) ^ e)) ^ e) // Ch(c,d,e)
        + (i03 = ((i03 ^= i05 ^ i11 ^ i00) << 1) | (i03 >>> 31)); // W19

    /*
     * Use hash schedule function Parity (rounds 20..39): Parity(x,y,z) = x ^ y ^
     * z, and K20 = .... = K39 = 0x6ed9eba1.
     */
    e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K20
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i04 = ((i04 ^= i06 ^ i12 ^ i01) << 1) | (i04 >>> 31)); // W20
    d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K21
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i05 = ((i05 ^= i07 ^ i13 ^ i02) << 1) | (i05 >>> 31)); // W21
    c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K22
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i06 = ((i06 ^= i08 ^ i14 ^ i03) << 1) | (i06 >>> 31)); // W22
    b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K23
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i07 = ((i07 ^= i09 ^ i15 ^ i04) << 1) | (i07 >>> 31)); // W23
    a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K24
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i08 = ((i08 ^= i10 ^ i00 ^ i05) << 1) | (i08 >>> 31)); // W24
    e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K25
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i09 = ((i09 ^= i11 ^ i01 ^ i06) << 1) | (i09 >>> 31)); // W25
    d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K26
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i10 = ((i10 ^= i12 ^ i02 ^ i07) << 1) | (i10 >>> 31)); // W26
    c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K27
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i11 = ((i11 ^= i13 ^ i03 ^ i08) << 1) | (i11 >>> 31)); // W27
    b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K28
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i12 = ((i12 ^= i14 ^ i04 ^ i09) << 1) | (i12 >>> 31)); // W28
    a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K29
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i13 = ((i13 ^= i15 ^ i05 ^ i10) << 1) | (i13 >>> 31)); // W29
    e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K30
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i14 = ((i14 ^= i00 ^ i06 ^ i11) << 1) | (i14 >>> 31)); // W30
    d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K31
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i15 = ((i15 ^= i01 ^ i07 ^ i12) << 1) | (i15 >>> 31)); // W31

    /*
     * Third pass, on scheduled input (rounds 32..47).
     */
    c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K32
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i00 = ((i00 ^= i02 ^ i08 ^ i13) << 1) | (i00 >>> 31)); // W32
    b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K33
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i01 = ((i01 ^= i03 ^ i09 ^ i14) << 1) | (i01 >>> 31)); // W33
    a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K34
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i02 = ((i02 ^= i04 ^ i10 ^ i15) << 1) | (i02 >>> 31)); // W34
    e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K35
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i03 = ((i03 ^= i05 ^ i11 ^ i00) << 1) | (i03 >>> 31)); // W35
    d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K36
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i04 = ((i04 ^= i06 ^ i12 ^ i01) << 1) | (i04 >>> 31)); // W36
    c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K37
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i05 = ((i05 ^= i07 ^ i13 ^ i02) << 1) | (i05 >>> 31)); // W37
    b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K38
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i06 = ((i06 ^= i08 ^ i14 ^ i03) << 1) | (i06 >>> 31)); // W38
    a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K39
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i07 = ((i07 ^= i09 ^ i15 ^ i04) << 1) | (i07 >>> 31)); // W39

    /*
     * Use hash schedule function Maj (rounds 40..59): Maj(x,y,z) = (x & y)^(x &
     * z)^(y & z) = ((x & y)|((x | y)& z)), and K40 = .... = K59 = 0x8f1bbcdc.
     */
    e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K40
        + ((b & (c = (c << 30) | (c >>> 2))) | ((b | c) & d)) //Maj(b,c,d)
        + (i08 = ((i08 ^= i10 ^ i00 ^ i05) << 1) | (i08 >>> 31)); // W40
    d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K41
        + ((a & (b = (b << 30) | (b >>> 2))) | ((a | b) & c)) //Maj(a,b,c)
        + (i09 = ((i09 ^= i11 ^ i01 ^ i06) << 1) | (i09 >>> 31)); // W41
    c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K42
        + ((e & (a = (a << 30) | (a >>> 2))) | ((e | a) & b)) //Maj(e,a,b)
        + (i10 = ((i10 ^= i12 ^ i02 ^ i07) << 1) | (i10 >>> 31)); // W42
    b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K43
        + ((d & (e = (e << 30) | (e >>> 2))) | ((d | e) & a)) //Maj(d,e,a)
        + (i11 = ((i11 ^= i13 ^ i03 ^ i08) << 1) | (i11 >>> 31)); // W43
    a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K44
        + ((c & (d = (d << 30) | (d >>> 2))) | ((c | d) & e)) //Maj(c,d,e)
        + (i12 = ((i12 ^= i14 ^ i04 ^ i09) << 1) | (i12 >>> 31)); // W44
    e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K45
        + ((b & (c = (c << 30) | (c >>> 2))) | ((b | c) & d)) //Maj(b,c,d)
        + (i13 = ((i13 ^= i15 ^ i05 ^ i10) << 1) | (i13 >>> 31)); // W45
    d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K46
        + ((a & (b = (b << 30) | (b >>> 2))) | ((a | b) & c)) //Maj(a,b,c)
        + (i14 = ((i14 ^= i00 ^ i06 ^ i11) << 1) | (i14 >>> 31)); // W46
    c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K47
        + ((e & (a = (a << 30) | (a >>> 2))) | ((e | a) & b)) //Maj(e,a,b)
        + (i15 = ((i15 ^= i01 ^ i07 ^ i12) << 1) | (i15 >>> 31)); // W47

    /*
     * Fourth pass, on scheduled input (rounds 48..63).
     */
    b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K48
        + ((d & (e = (e << 30) | (e >>> 2))) | ((d | e) & a)) //Maj(d,e,a)
        + (i00 = ((i00 ^= i02 ^ i08 ^ i13) << 1) | (i00 >>> 31)); // W48
    a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K49
        + ((c & (d = (d << 30) | (d >>> 2))) | ((c | d) & e)) //Maj(c,d,e)
        + (i01 = ((i01 ^= i03 ^ i09 ^ i14) << 1) | (i01 >>> 31)); // W49
    e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K50
        + ((b & (c = (c << 30) | (c >>> 2))) | ((b | c) & d)) //Maj(b,c,d)
        + (i02 = ((i02 ^= i04 ^ i10 ^ i15) << 1) | (i02 >>> 31)); // W50
    d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K51
        + ((a & (b = (b << 30) | (b >>> 2))) | ((a | b) & c)) //Maj(a,b,c)
        + (i03 = ((i03 ^= i05 ^ i11 ^ i00) << 1) | (i03 >>> 31)); // W51
    c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K52
        + ((e & (a = (a << 30) | (a >>> 2))) | ((e | a) & b)) //Maj(e,a,b)
        + (i04 = ((i04 ^= i06 ^ i12 ^ i01) << 1) | (i04 >>> 31)); // W52
    b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K53
        + ((d & (e = (e << 30) | (e >>> 2))) | ((d | e) & a)) //Maj(d,e,a)
        + (i05 = ((i05 ^= i07 ^ i13 ^ i02) << 1) | (i05 >>> 31)); // W53
    a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K54
        + ((c & (d = (d << 30) | (d >>> 2))) | ((c | d) & e)) //Maj(c,d,e)
        + (i06 = ((i06 ^= i08 ^ i14 ^ i03) << 1) | (i06 >>> 31)); // W54
    e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K55
        + ((b & (c = (c << 30) | (c >>> 2))) | ((b | c) & d)) //Maj(b,c,d)
        + (i07 = ((i07 ^= i09 ^ i15 ^ i04) << 1) | (i07 >>> 31)); // W55
    d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K56
        + ((a & (b = (b << 30) | (b >>> 2))) | ((a | b) & c)) //Maj(a,b,c)
        + (i08 = ((i08 ^= i10 ^ i00 ^ i05) << 1) | (i08 >>> 31)); // W56
    c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K57
        + ((e & (a = (a << 30) | (a >>> 2))) | ((e | a) & b)) //Maj(e,a,b)
        + (i09 = ((i09 ^= i11 ^ i01 ^ i06) << 1) | (i09 >>> 31)); // W57
    b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K58
        + ((d & (e = (e << 30) | (e >>> 2))) | ((d | e) & a)) //Maj(d,e,a)
        + (i10 = ((i10 ^= i12 ^ i02 ^ i07) << 1) | (i10 >>> 31)); // W58
    a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K59
        + ((c & (d = (d << 30) | (d >>> 2))) | ((c | d) & e)) //Maj(c,d,e)
        + (i11 = ((i11 ^= i13 ^ i03 ^ i08) << 1) | (i11 >>> 31)); // W59

    /*
     * Use hash schedule function Parity (rounds 60..79): Parity(x,y,z) = x ^ y ^
     * z, and K60 = .... = K79 = 0xca62c1d6.
     */
    e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K60
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i12 = ((i12 ^= i14 ^ i04 ^ i09) << 1) | (i12 >>> 31)); // W60
    d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K61
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i13 = ((i13 ^= i15 ^ i05 ^ i10) << 1) | (i13 >>> 31)); // W61
    c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K62
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i14 = ((i14 ^= i00 ^ i06 ^ i11) << 1) | (i14 >>> 31)); // W62
    b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K63
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i15 = ((i15 ^= i01 ^ i07 ^ i12) << 1) | (i15 >>> 31)); // W63

    /*
     * Fifth pass, on scheduled input (rounds 64..79).
     */
    a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K64
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i00 = ((i00 ^= i02 ^ i08 ^ i13) << 1) | (i00 >>> 31)); // W64
    e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K65
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i01 = ((i01 ^= i03 ^ i09 ^ i14) << 1) | (i01 >>> 31)); // W65
    d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K66
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i02 = ((i02 ^= i04 ^ i10 ^ i15) << 1) | (i02 >>> 31)); // W66
    c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K67
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i03 = ((i03 ^= i05 ^ i11 ^ i00) << 1) | (i03 >>> 31)); // W67
    b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K68
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i04 = ((i04 ^= i06 ^ i12 ^ i01) << 1) | (i04 >>> 31)); // W68
    a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K69
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i05 = ((i05 ^= i07 ^ i13 ^ i02) << 1) | (i05 >>> 31)); // W69
    e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K70
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i06 = ((i06 ^= i08 ^ i14 ^ i03) << 1) | (i06 >>> 31)); // W70
    d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K71
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i07 = ((i07 ^= i09 ^ i15 ^ i04) << 1) | (i07 >>> 31)); // W71
    c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K72
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i08 = ((i08 ^= i10 ^ i00 ^ i05) << 1) | (i08 >>> 31)); // W72
    b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K73
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i09 = ((i09 ^= i11 ^ i01 ^ i06) << 1) | (i09 >>> 31)); // W73
    a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K74
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i10 = ((i10 ^= i12 ^ i02 ^ i07) << 1) | (i10 >>> 31)); // W74
    e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K75
        + (b ^ (c = (c << 30) | (c >>> 2)) ^ d) // Parity(b,c,d)
        + (i11 = ((i11 ^= i13 ^ i03 ^ i08) << 1) | (i11 >>> 31)); // W75
    d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K76
        + (a ^ (b = (b << 30) | (b >>> 2)) ^ c) // Parity(a,b,c)
        + (i12 = ((i12 ^= i14 ^ i04 ^ i09) << 1) | (i12 >>> 31)); // W76
    c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K77
        + (e ^ (a = (a << 30) | (a >>> 2)) ^ b) // Parity(e,a,b)
        + (i13 = ((i13 ^= i15 ^ i05 ^ i10) << 1) | (i13 >>> 31)); // W77

    /*
     * Terminate the last two rounds of fifth pass, feeding the final digest on
     * the fly.
     */
    hB += b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K78
        + (d ^ (e = (e << 30) | (e >>> 2)) ^ a) // Parity(d,e,a)
        + (i14 = ((i14 ^= i00 ^ i06 ^ i11) << 1) | (i14 >>> 31)); // W78
    hA += a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K79
        + (c ^ (d = (d << 30) | (d >>> 2)) ^ e) // Parity(c,d,e)
        + (i15 = ((i15 ^= i01 ^ i07 ^ i12) << 1) | (i15 >>> 31)); // W79
    hE += e;
    hD += d;
    hC += /* c= */(c << 30) | (c >>> 2);
  }
}