[gui-dev] Re: Faster SHA1 and Tiger MessageDigestSPI's (version 1.11)
Roger Kapsi <[email protected]> Wed, 30 Jun 2004 13:50:51 +0200
| Newsgroups | gmane.network.gnutella.limewire.gui.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi I'm currently experimenting with Philippe's SHA1 code and NIO Buffers with the ability to access memory directly (well, lets say I'll start the experiments at the end of next week when the exams are over :)) But as the first step I've already prepared the computeBlock() for the C transition with some surprising results! What I did is to change blocks like... 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 ... to ... b = (b << 30) | (b >>> 2); i00 ^= i02 ^ i08 ^ i13; i00 = (i00 << 1) | (i00 >>> 31); d += ((e << 5) | (e >>> 27)) + 0x5a827999 // K16 + ((a & (b ^ c)) ^ c) // Ch(a,b,c) + (i00); // W16 And here are the results: - G3 500MHz: the hash rate drops from 17MB/s to 16MB/s - G4 450MHz: the hash rate drops from 16MB/s to 15MB/s - G5 2GHz: the hash rate rose from 75MB/s to 85MB/s! =) I'm wondering now if the latest and greatest P4/Athlon systems can benefit from this as well? Oh, and you may try this version on 10.2/Java 1.4.1 to check if it's a workaround for the wrong hash computation problem... Cheers! Roger _______________________________________________ gui-dev mailing list [email protected] http://www.limewire.org/mailman/listinfo/gui-dev
SHA1.java
(text/plain, 37.6 KB)
/* @(#)SHA1.java 1.11 2004-04-26
* 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
*/
/* Sun may wish to change the following package name, if integrating this
* class in the Sun JCE Security Provider for Java 1.5 (code-named Tiger).
*
* You can include it in your own Security Provider by inserting
* this property in your Provider derived class:
* put("MessageDigest.SHA-1", "com.bitzi.util.SHA1");
*/
//package com.bitzi.util;
import java.security.*;
//--+---+1--+---+--2+---+---+3--+---+--4+---+---+5--+---+--6+---+---+7--+---+--
//34567890123456789012345678901234567890123456789012345678901234567890123456789
/**
* <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,
* but truncates the final digest and uses distinct initialization values.</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 & Sons, 1996</li>
* </ol>
*/
public final class SHA1 extends MessageDigest implements Cloneable {
/**
* This implementation returns a fixed-size digest.
*/
private static final int HASH_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() {
super("SHA-1");
pad = new byte[64];
init();
}
/**
* Clones this object.
*/
public Object clone() throws CloneNotSupportedException {
SHA1 that = (SHA1)super.clone();
that.pad = (byte[])this.pad.clone();
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 HASH_LENGTH;
}
/**
* Reset athen initialize 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;
init();
}
/**
* Initialize the digest context.
*/
protected void init() {
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++;
if (padding < 63) {
pad[padding++] = input;
return;
}
pad[63] = input;
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 length 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;
/* Terminate the previous block. */
int padlen = 64 - padding;
if (padding > 0 && len >= padlen) {
System.arraycopy(input, offset, pad, padding, padlen);
computeBlock(pad, 0);
padding = 0;
offset += padlen;
len -= padlen;
}
/* Loop on large sets of complete blocks. */
while (len >= 512) {
computeBlock(input, offset);
computeBlock(input, offset + 64);
computeBlock(input, offset + 128);
computeBlock(input, offset + 192);
computeBlock(input, offset + 256);
computeBlock(input, offset + 320);
computeBlock(input, offset + 384);
computeBlock(input, offset + 448);
offset += 512;
len -= 512;
}
/* Loop on remaining complete blocks. */
while (len >= 64) {
computeBlock(input, offset);
offset += 64;
len -= 64;
}
/* remaining bytes kept for next block. */
if (len > 0) {
System.arraycopy(input, offset, pad, padding, len);
padding += len;
}
return;
}
throw new ArrayIndexOutOfBoundsException(offset);
}
/**
* 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() {
try {
final byte hashvalue[] = new byte[HASH_LENGTH];
engineDigest(hashvalue, 0, HASH_LENGTH);
return hashvalue;
} catch (DigestException e) {
return null;
}
}
/**
* 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, final int len)
throws DigestException {
if (len >= HASH_LENGTH) {
if (hashvalue.length - offset >= HASH_LENGTH) {
/* Flush the trailing bytes, adding padding bytes into last
* blocks. */
int i;
/* Add padding null bytes but replace the last 8 padding bytes
* by the little-endian 64-bit digested message bit-length. */
pad[i = padding] = (byte)0x80; /* required 1st padding byte */
/* Check if 8 bytes available in pad to store the total
* message size */
switch (i) { /* INVARIANT: i must be in [0..63] */
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;
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[]. */
i = 52;
do {
pad[i ] = (byte)0x00;
pad[i + 1] = (byte)0x00;
pad[i + 2] = (byte)0x00;
pad[i + 3] = (byte)0x00;
} while ((i -= 4) >= 0);
break;
default:
/* Clear the rest of 56 first bytes of pad[]. */
switch (i & 3) {
case 3: i++;
break;
case 2: pad[(i += 2) - 1] = (byte)0x00;
break;
case 1: pad[(i += 3) - 2] = (byte)0x00;
pad[ i - 1] = (byte)0x00;
break;
case 0: pad[(i += 4) - 3] = (byte)0x00;
pad[ i - 2] = (byte)0x00;
pad[ i - 1] = (byte)0x00;
}
do {
pad[i ] = (byte)0x00;
pad[i + 1] = (byte)0x00;
pad[i + 2] = (byte)0x00;
pad[i + 3] = (byte)0x00;
} while ((i += 4) < 56);
}
/* Convert the message size from bytes to big-endian bits. */
pad[56] = (byte)((i = (int)(bytes >>> 29)) >> 24);
pad[57] = (byte)(i >>> 16);
pad[58] = (byte)(i >>> 8);
pad[59] = (byte)i;
pad[60] = (byte)((i = (int)bytes << 3) >> 24);
pad[61] = (byte)(i >>> 16);
pad[62] = (byte)(i >>> 8);
pad[63] = (byte)i;
computeBlock(pad, 0);
/* Return the computed digest in big-endian byte order. */
hashvalue[offset ] = (byte)((i = hA) >>> 24);
hashvalue[offset + 1] = (byte)(i >>> 16);
hashvalue[offset + 2] = (byte)(i >>> 8);
hashvalue[offset + 3] = (byte)i;
hashvalue[offset + 4] = (byte)((i = hB) >>> 24);
hashvalue[offset += 5] = (byte)(i >>> 16);
hashvalue[offset + 1] = (byte)(i >>> 8);
hashvalue[offset + 2] = (byte)i;
hashvalue[offset + 3] = (byte)((i = hC) >>> 24);
hashvalue[offset + 4] = (byte)(i >>> 16);
hashvalue[offset += 5] = (byte)(i >>> 8);
hashvalue[offset + 1] = (byte)i;
hashvalue[offset + 2] = (byte)((i = hD) >>> 24);
hashvalue[offset + 3] = (byte)(i >>> 16);
hashvalue[offset + 4] = (byte)(i >>> 8);
hashvalue[offset += 5] = (byte)i;
hashvalue[offset + 1] = (byte)((i = hE) >>> 24);
hashvalue[offset + 2] = (byte)(i >>> 16);
hashvalue[offset + 3] = (byte)(i >>> 8);
hashvalue[offset + 4] = (byte)i;
engineReset(); /* clear the evidence */
return HASH_LENGTH;
}
throw new DigestException(
"insufficient space in output buffer to store the digest");
}
throw new DigestException("partial digests not returned");
}
/**
* 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 32-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). */
a = hA;
b = hB;
c = hC;
d = hD;
e = hE;
i00 = input[offset] << 24 | (input[offset + 1] & 0xff) << 16
| (input[offset + 2] & 0xff) << 8 | (input[offset + 3] & 0xff);
e += ((a << 5) | (a >>> 27)) + 0x5a827999 // K00
+ ((b & (c ^ d)) ^ d) // Ch(b,c,d)
+ (i00); // W00
b = (b << 30) | (b >>> 2);
i01 = input[offset + 4] << 24 | (input[offset += 5] & 0xff) << 16
| (input[offset + 1] & 0xff) << 8 | (input[offset + 2] & 0xff);
d += ((e << 5) | (e >>> 27)) + 0x5a827999 // K01
+ ((a & (b ^ c)) ^ c) // Ch(a,b,c)
+ (i01); // W01
a = (a << 30) | (a >>> 2);
i02 = input[offset + 3] << 24 | (input[offset + 4] & 0xff) << 16
| (input[offset += 5] & 0xff) << 8 | (input[offset + 1] & 0xff);
c += ((d << 5) | (d >>> 27)) + 0x5a827999 // K02
+ ((e & (a ^ b)) ^ b) // Ch(e,a,b)
+ (i02); // W02
e = (e << 30) | (e >>> 2);
i03 = input[offset + 2] << 24 | (input[offset + 3] & 0xff) << 16
| (input[offset + 4] & 0xff) << 8 | (input[offset += 5] & 0xff);
b += ((c << 5) | (c >>> 27)) + 0x5a827999 // K03
+ ((d & (e ^ a)) ^ a) // Ch(d,e,a)
+ (i03); // W03
d = (d << 30) | (d >>> 2);
i04 = input[offset + 1] << 24 | (input[offset + 2] & 0xff) << 16
| (input[offset + 3] & 0xff) << 8 | (input[offset + 4] & 0xff);
a += ((b << 5) | (b >>> 27)) + 0x5a827999 // K04
+ ((c & (d ^ e)) ^ e) // Ch(c,d,e)
+ (i04); // W04
c = (c << 30) | (c >>> 2);
i05 = input[offset += 5] << 24 | (input[offset + 1] & 0xff) << 16
| (input[offset + 2] & 0xff) << 8 | (input[offset + 3] & 0xff);
e += ((a << 5) | (a >>> 27)) + 0x5a827999 // K05
+ ((b & (c ^ d)) ^ d) // Ch(b,c,d)
+ (i05); // W05
b = (b << 30) | (b >>> 2);
i06 = input[offset + 4] << 24 | (input[offset += 5] & 0xff) << 16
| (input[offset + 1] & 0xff) << 8 | (input[offset + 2] & 0xff);
d += ((e << 5) | (e >>> 27)) + 0x5a827999 // K06
+ ((a & (b ^ c)) ^ c) // Ch(a,b,c)
+ (i06); // W06
a = (a << 30) | (a >>> 2);
i07 = input[offset + 3] << 24 | (input[offset + 4] & 0xff) << 16
| (input[offset += 5] & 0xff) << 8 | (input[offset + 1] & 0xff);
c += ((d << 5) | (d >>> 27)) + 0x5a827999 // K07
+ ((e & (a ^ b)) ^ b) // Ch(e,a,b)
+ (i07); // W07
e = (e << 30) | (e >>> 2);
i08 = input[offset + 2] << 24 | (input[offset + 3] & 0xff) << 16
| (input[offset + 4] & 0xff) << 8 | (input[offset += 5] & 0xff);
b += ((c << 5) | (c >>> 27)) + 0x5a827999 // K08
+ ((d & (e ^ a)) ^ a) // Ch(d,e,a)
+ (i08); // W08
d = (d << 30) | (d >>> 2);
i09 = input[offset + 1] << 24 | (input[offset + 2] & 0xff) << 16
| (input[offset + 3] & 0xff) << 8 | (input[offset + 4] & 0xff);
a += ((b << 5) | (b >>> 27)) + 0x5a827999 // K09
+ ((c & (d ^ e)) ^ e) // Ch(c,d,e)
+ (i09); // W09
c = (c << 30) | (c >>> 2);
i10 = input[offset += 5] << 24 | (input[offset + 1] & 0xff) << 16
| (input[offset + 2] & 0xff) << 8 | (input[offset + 3] & 0xff);
e += ((a << 5) | (a >>> 27)) + 0x5a827999 // K10
+ ((b & (c ^ d)) ^ d) // Ch(b,c,d)
+ (i10); // W10
b = (b << 30) | (b >>> 2);
i11 = input[offset + 4] << 24 | (input[offset += 5] & 0xff) << 16
| (input[offset + 1] & 0xff) << 8 | (input[offset + 2] & 0xff);
d += ((e << 5) | (e >>> 27)) + 0x5a827999 // K11
+ ((a & (b ^ c)) ^ c) // Ch(a,b,c)
+ (i11); // W11
a = (a << 30) | (a >>> 2);
i12 = input[offset + 3] << 24 | (input[offset + 4] & 0xff) << 16
| (input[offset += 5] & 0xff) << 8 | (input[offset + 1] & 0xff);
c += ((d << 5) | (d >>> 27)) + 0x5a827999 // K12
+ ((e & (a ^ b)) ^ b) // Ch(e,a,b)
+ (i12); // W12
e = (e << 30) | (e >>> 2);
i13 = input[offset + 2] << 24 | (input[offset + 3] & 0xff) << 16
| (input[offset + 4] & 0xff) << 8 | (input[offset += 5] & 0xff);
b += ((c << 5) | (c >>> 27)) + 0x5a827999 // K13
+ ((d & (e ^ a)) ^ a) // Ch(d,e,a)
+ (i13); // W13
d = (d << 30) | (d >>> 2);
i14 = input[offset + 1] << 24 | (input[offset + 2] & 0xff) << 16
| (input[offset + 3] & 0xff) << 8 | (input[offset + 4] & 0xff);
a += ((b << 5) | (b >>> 27)) + 0x5a827999 // K14
+ ((c & (d ^ e)) ^ e) // Ch(c,d,e)
+ (i14); // W14
c = (c << 30) | (c >>> 2);
i15 = input[offset += 5] << 24 | (input[offset + 1] & 0xff) << 16
| (input[offset + 2] & 0xff) << 8 | (input[offset + 3] & 0xff);
e += ((a << 5) | (a >>> 27)) + 0x5a827999 // K15
+ ((b & (c ^ d)) ^ d) // Ch(b,c,d)
+ (i15); // W15
/* Second pass, on scheduled input (rounds 16..31). */
b = (b << 30) | (b >>> 2);
i00 ^= i02 ^ i08 ^ i13;
i00 = (i00 << 1) | (i00 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x5a827999 // K16
+ ((a & (b ^ c)) ^ c) // Ch(a,b,c)
+ (i00); // W16
a = (a << 30) | (a >>> 2);
i01 ^= i03 ^ i09 ^ i14;
i01 = (i01 << 1) | (i01 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x5a827999 // K17
+ ((e & (a ^ b)) ^ b) // Ch(e,a,b)
+ (i01); // W17
e = (e << 30) | (e >>> 2);
i02 ^= i04 ^ i10 ^ i15;
i02 = (i02 << 1) | (i02 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x5a827999 // K18
+ ((d & (e ^ a)) ^ a) // Ch(d,e,a)
+ (i02); // W18
d = (d << 30) | (d >>> 2);
i03 ^= i05 ^ i11 ^ i00;
i03 = (i03 << 1) | (i03 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x5a827999 // K19
+ ((c & (d ^ e)) ^ e) // Ch(c,d,e)
+ (i03); // W19
/*
* Use hash schedule function Parity (rounds 20..39): Parity(x,y,z) = x ^
* y ^ z, and K20 = .... = K39 = 0x6ed9eba1.
*/
c = (c << 30) | (c >>> 2);
i04 ^= i06 ^ i12 ^ i01;
i04 = (i04 << 1) | (i04 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K20
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i04); // W20
b = (b << 30) | (b >>> 2);
i05 ^= i07 ^ i13 ^ i02;
i05 = (i05 << 1) | (i05 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K21
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i05); // W21
a = (a << 30) | (a >>> 2);
i06 ^= i08 ^ i14 ^ i03;
i06 = (i06 << 1) | (i06 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K22
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i06); // W22
e = (e << 30) | (e >>> 2);
i07 ^= i09 ^ i15 ^ i04;
i07 = (i07 << 1) | (i07 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K23
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i07); // W23
d = (d << 30) | (d >>> 2);
i08 ^= i10 ^ i00 ^ i05;
i08 = (i08 << 1) | (i08 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K24
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i08); // W24
c = (c << 30) | (c >>> 2);
i09 ^= i11 ^ i01 ^ i06;
i09 = (i09 << 1) | (i09 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K25
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i09); // W25
b = (b << 30) | (b >>> 2);
i10 ^= i12 ^ i02 ^ i07;
i10 = (i10 << 1) | (i10 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K26
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i10); // W26
a = (a << 30) | (a >>> 2);
i11 ^= i13 ^ i03 ^ i08;
i11 = (i11 << 1) | (i11 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K27
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i11); // W27
e = (e << 30) | (e >>> 2);
i12 ^= i14 ^ i04 ^ i09;
i12 = (i12 << 1) | (i12 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K28
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i12); // W28
d = (d << 30) | (d >>> 2);
i13 ^= i15 ^ i05 ^ i10;
i13 = (i13 << 1) | (i13 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K29
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i13); // W29
c = (c << 30) | (c >>> 2);
i14 ^= i00 ^ i06 ^ i11;
i14 = (i14 << 1) | (i14 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K30
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i14); // W30
b = (b << 30) | (b >>> 2);
i15 ^= i01 ^ i07 ^ i12;
i15 = (i15 << 1) | (i15 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K31
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i15); // W31
/* Third pass, on scheduled input (rounds 32..47). */
a = (a << 30) | (a >>> 2);
i00 ^= i02 ^ i08 ^ i13;
i00 = (i00 << 1) | (i00 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K32
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i00); // W32
e = (e << 30) | (e >>> 2);
i01 ^= i03 ^ i09 ^ i14;
i01 = (i01 << 1) | (i01 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K33
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i01); // W33
d = (d << 30) | (d >>> 2);
i02 ^= i04 ^ i10 ^ i15;
i02 = (i02 << 1) | (i02 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K34
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i02); // W34
c = (c << 30) | (c >>> 2);
i03 ^= i05 ^ i11 ^ i00;
i03 = (i03 << 1) | (i03 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x6ed9eba1 // K35
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i03); // W35
b = (b << 30) | (b >>> 2);
i04 ^= i06 ^ i12 ^ i01;
i04 = (i04 << 1) | (i04 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x6ed9eba1 // K36
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i04); // W36
a = (a << 30) | (a >>> 2);
i05 ^= i07 ^ i13 ^ i02;
i05 = (i05 << 1) | (i05 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x6ed9eba1 // K37
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i05); // W37
e = (e << 30) | (e >>> 2);
i06 ^= i08 ^ i14 ^ i03;
i06 = (i06 << 1) | (i06 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x6ed9eba1 // K38
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i06); // W38
d = (d << 30) | (d >>> 2);
i07 ^= i09 ^ i15 ^ i04;
i07 = (i07 << 1) | (i07 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x6ed9eba1 // K39
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i07); // 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.
*/
c = (c << 30) | (c >>> 2);
i08 ^= i10 ^ i00 ^ i05;
i08 = (i08 << 1) | (i08 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K40
+ ((b & c) | ((b | c) & d)) // Maj(b,c,d)
+ (i08); // W40
b = (b << 30) | (b >>> 2);
i09 ^= i11 ^ i01 ^ i06;
i09 = (i09 << 1) | (i09 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K41
+ ((a & b) | ((a | b) & c)) // Maj(a,b,c)
+ (i09); // W41
a = (a << 30) | (a >>> 2);
i10 ^= i12 ^ i02 ^ i07;
i10 = (i10 << 1) | (i10 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K42
+ ((e & a) | ((e | a) & b)) // Maj(e,a,b)
+ (i10); // W42
e = (e << 30) | (e >>> 2);
i11 ^= i13 ^ i03 ^ i08;
i11 = (i11 << 1) | (i11 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K43
+ ((d & e) | ((d | e) & a)) // Maj(d,e,a)
+ (i11); // W43
d = (d << 30) | (d >>> 2);
i12 ^= i14 ^ i04 ^ i09;
i12 = (i12 << 1) | (i12 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K44
+ ((c & d) | ((c | d) & e)) // Maj(c,d,e)
+ (i12); // W44
c = (c << 30) | (c >>> 2);
i13 ^= i15 ^ i05 ^ i10;
i13 = (i13 << 1) | (i13 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K45
+ ((b & c) | ((b | c) & d)) // Maj(b,c,d)
+ (i13); // W45
b = (b << 30) | (b >>> 2);
i14 ^= i00 ^ i06 ^ i11;
i14 = (i14 << 1) | (i14 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K46
+ ((a & b) | ((a | b) & c)) // Maj(a,b,c)
+ (i14); // W46
a = (a << 30) | (a >>> 2);
i15 ^= i01 ^ i07 ^ i12;
i15 = (i15 << 1) | (i15 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K47
+ ((e & a) | ((e | a) & b)) // Maj(e,a,b)
+ (i15); // W47
/* Fourth pass, on scheduled input (rounds 48..63). */
e = (e << 30) | (e >>> 2);
i00 ^= i02 ^ i08 ^ i13;
i00 = (i00 << 1) | (i00 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K48
+ ((d & e) | ((d | e) & a)) // Maj(d,e,a)
+ (i00); // W48
d = (d << 30) | (d >>> 2);
i01 ^= i03 ^ i09 ^ i14;
i01 = (i01 << 1) | (i01 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K49
+ ((c & d) | ((c | d) & e)) // Maj(c,d,e)
+ (i01); // W49
c = (c << 30) | (c >>> 2);
i02 ^= i04 ^ i10 ^ i15;
i02 = (i02 << 1) | (i02 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K50
+ ((b & c) | ((b | c) & d)) // Maj(b,c,d)
+ (i02); // W50
b = (b << 30) | (b >>> 2);
i03 ^= i05 ^ i11 ^ i00;
i03 = (i03 << 1) | (i03 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K51
+ ((a & b) | ((a | b) & c)) // Maj(a,b,c)
+ (i03); // W51
a = (a << 30) | (a >>> 2);
i04 ^= i06 ^ i12 ^ i01;
i04 = (i04 << 1) | (i04 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K52
+ ((e & a) | ((e | a) & b)) // Maj(e,a,b)
+ (i04); // W52
e = (e << 30) | (e >>> 2);
i05 ^= i07 ^ i13 ^ i02;
i05 = (i05 << 1) | (i05 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K53
+ ((d & e) | ((d | e) & a)) // Maj(d,e,a)
+ (i05); // W53
d = (d << 30) | (d >>> 2);
i06 ^= i08 ^ i14 ^ i03;
i06 = (i06 << 1) | (i06 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K54
+ ((c & d) | ((c | d) & e)) // Maj(c,d,e)
+ (i06); // W54
c = (c << 30) | (c >>> 2);
i07 ^= i09 ^ i15 ^ i04;
i07 = (i07 << 1) | (i07 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0x8f1bbcdc // K55
+ ((b & c) | ((b | c) & d)) // Maj(b,c,d)
+ (i07); // W55
b = (b << 30) | (b >>> 2);
i08 ^= i10 ^ i00 ^ i05;
i08 = (i08 << 1) | (i08 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0x8f1bbcdc // K56
+ ((a & b) | ((a | b) & c)) // Maj(a,b,c)
+ (i08); // W56
a = (a << 30) | (a >>> 2);
i09 ^= i11 ^ i01 ^ i06;
i09 = (i09 << 1) | (i09 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0x8f1bbcdc // K57
+ ((e & a) | ((e | a) & b)) // Maj(e,a,b)
+ (i09); // W57
e = (e << 30) | (e >>> 2);
i10 ^= i12 ^ i02 ^ i07;
i10 = (i10 << 1) | (i10 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0x8f1bbcdc // K58
+ ((d & e) | ((d | e) & a)) // Maj(d,e,a)
+ (i10); // W58
d = (d << 30) | (d >>> 2);
i11 ^= i13 ^ i03 ^ i08;
i11 = (i11 << 1) | (i11 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0x8f1bbcdc // K59
+ ((c & d) | ((c | d) & e)) // Maj(c,d,e)
+ (i11); // W59
/*
* Use hash schedule function Parity (rounds 60..79): Parity(x,y,z) = x ^
* y ^ z, and K60 = .... = K79 = 0xca62c1d6.
*/
c = (c << 30) | (c >>> 2);
i12 ^= i14 ^ i04 ^ i09;
i12 = (i12 << 1) | (i12 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K60
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i12); // W60
b = (b << 30) | (b >>> 2);
i13 ^= i15 ^ i05 ^ i10;
i13 = (i13 << 1) | (i13 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K61
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i13); // W61
a = (a << 30) | (a >>> 2);
i14 ^= i00 ^ i06 ^ i11;
i14 = (i14 << 1) | (i14 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K62
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i14); // W62
e = (e << 30) | (e >>> 2);
i15 ^= i01 ^ i07 ^ i12;
i15 = (i15 << 1) | (i15 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K63
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i15); // W63
/* Fifth pass, on scheduled input (rounds 64..79). */
d = (d << 30) | (d >>> 2);
i00 ^= i02 ^ i08 ^ i13;
i00 = (i00 << 1) | (i00 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K64
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i00); // W64
c = (c << 30) | (c >>> 2);
i01 ^= i03 ^ i09 ^ i14;
i01 = (i01 << 1) | (i01 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K65
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i01); // W65
b = (b << 30) | (b >>> 2);
i02 ^= i04 ^ i10 ^ i15;
i02 = (i02 << 1) | (i02 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K66
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i02); // W66
a = (a << 30) | (a >>> 2);
i03 ^= i05 ^ i11 ^ i00;
i03 = (i03 << 1) | (i03 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K67
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i03); // W67
e = (e << 30) | (e >>> 2);
i04 ^= i06 ^ i12 ^ i01;
i04 = (i04 << 1) | (i04 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K68
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i04); // W68
d = (d << 30) | (d >>> 2);
i05 ^= i07 ^ i13 ^ i02;
i05 = (i05 << 1) | (i05 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K69
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i05); // W69
c = (c << 30) | (c >>> 2);
i06 ^= i08 ^ i14 ^ i03;
i06 = (i06 << 1) | (i06 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K70
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i06); // W70
b = (b << 30) | (b >>> 2);
i07 ^= i09 ^ i15 ^ i04;
i07 = (i07 << 1) | (i07 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K71
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i07); // W71
a = (a << 30) | (a >>> 2);
i08 ^= i10 ^ i00 ^ i05;
i08 = (i08 << 1) | (i08 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K72
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i08); // W72
e = (e << 30) | (e >>> 2);
i09 ^= i11 ^ i01 ^ i06;
i09 = (i09 << 1) | (i09 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K73
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i09); // W73
d = (d << 30) | (d >>> 2);
i10 ^= i12 ^ i02 ^ i07;
i10 = (i10 << 1) | (i10 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K74
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i10); // W74
c = (c << 30) | (c >>> 2);
i11 ^= i13 ^ i03 ^ i08;
i11 = (i11 << 1) | (i11 >>> 31);
e += ((a << 5) | (a >>> 27)) + 0xca62c1d6 // K75
+ (b ^ c ^ d) // Parity(b,c,d)
+ (i11); // W75
b = (b << 30) | (b >>> 2);
i12 ^= i14 ^ i04 ^ i09;
i12 = (i12 << 1) | (i12 >>> 31);
d += ((e << 5) | (e >>> 27)) + 0xca62c1d6 // K76
+ (a ^ b ^ c) // Parity(a,b,c)
+ (i12); // W76
a = (a << 30) | (a >>> 2);
i13 ^= i15 ^ i05 ^ i10;
i13 = (i13 << 1) | (i13 >>> 31);
c += ((d << 5) | (d >>> 27)) + 0xca62c1d6 // K77
+ (e ^ a ^ b) // Parity(e,a,b)
+ (i13); // W77
/*
* Terminate the last two rounds of fifth pass, feeding the final digest
* on the fly.
*/
e = (e << 30) | (e >>> 2);
i14 ^= i00 ^ i06 ^ i11;
i14 = (i14 << 1) | (i14 >>> 31);
b += ((c << 5) | (c >>> 27)) + 0xca62c1d6 // K78
+ (d ^ e ^ a) // Parity(d,e,a)
+ (i14); // W78
hB += b;
d = (d << 30) | (d >>> 2);
i15 ^= i01 ^ i07 ^ i12;
i15 = (i15 << 1) | (i15 >>> 31);
a += ((b << 5) | (b >>> 27)) + 0xca62c1d6 // K79
+ (c ^ d ^ e) // Parity(c,d,e)
+ (i15); // W79
hA += a;
hE += e;
hD += d;
hC += /* c= */(c << 30) | (c >>> 2);
}
}
SHA1Test.java
(text/plain, 9.5 KB)
/* @(#)SHA1Test.java 1.10 2004-04-24
* 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
*/
/* Sun may wish to change the following package name, if integrating this
* class in the Sun JCE Security Provider for Java 1.5 (code-named Tiger).
*/
//package com.bitzi.util;
import java.security.*;
public class SHA1Test {
private static final SHA1 hash = new SHA1();
public static void main(String args[]) {
// http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
System.out.println("****************************************");
System.out.println("* Basic FIPS PUB 180-1 test vectors... *");
System.out.println("****************************************");
tst(1, 1,
"abc",
"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
tst(1, 2,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"84983E44 1C3BD26e BAAE4AA1 F95129E5 E54670F1");
tst(1, 3, /* one million bytes */
1000000, "a",
"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
System.out.println();
// http://csrc.ncsl.nist.gov/cryptval/shs/SHAVS.pdf
System.out.println("********************************************************");
System.out.println("* SHSV Examples of the selected short messages test... *");
System.out.println("********************************************************");
tst(2, 2, new byte[] {/* 8 bits, i.e. 1 byte */
(byte)0x5e},
"5e6f80a3 4a9798ca fc6a5db9 6cc57ba4 c4db59c2");
tst(2, 4, new byte[] {/* 128 bits, i.e. 16 bytes */
(byte)0x9a,(byte)0x7d,(byte)0xfd,(byte)0xf1,(byte)0xec,(byte)0xea,(byte)0xd0,(byte)0x6e,
(byte)0xd6,(byte)0x46,(byte)0xaa,(byte)0x55,(byte)0xfe,(byte)0x75,(byte)0x71,(byte)0x46},
"82abff66 05dbe1c1 7def12a3 94fa22a8 2b544a35");
System.out.println();
System.out.println("*******************************************************");
System.out.println("* SHSV Examples of the selected long messages test... *");
System.out.println("*******************************************************");
tst(3, 2, new byte[] {/* 1304 bits, i.e. 163 bytes */
(byte)0xf7,(byte)0x8f,(byte)0x92,(byte)0x14,(byte)0x1b,(byte)0xcd,(byte)0x17,(byte)0x0a,
(byte)0xe8,(byte)0x9b,(byte)0x4f,(byte)0xba,(byte)0x15,(byte)0xa1,(byte)0xd5,(byte)0x9f,
(byte)0x3f,(byte)0xd8,(byte)0x4d,(byte)0x22,(byte)0x3c,(byte)0x92,(byte)0x51,(byte)0xbd,
(byte)0xac,(byte)0xbb,(byte)0xae,(byte)0x61,(byte)0xd0,(byte)0x5e,(byte)0xd1,(byte)0x15,
(byte)0xa0,(byte)0x6a,(byte)0x7c,(byte)0xe1,(byte)0x17,(byte)0xb7,(byte)0xbe,(byte)0xea,
(byte)0xd2,(byte)0x44,(byte)0x21,(byte)0xde,(byte)0xd9,(byte)0xc3,(byte)0x25,(byte)0x92,
(byte)0xbd,(byte)0x57,(byte)0xed,(byte)0xea,(byte)0xe3,(byte)0x9c,(byte)0x39,(byte)0xfa,
(byte)0x1f,(byte)0xe8,(byte)0x94,(byte)0x6a,(byte)0x84,(byte)0xd0,(byte)0xcf,(byte)0x1f,
(byte)0x7b,(byte)0xee,(byte)0xad,(byte)0x17,(byte)0x13,(byte)0xe2,(byte)0xe0,(byte)0x95,
(byte)0x98,(byte)0x97,(byte)0x34,(byte)0x7f,(byte)0x67,(byte)0xc8,(byte)0x0b,(byte)0x04,
(byte)0x00,(byte)0xc2,(byte)0x09,(byte)0x81,(byte)0x5d,(byte)0x6b,(byte)0x10,(byte)0xa6,
(byte)0x83,(byte)0x83,(byte)0x6f,(byte)0xd5,(byte)0x56,(byte)0x2a,(byte)0x56,(byte)0xca,
(byte)0xb1,(byte)0xa2,(byte)0x8e,(byte)0x81,(byte)0xb6,(byte)0x57,(byte)0x66,(byte)0x54,
(byte)0x63,(byte)0x1c,(byte)0xf1,(byte)0x65,(byte)0x66,(byte)0xb8,(byte)0x6e,(byte)0x3b,
(byte)0x33,(byte)0xa1,(byte)0x08,(byte)0xb0,(byte)0x53,(byte)0x07,(byte)0xc0,(byte)0x0a,
(byte)0xff,(byte)0x14,(byte)0xa7,(byte)0x68,(byte)0xed,(byte)0x73,(byte)0x50,(byte)0x60,
(byte)0x6a,(byte)0x0f,(byte)0x85,(byte)0xe6,(byte)0xa9,(byte)0x1d,(byte)0x39,(byte)0x6f,
(byte)0x5b,(byte)0x5c,(byte)0xbe,(byte)0x57,(byte)0x7f,(byte)0x9b,(byte)0x38,(byte)0x80,
(byte)0x7c,(byte)0x7d,(byte)0x52,(byte)0x3d,(byte)0x6d,(byte)0x79,(byte)0x2f,(byte)0x6e,
(byte)0xbc,(byte)0x24,(byte)0xa4,(byte)0xec,(byte)0xf2,(byte)0xb3,(byte)0xa4,(byte)0x27,
(byte)0xcd,(byte)0xbb,(byte)0xfb},
"cb0082c8 f197d260 991ba6a4 60e76e20 2bad27b3");
System.out.println();
// See also http://csrc.ncsl.nist.gov/cryptval/shs/sha1-vectors.zip
{
final int RETRIES = 10;
final int ITERATIONS = 2000;
final int BLOCKSIZE = 65536;
byte[] input = new byte[BLOCKSIZE];
for (int i = BLOCKSIZE; --i >= 0; )
input[i] = (byte)i;
long best = 0;
for (int i = 0; i < 1000; i++) // training for stable measure
System.currentTimeMillis();
for (int retry = 0; retry < RETRIES; retry++) {
long t0 = System.currentTimeMillis();
for (int i = ITERATIONS; --i >= 0; );
long t1 = System.currentTimeMillis();
for (int i = ITERATIONS; --i >= 0; )
hash.engineUpdate(input, 0, BLOCKSIZE);
long t2 = System.currentTimeMillis();
long time = (t2 - t1) - (t1 - t0);
if (retry == 0 || time < best)
best = time;
}
hash.engineReset();
double rate = 1000.0 * ITERATIONS * BLOCKSIZE / best;
System.out.println("Our rate = " +
(float)(rate * 8) + " bits/s = " +
(float)(rate / (1024 * 1024)) + " Megabytes/s");
// Java 1.5 beta-b32c, on Athlon XP 1800+:
// with java -client: 48.21 Megabytes/s.
// with java -server: 68.23 Megabytes/s.
try {
MessageDigest md = MessageDigest.getInstance("SHA");
for (int retry = 0; retry < RETRIES; retry++) {
long t0 = System.currentTimeMillis();
for (int i = ITERATIONS; --i >= 0; );
long t1 = System.currentTimeMillis();
for (int i = ITERATIONS; --i >= 0; )
md.update(input, 0, BLOCKSIZE);
long t2 = System.currentTimeMillis();
long time = (t2 - t1) - (t1 - t0);
if (retry == 0 || time < best)
best = time;
}
md.reset();
rate = 1000.0 * ITERATIONS * BLOCKSIZE / best;
System.out.println("JCE rate = " +
(float)(rate * 8) + " bits/s = " +
(float)(rate / (1024 * 1024)) + " Megabytes/s");
} catch (NoSuchAlgorithmException nsae) {
System.out.println("No SHA algorithm in local JCE Security Providers");
}
// Java 1.5 beta-b32c, on Athlon XP 1800+:
// with java -client: 23.20 Megabytes/s.
// with java -server: 45.72 Megabytes/s.
}
}
private static final boolean tst(final int set, final int vector,
final String source,
final String expect) {
byte[] input = new byte[source.length()];
for (int i = 0; i < input.length; i++)
input[i] = (byte)source.charAt(i);
return tst(set, vector, input, expect);
}
private static final boolean tst(final int set, final int vector,
final byte[] input,
final String expect) {
System.out.print("Set " + set + ", vector# " + vector + ": ");
hash.engineUpdate(input, 0, input.length);
return tstResult(expect);
}
private static final boolean tst(final int set, final int vector,
final int times, final String source,
final String expect) {
byte[] input = new byte[source.length()];
for (int i = 0; i < input.length; i++)
input[i] = (byte)source.charAt(i);
System.out.print("Set " + set + ", vector# " + vector + ": ");
for (int i = 0; i < times; i++)
hash.engineUpdate(input, 0, input.length);
return tstResult(expect);
}
private static final boolean tstResult(String expect) {
final String result = toHex(hash.engineDigest());
expect = expect.toUpperCase();
if (!expect.equals(result)) {
System.out.println("**************** WRONG ***************");
System.out.println(" expect: " + expect);
System.out.println(" result: " + result);
return false;
}
System.out.println("OK");
return true;
}
private static final String toHex(final byte[] bytes) {
StringBuffer buf = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
if ((i & 3) == 0 && i != 0)
buf.append(' ');
buf.append(HEX.charAt((bytes[i] >> 4) & 0xF))
.append(HEX.charAt( bytes[i] & 0xF));
}
return buf.toString();
}
private static final String HEX = "0123456789ABCDEF";
}
PGP.sig
(application/pgp-signature, 186 B) - not displayed