2011-03-25 20:58:43 -04:00
package com.cypherx.xauth ;
2011-03-25 20:42:41 -04:00
/ * *
* The Whirlpool hashing function .
*
* < P >
* < b > References < / b >
*
* < P >
* The Whirlpool algorithm was developed by
* < a href = " mailto:pbarreto@scopus.com.br " > Paulo S . L . M . Barreto < / a > and
* < a href = " mailto:vincent.rijmen@cryptomathic.com " > Vincent Rijmen < / a > .
*
* See
* P . S . L . M . Barreto , V . Rijmen ,
* ` ` The Whirlpool hashing function , ' '
* First NESSIE workshop , 2000 ( tweaked version , 2003 ) ,
* < https : //www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
*
* @author Paulo S . L . M . Barreto
* @author Vincent Rijmen .
*
* @version 3 . 0 ( 2003 . 03 . 12 )
*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Differences from version 2 . 1 :
*
* - Suboptimal diffusion matrix replaced by cir ( 1 , 1 , 4 , 1 , 8 , 5 , 2 , 9 ) .
*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Differences from version 2 . 0 :
*
* - Generation of ISO / IEC 10118 - 3 test vectors .
* - Bug fix : nonzero carry was ignored when tallying the data length
* ( this bug apparently only manifested itself when feeding data
* in pieces rather than in a single chunk at once ) .
*
* Differences from version 1 . 0 :
*
* - Original S - box replaced by the tweaked , hardware - efficient version .
*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ' ' AS IS ' ' AND ANY EXPRESS
* OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR
* BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ,
* WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE
* OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE ,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* /
2011-03-25 20:41:16 -04:00
import java.util.Arrays ;
class Whirlpool {
2011-03-25 20:42:41 -04:00
/ * *
* The message digest size ( in bits )
* /
2011-03-25 20:41:16 -04:00
public static final int DIGESTBITS = 512 ;
2011-03-25 20:42:41 -04:00
/ * *
* The message digest size ( in bytes )
* /
2011-03-25 20:41:16 -04:00
public static final int DIGESTBYTES = DIGESTBITS > > > 3 ;
2011-03-25 20:42:41 -04:00
/ * *
* The number of rounds of the internal dedicated block cipher .
* /
2011-03-25 20:41:16 -04:00
protected static final int R = 10 ;
2011-03-25 20:42:41 -04:00
/ * *
* The substitution box .
* /
2011-03-25 20:41:16 -04:00
private static final String sbox =
" \ u1823 \ uc6E8 \ u87B8 \ u014F \ u36A6 \ ud2F5 \ u796F \ u9152 " +
" \ u60Bc \ u9B8E \ uA30c \ u7B35 \ u1dE0 \ ud7c2 \ u2E4B \ uFE57 " +
" \ u1577 \ u37E5 \ u9FF0 \ u4AdA \ u58c9 \ u290A \ uB1A0 \ u6B85 " +
" \ uBd5d \ u10F4 \ ucB3E \ u0567 \ uE427 \ u418B \ uA77d \ u95d8 " +
" \ uFBEE \ u7c66 \ udd17 \ u479E \ ucA2d \ uBF07 \ uAd5A \ u8333 " +
" \ u6302 \ uAA71 \ uc819 \ u49d9 \ uF2E3 \ u5B88 \ u9A26 \ u32B0 " +
" \ uE90F \ ud580 \ uBEcd \ u3448 \ uFF7A \ u905F \ u2068 \ u1AAE " +
" \ uB454 \ u9322 \ u64F1 \ u7312 \ u4008 \ uc3Ec \ udBA1 \ u8d3d " +
" \ u9700 \ ucF2B \ u7682 \ ud61B \ uB5AF \ u6A50 \ u45F3 \ u30EF " +
" \ u3F55 \ uA2EA \ u65BA \ u2Fc0 \ udE1c \ uFd4d \ u9275 \ u068A " +
" \ uB2E6 \ u0E1F \ u62d4 \ uA896 \ uF9c5 \ u2559 \ u8472 \ u394c " +
" \ u5E78 \ u388c \ ud1A5 \ uE261 \ uB321 \ u9c1E \ u43c7 \ uFc04 " +
" \ u5199 \ u6d0d \ uFAdF \ u7E24 \ u3BAB \ ucE11 \ u8F4E \ uB7EB " +
" \ u3c81 \ u94F7 \ uB913 \ u2cd3 \ uE76E \ uc403 \ u5644 \ u7FA9 " +
" \ u2ABB \ uc153 \ udc0B \ u9d6c \ u3174 \ uF646 \ uAc89 \ u14E1 " +
" \ u163A \ u6909 \ u70B6 \ ud0Ed \ ucc42 \ u98A4 \ u285c \ uF886 " ;
private static long [ ] [ ] C = new long [ 8 ] [ 256 ] ;
private static long [ ] rc = new long [ R + 1 ] ;
static {
for ( int x = 0 ; x < 256 ; x + + ) {
char c = sbox . charAt ( x / 2 ) ;
long v1 = ( ( x & 1 ) = = 0 ) ? c > > > 8 : c & 0xff ;
long v2 = v1 < < 1 ;
if ( v2 > = 0x100L ) {
v2 ^ = 0x11dL ;
}
long v4 = v2 < < 1 ;
if ( v4 > = 0x100L ) {
v4 ^ = 0x11dL ;
}
long v5 = v4 ^ v1 ;
long v8 = v4 < < 1 ;
if ( v8 > = 0x100L ) {
v8 ^ = 0x11dL ;
}
long v9 = v8 ^ v1 ;
2011-03-25 20:42:41 -04:00
/ *
* build the circulant table C [ 0 ] [ x ] = S [ x ] . [ 1 , 1 , 4 , 1 , 8 , 5 , 2 , 9 ] :
* /
2011-03-25 20:41:16 -04:00
C [ 0 ] [ x ] =
( v1 < < 56 ) | ( v1 < < 48 ) | ( v4 < < 40 ) | ( v1 < < 32 ) |
( v8 < < 24 ) | ( v5 < < 16 ) | ( v2 < < 8 ) | ( v9 ) ;
2011-03-25 20:42:41 -04:00
/ *
* build the remaining circulant tables C [ t ] [ x ] = C [ 0 ] [ x ] rotr t
* /
2011-03-25 20:41:16 -04:00
for ( int t = 1 ; t < 8 ; t + + ) {
C [ t ] [ x ] = ( C [ t - 1 ] [ x ] > > > 8 ) | ( ( C [ t - 1 ] [ x ] < < 56 ) ) ;
}
}
2011-03-25 20:42:41 -04:00
/ *
for ( int t = 0 ; t < 8 ; t + + ) {
System . out . println ( " static const u64 C " + t + " [256] = { " ) ;
for ( int i = 0 ; i < 64 ; i + + ) {
System . out . print ( " " ) ;
for ( int j = 0 ; j < 4 ; j + + ) {
String v = Long . toHexString ( C [ t ] [ 4 * i + j ] ) ;
while ( v . length ( ) < 16 ) {
v = " 0 " + v ;
}
System . out . print ( " LL(0x " + v + " ), " ) ;
}
System . out . println ( ) ;
}
System . out . println ( " }; " ) ;
System . out . println ( ) ;
}
System . out . println ( ) ;
//*/
2011-03-25 20:41:16 -04:00
2011-03-25 20:42:41 -04:00
/ *
* build the round constants :
* /
rc [ 0 ] = 0L ; /* not used (assigment kept only to properly initialize all variables) */
2011-03-25 20:41:16 -04:00
for ( int r = 1 ; r < = R ; r + + ) {
int i = 8 * ( r - 1 ) ;
rc [ r ] =
( C [ 0 ] [ i ] & 0xff00000000000000L ) ^
( C [ 1 ] [ i + 1 ] & 0x00ff000000000000L ) ^
( C [ 2 ] [ i + 2 ] & 0x0000ff0000000000L ) ^
( C [ 3 ] [ i + 3 ] & 0x000000ff00000000L ) ^
( C [ 4 ] [ i + 4 ] & 0x00000000ff000000L ) ^
( C [ 5 ] [ i + 5 ] & 0x0000000000ff0000L ) ^
( C [ 6 ] [ i + 6 ] & 0x000000000000ff00L ) ^
( C [ 7 ] [ i + 7 ] & 0x00000000000000ffL ) ;
}
2011-03-25 20:42:41 -04:00
/ *
System . out . println ( " static const u64 rc[R + 1] = { " ) ;
for ( int r = 0 ; r < = R ; r + + ) {
String v = Long . toHexString ( rc [ r ] ) ;
while ( v . length ( ) < 16 ) {
v = " 0 " + v ;
}
System . out . println ( " LL(0x " + v + " ), " ) ;
}
System . out . println ( " }; " ) ;
System . out . println ( ) ;
//*/
2011-03-25 20:41:16 -04:00
}
2011-03-25 20:42:41 -04:00
/ * *
* Global number of hashed bits ( 256 - bit counter ) .
* /
2011-03-25 20:41:16 -04:00
protected byte [ ] bitLength = new byte [ 32 ] ;
2011-03-25 20:42:41 -04:00
/ * *
* Buffer of data to hash .
* /
2011-03-25 20:41:16 -04:00
protected byte [ ] buffer = new byte [ 64 ] ;
2011-03-25 20:42:41 -04:00
/ * *
* Current number of bits on the buffer .
* /
2011-03-25 20:41:16 -04:00
protected int bufferBits = 0 ;
2011-03-25 20:42:41 -04:00
/ * *
* Current ( possibly incomplete ) byte slot on the buffer .
* /
2011-03-25 20:41:16 -04:00
protected int bufferPos = 0 ;
2011-03-25 20:42:41 -04:00
/ * *
* The hashing state .
* /
2011-03-25 20:41:16 -04:00
protected long [ ] hash = new long [ 8 ] ;
2011-03-25 20:42:41 -04:00
protected long [ ] K = new long [ 8 ] ; // the round key
2011-03-25 20:41:16 -04:00
protected long [ ] L = new long [ 8 ] ;
2011-03-25 20:42:41 -04:00
protected long [ ] block = new long [ 8 ] ; // mu(buffer)
protected long [ ] state = new long [ 8 ] ; // the cipher state
2011-03-25 20:41:16 -04:00
2011-03-25 20:42:41 -04:00
public Whirlpool ( ) {
}
2011-03-25 20:41:16 -04:00
2011-03-25 20:42:41 -04:00
/ * *
* The core Whirlpool transform .
* /
2011-03-25 20:41:16 -04:00
protected void processBuffer ( ) {
2011-03-25 20:42:41 -04:00
/ *
* map the buffer to a block :
* /
2011-03-25 20:41:16 -04:00
for ( int i = 0 , j = 0 ; i < 8 ; i + + , j + = 8 ) {
block [ i ] =
( ( ( long ) buffer [ j ] ) < < 56 ) ^
( ( ( long ) buffer [ j + 1 ] & 0xffL ) < < 48 ) ^
( ( ( long ) buffer [ j + 2 ] & 0xffL ) < < 40 ) ^
( ( ( long ) buffer [ j + 3 ] & 0xffL ) < < 32 ) ^
( ( ( long ) buffer [ j + 4 ] & 0xffL ) < < 24 ) ^
( ( ( long ) buffer [ j + 5 ] & 0xffL ) < < 16 ) ^
( ( ( long ) buffer [ j + 6 ] & 0xffL ) < < 8 ) ^
( ( ( long ) buffer [ j + 7 ] & 0xffL ) ) ;
}
2011-03-25 20:42:41 -04:00
/ *
* compute and apply K ^ 0 to the cipher state :
* /
2011-03-25 20:41:16 -04:00
for ( int i = 0 ; i < 8 ; i + + ) {
state [ i ] = block [ i ] ^ ( K [ i ] = hash [ i ] ) ;
}
2011-03-25 20:42:41 -04:00
/ *
* iterate over all rounds :
* /
2011-03-25 20:41:16 -04:00
for ( int r = 1 ; r < = R ; r + + ) {
2011-03-25 20:42:41 -04:00
/ *
* compute K ^ r from K ^ { r - 1 } :
* /
2011-03-25 20:41:16 -04:00
for ( int i = 0 ; i < 8 ; i + + ) {
L [ i ] = 0L ;
for ( int t = 0 , s = 56 ; t < 8 ; t + + , s - = 8 ) {
L [ i ] ^ = C [ t ] [ ( int ) ( K [ ( i - t ) & 7 ] > > > s ) & 0xff ] ;
}
}
for ( int i = 0 ; i < 8 ; i + + ) {
K [ i ] = L [ i ] ;
}
K [ 0 ] ^ = rc [ r ] ;
2011-03-25 20:42:41 -04:00
/ *
* apply the r - th round transformation :
* /
2011-03-25 20:41:16 -04:00
for ( int i = 0 ; i < 8 ; i + + ) {
L [ i ] = K [ i ] ;
for ( int t = 0 , s = 56 ; t < 8 ; t + + , s - = 8 ) {
L [ i ] ^ = C [ t ] [ ( int ) ( state [ ( i - t ) & 7 ] > > > s ) & 0xff ] ;
}
}
for ( int i = 0 ; i < 8 ; i + + ) {
state [ i ] = L [ i ] ;
}
}
2011-03-25 20:42:41 -04:00
/ *
* apply the Miyaguchi - Preneel compression function :
* /
2011-03-25 20:41:16 -04:00
for ( int i = 0 ; i < 8 ; i + + ) {
hash [ i ] ^ = state [ i ] ^ block [ i ] ;
}
}
2011-03-25 20:42:41 -04:00
/ * *
* Initialize the hashing state .
* /
2011-03-25 20:41:16 -04:00
public void NESSIEinit ( ) {
Arrays . fill ( bitLength , ( byte ) 0 ) ;
bufferBits = bufferPos = 0 ;
2011-03-25 20:42:41 -04:00
buffer [ 0 ] = 0 ; // it's only necessary to cleanup buffer[bufferPos].
Arrays . fill ( hash , 0L ) ; // initial value
2011-03-25 20:41:16 -04:00
}
2011-03-25 20:42:41 -04:00
/ * *
* Delivers input data to the hashing algorithm .
*
* @param source plaintext data to hash .
* @param sourceBits how many bits of plaintext to process .
*
* This method maintains the invariant : bufferBits < 512
* /
2011-03-25 20:41:16 -04:00
public void NESSIEadd ( byte [ ] source , long sourceBits ) {
2011-03-25 20:42:41 -04:00
/ *
sourcePos
|
+ - - - - - - - + - - - - - - - + - - - - - - -
| | | | | | | | | | | | | | | | | | | | | source
+ - - - - - - - + - - - - - - - + - - - - - - -
+ - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - -
| | | | | | | | | | | | | | | | | | | | | | buffer
+ - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - -
|
bufferPos
* /
int sourcePos = 0 ; // index of leftmost source byte containing data (1 to 8 bits).
int sourceGap = ( 8 - ( ( int ) sourceBits & 7 ) ) & 7 ; // space on source[sourcePos].
int bufferRem = bufferBits & 7 ; // occupied bits on buffer[bufferPos].
2011-03-25 20:41:16 -04:00
int b ;
2011-03-25 20:42:41 -04:00
// tally the length of the added data:
2011-03-25 20:41:16 -04:00
long value = sourceBits ;
for ( int i = 31 , carry = 0 ; i > = 0 ; i - - ) {
carry + = ( bitLength [ i ] & 0xff ) + ( ( int ) value & 0xff ) ;
bitLength [ i ] = ( byte ) carry ;
carry > > > = 8 ;
value > > > = 8 ;
}
2011-03-25 20:42:41 -04:00
// process data in chunks of 8 bits:
while ( sourceBits > 8 ) { // at least source[sourcePos] and source[sourcePos+1] contain data.
// take a byte from the source:
2011-03-25 20:41:16 -04:00
b = ( ( source [ sourcePos ] < < sourceGap ) & 0xff ) |
( ( source [ sourcePos + 1 ] & 0xff ) > > > ( 8 - sourceGap ) ) ;
if ( b < 0 | | b > = 256 ) {
throw new RuntimeException ( " LOGIC ERROR " ) ;
}
2011-03-25 20:42:41 -04:00
// process this byte:
2011-03-25 20:41:16 -04:00
buffer [ bufferPos + + ] | = b > > > bufferRem ;
2011-03-25 20:42:41 -04:00
bufferBits + = 8 - bufferRem ; // bufferBits = 8*bufferPos;
2011-03-25 20:41:16 -04:00
if ( bufferBits = = 512 ) {
2011-03-25 20:42:41 -04:00
// process data block:
2011-03-25 20:41:16 -04:00
processBuffer ( ) ;
2011-03-25 20:42:41 -04:00
// reset buffer:
2011-03-25 20:41:16 -04:00
bufferBits = bufferPos = 0 ;
}
buffer [ bufferPos ] = ( byte ) ( ( b < < ( 8 - bufferRem ) ) & 0xff ) ;
bufferBits + = bufferRem ;
2011-03-25 20:42:41 -04:00
// proceed to remaining data:
2011-03-25 20:41:16 -04:00
sourceBits - = 8 ;
sourcePos + + ;
}
2011-03-25 20:42:41 -04:00
// now 0 <= sourceBits <= 8;
// furthermore, all data (if any is left) is in source[sourcePos].
2011-03-25 20:41:16 -04:00
if ( sourceBits > 0 ) {
2011-03-25 20:42:41 -04:00
b = ( source [ sourcePos ] < < sourceGap ) & 0xff ; // bits are left-justified on b.
// process the remaining bits:
2011-03-25 20:41:16 -04:00
buffer [ bufferPos ] | = b > > > bufferRem ;
} else {
b = 0 ;
}
if ( bufferRem + sourceBits < 8 ) {
2011-03-25 20:42:41 -04:00
// all remaining data fits on buffer[bufferPos], and there still remains some space.
2011-03-25 20:41:16 -04:00
bufferBits + = sourceBits ;
} else {
2011-03-25 20:42:41 -04:00
// buffer[bufferPos] is full:
2011-03-25 20:41:16 -04:00
bufferPos + + ;
2011-03-25 20:42:41 -04:00
bufferBits + = 8 - bufferRem ; // bufferBits = 8*bufferPos;
2011-03-25 20:41:16 -04:00
sourceBits - = 8 - bufferRem ;
2011-03-25 20:42:41 -04:00
// now 0 <= sourceBits < 8; furthermore, all data is in source[sourcePos].
2011-03-25 20:41:16 -04:00
if ( bufferBits = = 512 ) {
2011-03-25 20:42:41 -04:00
// process data block:
2011-03-25 20:41:16 -04:00
processBuffer ( ) ;
2011-03-25 20:42:41 -04:00
// reset buffer:
2011-03-25 20:41:16 -04:00
bufferBits = bufferPos = 0 ;
}
buffer [ bufferPos ] = ( byte ) ( ( b < < ( 8 - bufferRem ) ) & 0xff ) ;
bufferBits + = ( int ) sourceBits ;
}
}
2011-03-25 20:42:41 -04:00
/ * *
* Get the hash value from the hashing state .
*
* This method uses the invariant : bufferBits < 512
* /
2011-03-25 20:41:16 -04:00
public void NESSIEfinalize ( byte [ ] digest ) {
2011-03-25 20:42:41 -04:00
// append a '1'-bit:
2011-03-25 20:41:16 -04:00
buffer [ bufferPos ] | = 0x80 > > > ( bufferBits & 7 ) ;
2011-03-25 20:42:41 -04:00
bufferPos + + ; // all remaining bits on the current byte are set to zero.
// pad with zero bits to complete 512N + 256 bits:
2011-03-25 20:41:16 -04:00
if ( bufferPos > 32 ) {
while ( bufferPos < 64 ) {
buffer [ bufferPos + + ] = 0 ;
}
2011-03-25 20:42:41 -04:00
// process data block:
2011-03-25 20:41:16 -04:00
processBuffer ( ) ;
2011-03-25 20:42:41 -04:00
// reset buffer:
2011-03-25 20:41:16 -04:00
bufferPos = 0 ;
}
while ( bufferPos < 32 ) {
buffer [ bufferPos + + ] = 0 ;
}
2011-03-25 20:42:41 -04:00
// append bit length of hashed data:
2011-03-25 20:41:16 -04:00
System . arraycopy ( bitLength , 0 , buffer , 32 , 32 ) ;
2011-03-25 20:42:41 -04:00
// process data block:
2011-03-25 20:41:16 -04:00
processBuffer ( ) ;
2011-03-25 20:42:41 -04:00
// return the completed message digest:
2011-03-25 20:41:16 -04:00
for ( int i = 0 , j = 0 ; i < 8 ; i + + , j + = 8 ) {
long h = hash [ i ] ;
digest [ j ] = ( byte ) ( h > > > 56 ) ;
digest [ j + 1 ] = ( byte ) ( h > > > 48 ) ;
digest [ j + 2 ] = ( byte ) ( h > > > 40 ) ;
digest [ j + 3 ] = ( byte ) ( h > > > 32 ) ;
digest [ j + 4 ] = ( byte ) ( h > > > 24 ) ;
digest [ j + 5 ] = ( byte ) ( h > > > 16 ) ;
digest [ j + 6 ] = ( byte ) ( h > > > 8 ) ;
digest [ j + 7 ] = ( byte ) ( h ) ;
}
}
2011-03-25 20:42:41 -04:00
/ * *
* Delivers string input data to the hashing algorithm .
*
* @param source plaintext data to hash ( ASCII text string ) .
*
* This method maintains the invariant : bufferBits < 512
* /
2011-03-25 20:41:16 -04:00
public void NESSIEadd ( String source ) {
if ( source . length ( ) > 0 ) {
byte [ ] data = new byte [ source . length ( ) ] ;
for ( int i = 0 ; i < source . length ( ) ; i + + ) {
data [ i ] = ( byte ) source . charAt ( i ) ;
}
NESSIEadd ( data , 8 * data . length ) ;
}
}
2011-04-03 17:04:21 -04:00
static String display ( byte [ ] array ) {
2011-03-25 20:41:16 -04:00
char [ ] val = new char [ 2 * array . length ] ;
String hex = " 0123456789ABCDEF " ;
for ( int i = 0 ; i < array . length ; i + + ) {
int b = array [ i ] & 0xff ;
val [ 2 * i ] = hex . charAt ( b > > > 4 ) ;
val [ 2 * i + 1 ] = hex . charAt ( b & 15 ) ;
}
return String . valueOf ( val ) ;
}
2011-03-25 20:42:41 -04:00
private static final int LONG_ITERATION = 100000000 ;
/ * *
* Generate the NESSIE test vector set for Whirlpool .
*
* The test consists of :
* 1 . hashing all bit strings containing only zero bits
* for all lengths from 0 to 1023 ;
* 2 . hashing all 512 - bit strings containing a single set bit ;
* 3 . the iterated hashing of the 512 - bit string of zero bits a large number of times .
* /
public static void makeNESSIETestVectors ( ) {
Whirlpool w = new Whirlpool ( ) ;
byte [ ] digest = new byte [ 64 ] ;
byte [ ] data = new byte [ 128 ] ;
Arrays . fill ( data , ( byte ) 0 ) ;
System . out . println ( " Message digests of strings of 0-bits and length L: " ) ;
for ( int i = 0 ; i < 1024 ; i + + ) {
w . NESSIEinit ( ) ;
w . NESSIEadd ( data , i ) ;
w . NESSIEfinalize ( digest ) ;
String s = Integer . toString ( i ) ;
s = " " . substring ( s . length ( ) ) + s ;
System . out . println ( " L = " + s + " : " + display ( digest ) ) ;
}
System . out . println ( " Message digests of all 512-bit strings S containing a single 1-bit: " ) ;
data = new byte [ 512 / 8 ] ;
Arrays . fill ( data , ( byte ) 0 ) ;
for ( int i = 0 ; i < 512 ; i + + ) {
// set bit i:
data [ i / 8 ] | = 0x80 > > > ( i % 8 ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( data , 512 ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " S = " + display ( data ) + " : " + display ( digest ) ) ;
// reset bit i:
data [ i / 8 ] = 0 ;
}
for ( int i = 0 ; i < digest . length ; i + + ) {
digest [ i ] = 0 ;
}
for ( int i = 0 ; i < LONG_ITERATION ; i + + ) {
w . NESSIEinit ( ) ;
w . NESSIEadd ( digest , 512 ) ;
w . NESSIEfinalize ( digest ) ;
}
System . out . println ( " Iterated message digest computation ( " + LONG_ITERATION + " times): " + display ( digest ) ) ;
}
/ * *
* Generate the ISO / IEC 10118 - 3 test vector set for Whirlpool .
* /
public static void makeISOTestVectors ( ) {
Whirlpool w = new Whirlpool ( ) ;
byte [ ] digest = new byte [ DIGESTBYTES ] ;
byte [ ] data = new byte [ 1000000 ] ;
Arrays . fill ( data , ( byte ) 0 ) ;
System . out . println ( " 1. In this example the data-string is the empty string, i.e. the string of length zero. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 2. In this example the data-string consists of a single byte, namely the ASCII-coded version of the letter 'a'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " a " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 3. In this example the data-string is the three-byte string consisting of the ASCII-coded version of 'abc'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " abc " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 4. In this example the data-string is the 14-byte string consisting of the ASCII-coded version of 'message digest'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " message digest " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 5. In this example the data-string is the 26-byte string consisting of the ASCII-coded version of 'abcdefghijklmnopqrstuvwxyz'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " abcdefghijklmnopqrstuvwxyz " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 6. In this example the data-string is the 62-byte string consisting of the ASCII-coded version of 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 7. In this example the data-string is the 80-byte string consisting of the ASCII-coded version of eight repetitions of '1234567890'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " 12345678901234567890123456789012345678901234567890123456789012345678901234567890 " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
System . out . println ( " 8. In this example the data-string is the 32-byte string consisting of the ASCII-coded version of 'abcdbcdecdefdefgefghfghighijhijk'. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( " abcdbcdecdefdefgefghfghighijhijk " ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
Arrays . fill ( data , ( byte ) 'a' ) ;
System . out . println ( " 9. In this example the data-string is the 1000000-byte string consisting of the ASCII-coded version of 'a' repeated 10^6 times. \ n " ) ;
w . NESSIEinit ( ) ;
w . NESSIEadd ( data , 8 * 1000000 ) ;
w . NESSIEfinalize ( digest ) ;
System . out . println ( " The hash-code is the following 512-bit string. \ n \ n " + display ( digest ) + " \ n " ) ;
}
public static void main ( String [ ] args ) {
//makeNESSIETestVectors();
makeISOTestVectors ( ) ;
}
}