数字签名算法:Keccak

Digest

public interface Digest {

	/**
	 * Insert one more input data byte.
	 *
	 * @param in   the input byte
	 */
	void update(byte in);

	/**
	 * Insert some more bytes.
	 *
	 * @param inbuf   the data bytes
	 */
	void update(byte[] inbuf);

	/**
	 * Insert some more bytes.
	 *
	 * @param inbuf   the data buffer
	 * @param off     the data offset in {@code inbuf}
	 * @param len     the data length (in bytes)
	 */
	void update(byte[] inbuf, int off, int len);

	/**
	 * Finalize the current hash computation and return the hash value
	 * in a newly-allocated array. The object is resetted.
	 *
	 * @return  the hash output
	 */
	byte[] digest();

	/**
	 * Input some bytes, then finalize the current hash computation
	 * and return the hash value in a newly-allocated array. The object
	 * is resetted.
	 *
	 * @param inbuf   the input data
	 * @return  the hash output
	 */
	byte[] digest(byte[] inbuf);

	/**
	 * Finalize the current hash computation and store the hash value
	 * in the provided output buffer. The {@code len} parameter
	 * contains the maximum number of bytes that should be written;
	 * no more bytes than the natural hash function output length will
	 * be produced. If {@code len} is smaller than the natural
	 * hash output length, the hash output is truncated to its first
	 * {@code len} bytes. The object is resetted.
	 *
	 * @param outbuf   the output buffer
	 * @param off      the output offset within {@code outbuf}
	 * @param len      the requested hash output length (in bytes)
	 * @return  the number of bytes actually written in {@code outbuf}
	 */
	int digest(byte[] outbuf, int off, int len);

	/**
	 * Get the natural hash function output length (in bytes).
	 *
	 * @return  the digest output length (in bytes)
	 */
	int getDigestLength();

	/**
	 * Reset the object: this makes it suitable for a new hash
	 * computation. The current computation, if any, is discarded.
	 */
	void reset();

	/**
	 * Clone the current state. The returned object evolves independantly
	 * of this object.
	 *
	 * @return  the clone
	 */
	Digest copy();

	/**
	 * <p>Return the "block length" for the hash function. This
	 * value is naturally defined for iterated hash functions
	 * (Merkle-Damgard). It is used in HMAC (that's what the
	 * <a href="http://tools.ietf.org/html/rfc2104">HMAC specification</a>
	 * names the "{@code B}" parameter).</p>
	 *
	 * <p>If the function is "block-less" then this function may
	 * return {@code -n} where {@code n} is an integer such that the
	 * block length for HMAC ("{@code B}") will be inferred from the
	 * key length, by selecting the smallest multiple of {@code n}
	 * which is no smaller than the key length. For instance, for
	 * the Fugue-xxx hash functions, this function returns -4: the
	 * virtual block length B is the HMAC key length, rounded up to
	 * the next multiple of 4.</p>
	 *
	 * @return  the internal block length (in bytes), or {@code -n}
	 */
	int getBlockLength();

	/**
	 * <p>Get the display name for this function (e.g. {@code "SHA-1"}
	 * for SHA-1).</p>
	 *
	 * @see Object
	 */
	String toString();
}

 DigestEngine

public abstract class DigestEngine implements Digest {

	/**
	 * Reset the hash algorithm state.
	 */
	protected abstract void engineReset();

	/**
	 * Process one block of data.
	 *
	 * @param data   the data block
	 */
	protected abstract void processBlock(byte[] data);

	/**
	 * Perform the final padding and store the result in the
	 * provided buffer. This method shall call {@link #flush}
	 * and then {@link #update} with the appropriate padding
	 * data in order to get the full input data.
	 *
	 * @param buf   the output buffer
	 * @param off   the output offset
	 */
	protected abstract void doPadding(byte[] buf, int off);

	/**
	 * This function is called at object creation time; the
	 * implementation should use it to perform initialization tasks.
	 * After this method is called, the implementation should be ready
	 * to process data or meaningfully honour calls such as
	 * {@link #getDigestLength}
	 */
	protected abstract void doInit();

	private int digestLen, blockLen, inputLen;
	private byte[] inputBuf, outputBuf;
	private long blockCount;

	/**
	 * Instantiate the engine.
	 */
	public DigestEngine()
	{
		doInit();
		digestLen = getDigestLength();
		blockLen = getInternalBlockLength();
		inputBuf = new byte[blockLen];
		outputBuf = new byte[digestLen];
		inputLen = 0;
		blockCount = 0;
	}

	private void adjustDigestLen()
	{
		if (digestLen == 0) {
			digestLen = getDigestLength();
			outputBuf = new byte[digestLen];
		}
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public byte[] digest()
	{
		adjustDigestLen();
		byte[] result = new byte[digestLen];
		digest(result, 0, digestLen);
		return result;
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public byte[] digest(byte[] input)
	{
		update(input, 0, input.length);
		return digest();
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public int digest(byte[] buf, int offset, int len)
	{
		adjustDigestLen();
		if (len >= digestLen) {
			doPadding(buf, offset);
			reset();
			return digestLen;
		} else {
			doPadding(outputBuf, 0);
			System.arraycopy(outputBuf, 0, buf, offset, len);
			reset();
			return len;
		}
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public void reset()
	{
		engineReset();
		inputLen = 0;
		blockCount = 0;
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public void update(byte input)
	{
		inputBuf[inputLen ++] = (byte)input;
		if (inputLen == blockLen) {
			processBlock(inputBuf);
			blockCount ++;
			inputLen = 0;
		}
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public void update(byte[] input)
	{
		update(input, 0, input.length);
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public void update(byte[] input, int offset, int len)
	{
		while (len > 0) {
			int copyLen = blockLen - inputLen;
			if (copyLen > len)
				copyLen = len;
			System.arraycopy(input, offset, inputBuf, inputLen,
				copyLen);
			offset += copyLen;
			inputLen += copyLen;
			len -= copyLen;
			if (inputLen == blockLen) {
				processBlock(inputBuf);
				blockCount ++;
				inputLen = 0;
			}
		}
	}

	/**
	 * Get the internal block length. This is the length (in
	 * bytes) of the array which will be passed as parameter to
	 * {@link #processBlock}. The default implementation of this
	 * method calls {@link #getBlockLength} and returns the same
	 * value. Overriding this method is useful when the advertised
	 * block length (which is used, for instance, by HMAC) is
	 * suboptimal with regards to internal buffering needs.
	 *
	 * @return  the internal block length (in bytes)
	 */
	protected int getInternalBlockLength()
	{
		return getBlockLength();
	}

	/**
	 * Flush internal buffers, so that less than a block of data
	 * may at most be upheld.
	 *
	 * @return  the number of bytes still unprocessed after the flush
	 */
	protected final int flush()
	{
		return inputLen;
	}

	/**
	 * Get a reference to an internal buffer with the same size
	 * than a block. The contents of that buffer are defined only
	 * immediately after a call to {@link #flush()}: if
	 * {@link #flush()} return the value {@code n}, then the
	 * first {@code n} bytes of the array returned by this method
	 * are the {@code n} bytes of input data which are still
	 * unprocessed. The values of the remaining bytes are
	 * undefined and may be altered at will.
	 *
	 * @return  a block-sized internal buffer
	 */
	protected final byte[] getBlockBuffer()
	{
		return inputBuf;
	}

	/**
	 * Get the "block count": this is the number of times the
	 * {@link #processBlock} method has been invoked for the
	 * current hash operation. That counter is incremented
	 * <em>after</em> the call to {@link #processBlock}.
	 *
	 * @return  the block count
	 */
	protected long getBlockCount()
	{
		return blockCount;
	}

	/**
	 * This function copies the internal buffering state to some
	 * other instance of a class extending {@code DigestEngine}.
	 * It returns a reference to the copy. This method is intended
	 * to be called by the implementation of the {@link #copy}
	 * method.
	 *
	 * @param dest   the copy
	 * @return  the value {@code dest}
	 */
	protected Digest copyState(DigestEngine dest)
	{
		dest.inputLen = inputLen;
		dest.blockCount = blockCount;
		System.arraycopy(inputBuf, 0, dest.inputBuf, 0,
			inputBuf.length);
		adjustDigestLen();
		dest.adjustDigestLen();
		System.arraycopy(outputBuf, 0, dest.outputBuf, 0,
			outputBuf.length);
		return dest;
	}
}

 KeccakCore

abstract class KeccakCore extends DigestEngine {

	KeccakCore()
	{
	}

	private long[] A;
	private byte[] tmpOut;

	private static final long[] RC = {
		0x0000000000000001L, 0x0000000000008082L,
		0x800000000000808AL, 0x8000000080008000L,
		0x000000000000808BL, 0x0000000080000001L,
		0x8000000080008081L, 0x8000000000008009L,
		0x000000000000008AL, 0x0000000000000088L,
		0x0000000080008009L, 0x000000008000000AL,
		0x000000008000808BL, 0x800000000000008BL,
		0x8000000000008089L, 0x8000000000008003L,
		0x8000000000008002L, 0x8000000000000080L,
		0x000000000000800AL, 0x800000008000000AL,
		0x8000000080008081L, 0x8000000000008080L,
		0x0000000080000001L, 0x8000000080008008L
	};

	/**
	 * Encode the 64-bit word {@code val} into the array
	 * {@code buf} at offset {@code off}, in little-endian
	 * convention (least significant byte first).
	 *
	 * @param val   the value to encode
	 * @param buf   the destination buffer
	 * @param off   the destination offset
	 */
	private static void encodeLELong(long val, byte[] buf, int off)
	{
		buf[off + 0] = (byte)val;
		buf[off + 1] = (byte)(val >>> 8);
		buf[off + 2] = (byte)(val >>> 16);
		buf[off + 3] = (byte)(val >>> 24);
		buf[off + 4] = (byte)(val >>> 32);
		buf[off + 5] = (byte)(val >>> 40);
		buf[off + 6] = (byte)(val >>> 48);
		buf[off + 7] = (byte)(val >>> 56);
	}

	/**
	 * Decode a 64-bit little-endian word from the array {@code buf}
	 * at offset {@code off}.
	 *
	 * @param buf   the source buffer
	 * @param off   the source offset
	 * @return  the decoded value
	 */
	private static long decodeLELong(byte[] buf, int off)
	{
		return (buf[off + 0] & 0xFFL)
			| ((buf[off + 1] & 0xFFL) << 8)
			| ((buf[off + 2] & 0xFFL) << 16)
			| ((buf[off + 3] & 0xFFL) << 24)
			| ((buf[off + 4] & 0xFFL) << 32)
			| ((buf[off + 5] & 0xFFL) << 40)
			| ((buf[off + 6] & 0xFFL) << 48)
			| ((buf[off + 7] & 0xFFL) << 56);
	}

	/** @see org.ethereum.crypto.cryptohash.DigestEngine */
	protected void engineReset()
	{
		doReset();
	}

	/** @see org.ethereum.crypto.cryptohash.DigestEngine */
	protected void processBlock(byte[] data)
	{
		/* Input block */
		for (int i = 0; i < data.length; i += 8)
			A[i >>> 3] ^= decodeLELong(data, i);

		long t0, t1, t2, t3, t4;
		long tt0, tt1, tt2, tt3, tt4;
		long t, kt;
		long c0, c1, c2, c3, c4, bnn;

		/*
		 * Unrolling four rounds kills performance big time
		 * on Intel x86 Core2, in both 32-bit and 64-bit modes
		 * (less than 1 MB/s instead of 55 MB/s on x86-64).
		 * Unrolling two rounds appears to be fine.
		 */
		for (int j = 0; j < 24; j += 2) {

			tt0 = A[ 1] ^ A[ 6];
			tt1 = A[11] ^ A[16];
			tt0 ^= A[21] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 4] ^ A[ 9];
			tt3 = A[14] ^ A[19];
			tt0 ^= A[24];
			tt2 ^= tt3;
			t0 = tt0 ^ tt2;

			tt0 = A[ 2] ^ A[ 7];
			tt1 = A[12] ^ A[17];
			tt0 ^= A[22] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 0] ^ A[ 5];
			tt3 = A[10] ^ A[15];
			tt0 ^= A[20];
			tt2 ^= tt3;
			t1 = tt0 ^ tt2;

			tt0 = A[ 3] ^ A[ 8];
			tt1 = A[13] ^ A[18];
			tt0 ^= A[23] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 1] ^ A[ 6];
			tt3 = A[11] ^ A[16];
			tt0 ^= A[21];
			tt2 ^= tt3;
			t2 = tt0 ^ tt2;

			tt0 = A[ 4] ^ A[ 9];
			tt1 = A[14] ^ A[19];
			tt0 ^= A[24] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 2] ^ A[ 7];
			tt3 = A[12] ^ A[17];
			tt0 ^= A[22];
			tt2 ^= tt3;
			t3 = tt0 ^ tt2;

			tt0 = A[ 0] ^ A[ 5];
			tt1 = A[10] ^ A[15];
			tt0 ^= A[20] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 3] ^ A[ 8];
			tt3 = A[13] ^ A[18];
			tt0 ^= A[23];
			tt2 ^= tt3;
			t4 = tt0 ^ tt2;

			A[ 0] = A[ 0] ^ t0;
			A[ 5] = A[ 5] ^ t0;
			A[10] = A[10] ^ t0;
			A[15] = A[15] ^ t0;
			A[20] = A[20] ^ t0;
			A[ 1] = A[ 1] ^ t1;
			A[ 6] = A[ 6] ^ t1;
			A[11] = A[11] ^ t1;
			A[16] = A[16] ^ t1;
			A[21] = A[21] ^ t1;
			A[ 2] = A[ 2] ^ t2;
			A[ 7] = A[ 7] ^ t2;
			A[12] = A[12] ^ t2;
			A[17] = A[17] ^ t2;
			A[22] = A[22] ^ t2;
			A[ 3] = A[ 3] ^ t3;
			A[ 8] = A[ 8] ^ t3;
			A[13] = A[13] ^ t3;
			A[18] = A[18] ^ t3;
			A[23] = A[23] ^ t3;
			A[ 4] = A[ 4] ^ t4;
			A[ 9] = A[ 9] ^ t4;
			A[14] = A[14] ^ t4;
			A[19] = A[19] ^ t4;
			A[24] = A[24] ^ t4;
			A[ 5] = (A[ 5] << 36) | (A[ 5] >>> (64 - 36));
			A[10] = (A[10] << 3) | (A[10] >>> (64 - 3));
			A[15] = (A[15] << 41) | (A[15] >>> (64 - 41));
			A[20] = (A[20] << 18) | (A[20] >>> (64 - 18));
			A[ 1] = (A[ 1] << 1) | (A[ 1] >>> (64 - 1));
			A[ 6] = (A[ 6] << 44) | (A[ 6] >>> (64 - 44));
			A[11] = (A[11] << 10) | (A[11] >>> (64 - 10));
			A[16] = (A[16] << 45) | (A[16] >>> (64 - 45));
			A[21] = (A[21] << 2) | (A[21] >>> (64 - 2));
			A[ 2] = (A[ 2] << 62) | (A[ 2] >>> (64 - 62));
			A[ 7] = (A[ 7] << 6) | (A[ 7] >>> (64 - 6));
			A[12] = (A[12] << 43) | (A[12] >>> (64 - 43));
			A[17] = (A[17] << 15) | (A[17] >>> (64 - 15));
			A[22] = (A[22] << 61) | (A[22] >>> (64 - 61));
			A[ 3] = (A[ 3] << 28) | (A[ 3] >>> (64 - 28));
			A[ 8] = (A[ 8] << 55) | (A[ 8] >>> (64 - 55));
			A[13] = (A[13] << 25) | (A[13] >>> (64 - 25));
			A[18] = (A[18] << 21) | (A[18] >>> (64 - 21));
			A[23] = (A[23] << 56) | (A[23] >>> (64 - 56));
			A[ 4] = (A[ 4] << 27) | (A[ 4] >>> (64 - 27));
			A[ 9] = (A[ 9] << 20) | (A[ 9] >>> (64 - 20));
			A[14] = (A[14] << 39) | (A[14] >>> (64 - 39));
			A[19] = (A[19] << 8) | (A[19] >>> (64 - 8));
			A[24] = (A[24] << 14) | (A[24] >>> (64 - 14));
			bnn = ~A[12];
			kt = A[ 6] | A[12];
			c0 = A[ 0] ^ kt;
			kt = bnn | A[18];
			c1 = A[ 6] ^ kt;
			kt = A[18] & A[24];
			c2 = A[12] ^ kt;
			kt = A[24] | A[ 0];
			c3 = A[18] ^ kt;
			kt = A[ 0] & A[ 6];
			c4 = A[24] ^ kt;
			A[ 0] = c0;
			A[ 6] = c1;
			A[12] = c2;
			A[18] = c3;
			A[24] = c4;
			bnn = ~A[22];
			kt = A[ 9] | A[10];
			c0 = A[ 3] ^ kt;
			kt = A[10] & A[16];
			c1 = A[ 9] ^ kt;
			kt = A[16] | bnn;
			c2 = A[10] ^ kt;
			kt = A[22] | A[ 3];
			c3 = A[16] ^ kt;
			kt = A[ 3] & A[ 9];
			c4 = A[22] ^ kt;
			A[ 3] = c0;
			A[ 9] = c1;
			A[10] = c2;
			A[16] = c3;
			A[22] = c4;
			bnn = ~A[19];
			kt = A[ 7] | A[13];
			c0 = A[ 1] ^ kt;
			kt = A[13] & A[19];
			c1 = A[ 7] ^ kt;
			kt = bnn & A[20];
			c2 = A[13] ^ kt;
			kt = A[20] | A[ 1];
			c3 = bnn ^ kt;
			kt = A[ 1] & A[ 7];
			c4 = A[20] ^ kt;
			A[ 1] = c0;
			A[ 7] = c1;
			A[13] = c2;
			A[19] = c3;
			A[20] = c4;
			bnn = ~A[17];
			kt = A[ 5] & A[11];
			c0 = A[ 4] ^ kt;
			kt = A[11] | A[17];
			c1 = A[ 5] ^ kt;
			kt = bnn | A[23];
			c2 = A[11] ^ kt;
			kt = A[23] & A[ 4];
			c3 = bnn ^ kt;
			kt = A[ 4] | A[ 5];
			c4 = A[23] ^ kt;
			A[ 4] = c0;
			A[ 5] = c1;
			A[11] = c2;
			A[17] = c3;
			A[23] = c4;
			bnn = ~A[ 8];
			kt = bnn & A[14];
			c0 = A[ 2] ^ kt;
			kt = A[14] | A[15];
			c1 = bnn ^ kt;
			kt = A[15] & A[21];
			c2 = A[14] ^ kt;
			kt = A[21] | A[ 2];
			c3 = A[15] ^ kt;
			kt = A[ 2] & A[ 8];
			c4 = A[21] ^ kt;
			A[ 2] = c0;
			A[ 8] = c1;
			A[14] = c2;
			A[15] = c3;
			A[21] = c4;
			A[ 0] = A[ 0] ^ RC[j + 0];

			tt0 = A[ 6] ^ A[ 9];
			tt1 = A[ 7] ^ A[ 5];
			tt0 ^= A[ 8] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[24] ^ A[22];
			tt3 = A[20] ^ A[23];
			tt0 ^= A[21];
			tt2 ^= tt3;
			t0 = tt0 ^ tt2;

			tt0 = A[12] ^ A[10];
			tt1 = A[13] ^ A[11];
			tt0 ^= A[14] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 0] ^ A[ 3];
			tt3 = A[ 1] ^ A[ 4];
			tt0 ^= A[ 2];
			tt2 ^= tt3;
			t1 = tt0 ^ tt2;

			tt0 = A[18] ^ A[16];
			tt1 = A[19] ^ A[17];
			tt0 ^= A[15] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[ 6] ^ A[ 9];
			tt3 = A[ 7] ^ A[ 5];
			tt0 ^= A[ 8];
			tt2 ^= tt3;
			t2 = tt0 ^ tt2;

			tt0 = A[24] ^ A[22];
			tt1 = A[20] ^ A[23];
			tt0 ^= A[21] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[12] ^ A[10];
			tt3 = A[13] ^ A[11];
			tt0 ^= A[14];
			tt2 ^= tt3;
			t3 = tt0 ^ tt2;

			tt0 = A[ 0] ^ A[ 3];
			tt1 = A[ 1] ^ A[ 4];
			tt0 ^= A[ 2] ^ tt1;
			tt0 = (tt0 << 1) | (tt0 >>> 63);
			tt2 = A[18] ^ A[16];
			tt3 = A[19] ^ A[17];
			tt0 ^= A[15];
			tt2 ^= tt3;
			t4 = tt0 ^ tt2;

			A[ 0] = A[ 0] ^ t0;
			A[ 3] = A[ 3] ^ t0;
			A[ 1] = A[ 1] ^ t0;
			A[ 4] = A[ 4] ^ t0;
			A[ 2] = A[ 2] ^ t0;
			A[ 6] = A[ 6] ^ t1;
			A[ 9] = A[ 9] ^ t1;
			A[ 7] = A[ 7] ^ t1;
			A[ 5] = A[ 5] ^ t1;
			A[ 8] = A[ 8] ^ t1;
			A[12] = A[12] ^ t2;
			A[10] = A[10] ^ t2;
			A[13] = A[13] ^ t2;
			A[11] = A[11] ^ t2;
			A[14] = A[14] ^ t2;
			A[18] = A[18] ^ t3;
			A[16] = A[16] ^ t3;
			A[19] = A[19] ^ t3;
			A[17] = A[17] ^ t3;
			A[15] = A[15] ^ t3;
			A[24] = A[24] ^ t4;
			A[22] = A[22] ^ t4;
			A[20] = A[20] ^ t4;
			A[23] = A[23] ^ t4;
			A[21] = A[21] ^ t4;
			A[ 3] = (A[ 3] << 36) | (A[ 3] >>> (64 - 36));
			A[ 1] = (A[ 1] << 3) | (A[ 1] >>> (64 - 3));
			A[ 4] = (A[ 4] << 41) | (A[ 4] >>> (64 - 41));
			A[ 2] = (A[ 2] << 18) | (A[ 2] >>> (64 - 18));
			A[ 6] = (A[ 6] << 1) | (A[ 6] >>> (64 - 1));
			A[ 9] = (A[ 9] << 44) | (A[ 9] >>> (64 - 44));
			A[ 7] = (A[ 7] << 10) | (A[ 7] >>> (64 - 10));
			A[ 5] = (A[ 5] << 45) | (A[ 5] >>> (64 - 45));
			A[ 8] = (A[ 8] << 2) | (A[ 8] >>> (64 - 2));
			A[12] = (A[12] << 62) | (A[12] >>> (64 - 62));
			A[10] = (A[10] << 6) | (A[10] >>> (64 - 6));
			A[13] = (A[13] << 43) | (A[13] >>> (64 - 43));
			A[11] = (A[11] << 15) | (A[11] >>> (64 - 15));
			A[14] = (A[14] << 61) | (A[14] >>> (64 - 61));
			A[18] = (A[18] << 28) | (A[18] >>> (64 - 28));
			A[16] = (A[16] << 55) | (A[16] >>> (64 - 55));
			A[19] = (A[19] << 25) | (A[19] >>> (64 - 25));
			A[17] = (A[17] << 21) | (A[17] >>> (64 - 21));
			A[15] = (A[15] << 56) | (A[15] >>> (64 - 56));
			A[24] = (A[24] << 27) | (A[24] >>> (64 - 27));
			A[22] = (A[22] << 20) | (A[22] >>> (64 - 20));
			A[20] = (A[20] << 39) | (A[20] >>> (64 - 39));
			A[23] = (A[23] << 8) | (A[23] >>> (64 - 8));
			A[21] = (A[21] << 14) | (A[21] >>> (64 - 14));
			bnn = ~A[13];
			kt = A[ 9] | A[13];
			c0 = A[ 0] ^ kt;
			kt = bnn | A[17];
			c1 = A[ 9] ^ kt;
			kt = A[17] & A[21];
			c2 = A[13] ^ kt;
			kt = A[21] | A[ 0];
			c3 = A[17] ^ kt;
			kt = A[ 0] & A[ 9];
			c4 = A[21] ^ kt;
			A[ 0] = c0;
			A[ 9] = c1;
			A[13] = c2;
			A[17] = c3;
			A[21] = c4;
			bnn = ~A[14];
			kt = A[22] | A[ 1];
			c0 = A[18] ^ kt;
			kt = A[ 1] & A[ 5];
			c1 = A[22] ^ kt;
			kt = A[ 5] | bnn;
			c2 = A[ 1] ^ kt;
			kt = A[14] | A[18];
			c3 = A[ 5] ^ kt;
			kt = A[18] & A[22];
			c4 = A[14] ^ kt;
			A[18] = c0;
			A[22] = c1;
			A[ 1] = c2;
			A[ 5] = c3;
			A[14] = c4;
			bnn = ~A[23];
			kt = A[10] | A[19];
			c0 = A[ 6] ^ kt;
			kt = A[19] & A[23];
			c1 = A[10] ^ kt;
			kt = bnn & A[ 2];
			c2 = A[19] ^ kt;
			kt = A[ 2] | A[ 6];
			c3 = bnn ^ kt;
			kt = A[ 6] & A[10];
			c4 = A[ 2] ^ kt;
			A[ 6] = c0;
			A[10] = c1;
			A[19] = c2;
			A[23] = c3;
			A[ 2] = c4;
			bnn = ~A[11];
			kt = A[ 3] & A[ 7];
			c0 = A[24] ^ kt;
			kt = A[ 7] | A[11];
			c1 = A[ 3] ^ kt;
			kt = bnn | A[15];
			c2 = A[ 7] ^ kt;
			kt = A[15] & A[24];
			c3 = bnn ^ kt;
			kt = A[24] | A[ 3];
			c4 = A[15] ^ kt;
			A[24] = c0;
			A[ 3] = c1;
			A[ 7] = c2;
			A[11] = c3;
			A[15] = c4;
			bnn = ~A[16];
			kt = bnn & A[20];
			c0 = A[12] ^ kt;
			kt = A[20] | A[ 4];
			c1 = bnn ^ kt;
			kt = A[ 4] & A[ 8];
			c2 = A[20] ^ kt;
			kt = A[ 8] | A[12];
			c3 = A[ 4] ^ kt;
			kt = A[12] & A[16];
			c4 = A[ 8] ^ kt;
			A[12] = c0;
			A[16] = c1;
			A[20] = c2;
			A[ 4] = c3;
			A[ 8] = c4;
			A[ 0] = A[ 0] ^ RC[j + 1];
			t = A[ 5];
			A[ 5] = A[18];
			A[18] = A[11];
			A[11] = A[10];
			A[10] = A[ 6];
			A[ 6] = A[22];
			A[22] = A[20];
			A[20] = A[12];
			A[12] = A[19];
			A[19] = A[15];
			A[15] = A[24];
			A[24] = A[ 8];
			A[ 8] = t;
			t = A[ 1];
			A[ 1] = A[ 9];
			A[ 9] = A[14];
			A[14] = A[ 2];
			A[ 2] = A[13];
			A[13] = A[23];
			A[23] = A[ 4];
			A[ 4] = A[21];
			A[21] = A[16];
			A[16] = A[ 3];
			A[ 3] = A[17];
			A[17] = A[ 7];
			A[ 7] = t;
		}
	}

	/** @see org.ethereum.crypto.cryptohash.DigestEngine */
	protected void doPadding(byte[] out, int off)
	{
		int ptr = flush();
		byte[] buf = getBlockBuffer();
		if ((ptr + 1) == buf.length) {
			buf[ptr] = (byte)0x81;
		} else {
			buf[ptr] = (byte)0x01;
			for (int i = ptr + 1; i < (buf.length - 1); i ++)
				buf[i] = 0;
			buf[buf.length - 1] = (byte)0x80;
		}
		processBlock(buf);
		A[ 1] = ~A[ 1];
		A[ 2] = ~A[ 2];
		A[ 8] = ~A[ 8];
		A[12] = ~A[12];
		A[17] = ~A[17];
		A[20] = ~A[20];
		int dlen = getDigestLength();
		for (int i = 0; i < dlen; i += 8)
			encodeLELong(A[i >>> 3], tmpOut, i);
		System.arraycopy(tmpOut, 0, out, off, dlen);
	}

	/** @see org.ethereum.crypto.cryptohash.DigestEngine */
	protected void doInit()
	{
		A = new long[25];
		tmpOut = new byte[(getDigestLength() + 7) & ~7];
		doReset();
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public int getBlockLength()
	{
		return 200 - 2 * getDigestLength();
	}

	private final void doReset()
	{
		for (int i = 0; i < 25; i ++)
			A[i] = 0;
		A[ 1] = 0xFFFFFFFFFFFFFFFFL;
		A[ 2] = 0xFFFFFFFFFFFFFFFFL;
		A[ 8] = 0xFFFFFFFFFFFFFFFFL;
		A[12] = 0xFFFFFFFFFFFFFFFFL;
		A[17] = 0xFFFFFFFFFFFFFFFFL;
		A[20] = 0xFFFFFFFFFFFFFFFFL;
	}

	/** @see org.ethereum.crypto.cryptohash.DigestEngine */
	protected Digest copyState(KeccakCore dst)
	{
		System.arraycopy(A, 0, dst.A, 0, 25);
		return super.copyState(dst);
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public String toString()
	{
		return "Keccak-" + (getDigestLength() << 3);
	}
}

 Keccak256

public class Keccak256 extends KeccakCore {

	/**
	 * Create the engine.
	 */
	public Keccak256()
	{
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public Digest copy()
	{
		return copyState(new Keccak256());
	}

	/** @see org.ethereum.crypto.cryptohash.Digest */
	public int getDigestLength()
	{
		return 32;
	}
}

 Keccak512

public class Keccak512 extends KeccakCore {

	/**
	 * Create the engine.
	 */
	public Keccak512()
	{
	}

	/** @see Digest */
	public Digest copy()
	{
		return copyState(new Keccak512());
	}

	/** @see Digest */
	public int getDigestLength()
	{
		return 64;
	}
}

测试代码

public static byte[] sha3(byte[] input) {
    Keccak256 digest =  new Keccak256();
    digest.update(input);
    return digest.digest();
}

@Test
public void test() {
    String message = "13120983870";
    byte[] result = sha3(message.getBytes());
    System.out.println("base64:" + Base64.byteArrayToBase64(result));
}

运行结果

base64:MFs2drA5BkHW8/hhU4xzNzdA/E/ySpvAJ1iypI+Cyhs=

猜你喜欢

转载自lobin.iteye.com/blog/2436668