Whirlpool hash function


Detailed Description

WHIRLPOOL is a cryptographic hash function designed after the Square block cipher. WHIRLPOOL is a Miyaguchi-Preneel construction based on a substantially modified Advanced Encryption Standard (AES). Given a message less than 2^256 bits in length, it returns a 512-bit message digest.

The whirlpool_init() function initializes the hash context pointed to by context. After initialization input can be added to the transform routine using whirlpool_add(). Once all bytes have been added the transform has to be finished by calling whilrpool_finalize().

An application should not directly use the internal whirlpool_transform() function, but always use whirlpool_add().

The whirlpool_digest() function combines the procedure explained above for a single string and returns the digest in hexadecimal notation.


Data Structures

struct  whirlpool_t
 dynamic whirlpool state data More...

Defines

#define DIGESTBYTES   64
 number of bytes in the digest
#define DIGESTBITS   (8*DIGESTBYTES)
 number of bits in the digest
#define WBLOCKBYTES   64
 number of bytes in the input buffer
#define WBLOCKBITS   (8*WBLOCKBYTES)
 number of bits in the input buffer
#define LENGTHBYTES   32
 number of hashed bytes
#define LENGTHBITS   (8*LENGTHBYTES)
 number of hashed bits

Functions

void whirlpool_transform (whirlpool_t *const context)
 internal transform routine
void whirlpool_init (whirlpool_t *const context)
 initialize whirlpool state context
void whirlpool_finalize (whirlpool_t *const context, unsigned char *const result)
 finalize whirlpool transformation
void whirlpool_add (whirlpool_t *const context, const unsigned char *const src, unsigned long bits)
 add bytes to the transform routine
char * whirlpool_digest (const char *str)
 create digest from string


Define Documentation

#define DIGESTBYTES   64

number of bytes in the digest

Definition at line 46 of file whirlpool.h.

Referenced by whirlpool_digest(), and whirlpool_finalize().

#define DIGESTBITS   (8*DIGESTBYTES)

number of bits in the digest

Definition at line 49 of file whirlpool.h.

Referenced by whirlpool_add().

#define WBLOCKBYTES   64

number of bytes in the input buffer

Definition at line 53 of file whirlpool.h.

Referenced by whirlpool_finalize().

#define WBLOCKBITS   (8*WBLOCKBYTES)

number of bits in the input buffer

Definition at line 56 of file whirlpool.h.

#define LENGTHBYTES   32

number of hashed bytes

Definition at line 60 of file whirlpool.h.

Referenced by whirlpool_finalize(), and whirlpool_init().

#define LENGTHBITS   (8*LENGTHBYTES)

number of hashed bits

Definition at line 63 of file whirlpool.h.


Function Documentation

void whirlpool_transform ( whirlpool_t *const  context  ) 

internal transform routine

Parameters:
[in] context whirlpool state context

Definition at line 27 of file whirlpool_transform.c.

References whirlpool_t::buf, whirlpool_t::hash, and R.

Referenced by whirlpool_add(), and whirlpool_finalize().

00028 {
00029         int i, r;
00030         uint64_t K[8];
00031         uint64_t block[8];
00032         uint64_t state[8];
00033         uint64_t L[8];
00034         uint8_t *buf = context->buf;
00035 
00036         /* map the buffer to a block */
00037         for (i = 0; i < 8; i++, buf += 8) {
00038                 block[i] = (((uint64_t)buf[0]        ) << 56) ^
00039                            (((uint64_t)buf[1] & 0xffL) << 48) ^
00040                            (((uint64_t)buf[2] & 0xffL) << 40) ^
00041                            (((uint64_t)buf[3] & 0xffL) << 32) ^
00042                            (((uint64_t)buf[4] & 0xffL) << 24) ^
00043                            (((uint64_t)buf[5] & 0xffL) << 16) ^
00044                            (((uint64_t)buf[6] & 0xffL) <<  8) ^
00045                            (((uint64_t)buf[7] & 0xffL)      );
00046         }
00047         
00048         /* compute and apply K^0 to the cipher state */
00049         state[0] = block[0] ^ (K[0] = context->hash[0]);
00050         state[1] = block[1] ^ (K[1] = context->hash[1]);
00051         state[2] = block[2] ^ (K[2] = context->hash[2]);
00052         state[3] = block[3] ^ (K[3] = context->hash[3]);
00053         state[4] = block[4] ^ (K[4] = context->hash[4]);
00054         state[5] = block[5] ^ (K[5] = context->hash[5]);
00055         state[6] = block[6] ^ (K[6] = context->hash[6]);
00056         state[7] = block[7] ^ (K[7] = context->hash[7]);
00057         
00058         /* iterate over all rounds */
00059         for (r = 1; r <= R; r++) {
00060                 /* compute K^r from K^{r-1} */
00061                 L[0] = C0[(int)(K[0] >> 56)       ] ^
00062                        C1[(int)(K[7] >> 48) & 0xff] ^
00063                        C2[(int)(K[6] >> 40) & 0xff] ^
00064                        C3[(int)(K[5] >> 32) & 0xff] ^
00065                        C4[(int)(K[4] >> 24) & 0xff] ^
00066                        C5[(int)(K[3] >> 16) & 0xff] ^
00067                        C6[(int)(K[2] >>  8) & 0xff] ^
00068                        C7[(int)(K[1]      ) & 0xff] ^
00069                        rc[r];
00070                 
00071                 L[1] = C0[(int)(K[1] >> 56)       ] ^
00072                        C1[(int)(K[0] >> 48) & 0xff] ^
00073                        C2[(int)(K[7] >> 40) & 0xff] ^
00074                        C3[(int)(K[6] >> 32) & 0xff] ^
00075                        C4[(int)(K[5] >> 24) & 0xff] ^
00076                        C5[(int)(K[4] >> 16) & 0xff] ^
00077                        C6[(int)(K[3] >>  8) & 0xff] ^
00078                        C7[(int)(K[2]      ) & 0xff];
00079                 
00080                 L[2] = C0[(int)(K[2] >> 56)       ] ^
00081                        C1[(int)(K[1] >> 48) & 0xff] ^
00082                        C2[(int)(K[0] >> 40) & 0xff] ^
00083                        C3[(int)(K[7] >> 32) & 0xff] ^
00084                        C4[(int)(K[6] >> 24) & 0xff] ^
00085                        C5[(int)(K[5] >> 16) & 0xff] ^
00086                        C6[(int)(K[4] >>  8) & 0xff] ^
00087                        C7[(int)(K[3]      ) & 0xff];
00088                 
00089                 L[3] = C0[(int)(K[3] >> 56)       ] ^
00090                        C1[(int)(K[2] >> 48) & 0xff] ^
00091                        C2[(int)(K[1] >> 40) & 0xff] ^
00092                        C3[(int)(K[0] >> 32) & 0xff] ^
00093                        C4[(int)(K[7] >> 24) & 0xff] ^
00094                        C5[(int)(K[6] >> 16) & 0xff] ^
00095                        C6[(int)(K[5] >>  8) & 0xff] ^
00096                        C7[(int)(K[4]      ) & 0xff];
00097                 
00098                 L[4] = C0[(int)(K[4] >> 56)       ] ^
00099                        C1[(int)(K[3] >> 48) & 0xff] ^
00100                        C2[(int)(K[2] >> 40) & 0xff] ^
00101                        C3[(int)(K[1] >> 32) & 0xff] ^
00102                        C4[(int)(K[0] >> 24) & 0xff] ^
00103                        C5[(int)(K[7] >> 16) & 0xff] ^
00104                        C6[(int)(K[6] >>  8) & 0xff] ^
00105                        C7[(int)(K[5]      ) & 0xff];
00106                 
00107                 L[5] = C0[(int)(K[5] >> 56)       ] ^
00108                        C1[(int)(K[4] >> 48) & 0xff] ^
00109                        C2[(int)(K[3] >> 40) & 0xff] ^
00110                        C3[(int)(K[2] >> 32) & 0xff] ^
00111                        C4[(int)(K[1] >> 24) & 0xff] ^
00112                        C5[(int)(K[0] >> 16) & 0xff] ^
00113                        C6[(int)(K[7] >>  8) & 0xff] ^
00114                        C7[(int)(K[6]      ) & 0xff];
00115                 
00116                 L[6] = C0[(int)(K[6] >> 56)       ] ^
00117                        C1[(int)(K[5] >> 48) & 0xff] ^
00118                        C2[(int)(K[4] >> 40) & 0xff] ^
00119                        C3[(int)(K[3] >> 32) & 0xff] ^
00120                        C4[(int)(K[2] >> 24) & 0xff] ^
00121                        C5[(int)(K[1] >> 16) & 0xff] ^
00122                        C6[(int)(K[0] >>  8) & 0xff] ^
00123                        C7[(int)(K[7]      ) & 0xff];
00124                 
00125                 L[7] = C0[(int)(K[7] >> 56)       ] ^
00126                        C1[(int)(K[6] >> 48) & 0xff] ^
00127                        C2[(int)(K[5] >> 40) & 0xff] ^
00128                        C3[(int)(K[4] >> 32) & 0xff] ^
00129                        C4[(int)(K[3] >> 24) & 0xff] ^
00130                        C5[(int)(K[2] >> 16) & 0xff] ^
00131                        C6[(int)(K[1] >>  8) & 0xff] ^
00132                        C7[(int)(K[0]      ) & 0xff];
00133                 
00134                 K[0] = L[0];
00135                 K[1] = L[1];
00136                 K[2] = L[2];
00137                 K[3] = L[3];
00138                 K[4] = L[4];
00139                 K[5] = L[5];
00140                 K[6] = L[6];
00141                 K[7] = L[7];
00142                 
00143                 /* apply the r-th round transformation */
00144                 L[0] = C0[(int)(state[0] >> 56)       ] ^
00145                        C1[(int)(state[7] >> 48) & 0xff] ^
00146                        C2[(int)(state[6] >> 40) & 0xff] ^
00147                        C3[(int)(state[5] >> 32) & 0xff] ^
00148                        C4[(int)(state[4] >> 24) & 0xff] ^
00149                        C5[(int)(state[3] >> 16) & 0xff] ^
00150                        C6[(int)(state[2] >>  8) & 0xff] ^
00151                        C7[(int)(state[1]      ) & 0xff] ^
00152                        K[0];
00153                 
00154                 L[1] = C0[(int)(state[1] >> 56)       ] ^
00155                        C1[(int)(state[0] >> 48) & 0xff] ^
00156                        C2[(int)(state[7] >> 40) & 0xff] ^
00157                        C3[(int)(state[6] >> 32) & 0xff] ^
00158                        C4[(int)(state[5] >> 24) & 0xff] ^
00159                        C5[(int)(state[4] >> 16) & 0xff] ^
00160                        C6[(int)(state[3] >>  8) & 0xff] ^
00161                        C7[(int)(state[2]      ) & 0xff] ^
00162                        K[1];
00163                 
00164                 L[2] = C0[(int)(state[2] >> 56)       ] ^
00165                        C1[(int)(state[1] >> 48) & 0xff] ^
00166                        C2[(int)(state[0] >> 40) & 0xff] ^
00167                        C3[(int)(state[7] >> 32) & 0xff] ^
00168                        C4[(int)(state[6] >> 24) & 0xff] ^
00169                        C5[(int)(state[5] >> 16) & 0xff] ^
00170                        C6[(int)(state[4] >>  8) & 0xff] ^
00171                        C7[(int)(state[3]      ) & 0xff] ^
00172                        K[2];
00173                 
00174                 L[3] = C0[(int)(state[3] >> 56)       ] ^
00175                        C1[(int)(state[2] >> 48) & 0xff] ^
00176                        C2[(int)(state[1] >> 40) & 0xff] ^
00177                        C3[(int)(state[0] >> 32) & 0xff] ^
00178                        C4[(int)(state[7] >> 24) & 0xff] ^
00179                        C5[(int)(state[6] >> 16) & 0xff] ^
00180                        C6[(int)(state[5] >>  8) & 0xff] ^
00181                        C7[(int)(state[4]      ) & 0xff] ^
00182                        K[3];
00183                 
00184                 L[4] = C0[(int)(state[4] >> 56)       ] ^
00185                        C1[(int)(state[3] >> 48) & 0xff] ^
00186                        C2[(int)(state[2] >> 40) & 0xff] ^
00187                        C3[(int)(state[1] >> 32) & 0xff] ^
00188                        C4[(int)(state[0] >> 24) & 0xff] ^
00189                        C5[(int)(state[7] >> 16) & 0xff] ^
00190                        C6[(int)(state[6] >>  8) & 0xff] ^
00191                        C7[(int)(state[5]      ) & 0xff] ^
00192                        K[4];
00193                 
00194                 L[5] = C0[(int)(state[5] >> 56)       ] ^
00195                        C1[(int)(state[4] >> 48) & 0xff] ^
00196                        C2[(int)(state[3] >> 40) & 0xff] ^
00197                        C3[(int)(state[2] >> 32) & 0xff] ^
00198                        C4[(int)(state[1] >> 24) & 0xff] ^
00199                        C5[(int)(state[0] >> 16) & 0xff] ^
00200                        C6[(int)(state[7] >>  8) & 0xff] ^
00201                        C7[(int)(state[6]      ) & 0xff] ^
00202                        K[5];
00203                 
00204                 L[6] = C0[(int)(state[6] >> 56)       ] ^
00205                        C1[(int)(state[5] >> 48) & 0xff] ^
00206                        C2[(int)(state[4] >> 40) & 0xff] ^
00207                        C3[(int)(state[3] >> 32) & 0xff] ^
00208                        C4[(int)(state[2] >> 24) & 0xff] ^
00209                        C5[(int)(state[1] >> 16) & 0xff] ^
00210                        C6[(int)(state[0] >>  8) & 0xff] ^
00211                        C7[(int)(state[7]      ) & 0xff] ^
00212                        K[6];
00213                 
00214                 L[7] = C0[(int)(state[7] >> 56)       ] ^
00215                        C1[(int)(state[6] >> 48) & 0xff] ^
00216                        C2[(int)(state[5] >> 40) & 0xff] ^
00217                        C3[(int)(state[4] >> 32) & 0xff] ^
00218                        C4[(int)(state[3] >> 24) & 0xff] ^
00219                        C5[(int)(state[2] >> 16) & 0xff] ^
00220                        C6[(int)(state[1] >>  8) & 0xff] ^
00221                        C7[(int)(state[0]      ) & 0xff] ^
00222                        K[7];
00223                 
00224                 state[0] = L[0];
00225                 state[1] = L[1];
00226                 state[2] = L[2];
00227                 state[3] = L[3];
00228                 state[4] = L[4];
00229                 state[5] = L[5];
00230                 state[6] = L[6];
00231                 state[7] = L[7];
00232         }
00233         
00234         /* apply the Miyaguchi-Preneel compression function */
00235         context->hash[0] ^= state[0] ^ block[0];
00236         context->hash[1] ^= state[1] ^ block[1];
00237         context->hash[2] ^= state[2] ^ block[2];
00238         context->hash[3] ^= state[3] ^ block[3];
00239         context->hash[4] ^= state[4] ^ block[4];
00240         context->hash[5] ^= state[5] ^ block[5];
00241         context->hash[6] ^= state[6] ^ block[6];
00242         context->hash[7] ^= state[7] ^ block[7];
00243 }

void whirlpool_init ( whirlpool_t *const  context  ) 

initialize whirlpool state context

Parameters:
[in] context whirlpool state context

Definition at line 25 of file whirlpool_init.c.

References whirlpool_t::bits, whirlpool_t::buf, whirlpool_t::hash, whirlpool_t::len, LENGTHBYTES, whirlpool_t::pos, and str_zero().

Referenced by whirlpool_digest().

00026 {
00027         int i;
00028         
00029         str_zero(context->len, LENGTHBYTES);
00030         
00031         context->bits = context->pos = 0;
00032         context->buf[0]  = 0;
00033         
00034         for (i = 0; i < 8; i++)
00035                 context->hash[i] = 0L;
00036 }

void whirlpool_finalize ( whirlpool_t *const  context,
unsigned char *const   result 
)

finalize whirlpool transformation

Parameters:
[in] context whirlpool state context
[out] result string to store digest

Definition at line 25 of file whirlpool_finalize.c.

References whirlpool_t::bits, whirlpool_t::buf, DIGESTBYTES, whirlpool_t::hash, whirlpool_t::len, LENGTHBYTES, whirlpool_t::pos, str_cpyn(), str_zero(), WBLOCKBYTES, and whirlpool_transform().

Referenced by whirlpool_digest().

00026 {
00027         int i;
00028         uint8_t *buf    = context->buf;
00029         uint8_t *len    = context->len;
00030         int bits        = context->bits;
00031         int pos         = context->pos;
00032         uint8_t *digest = result;
00033         
00034         /* append a '1'-bit */
00035         buf[pos] |= 0x80U >> (bits & 7);
00036         pos++; /* all remaining bits on the current uint8_t are set to zero. */
00037         
00038         /* pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits */
00039         if (pos > WBLOCKBYTES - LENGTHBYTES) {
00040                 if (pos < WBLOCKBYTES)
00041                         str_zero(&buf[pos], WBLOCKBYTES - pos);
00042                 
00043                 /* process data block */
00044                 whirlpool_transform(context);
00045                 
00046                 /* reset buffer */
00047                 pos = 0;
00048         }
00049         
00050         if (pos < WBLOCKBYTES - LENGTHBYTES)
00051                 str_zero(&buf[pos], (WBLOCKBYTES - LENGTHBYTES) - pos);
00052         
00053         pos = WBLOCKBYTES - LENGTHBYTES;
00054         
00055         /* append bit length of hashed data */
00056         str_cpyn(&buf[WBLOCKBYTES - LENGTHBYTES], len, LENGTHBYTES);
00057         
00058         /* process data block */
00059         whirlpool_transform(context);
00060         
00061         /* return the completed message digest */
00062         for (i = 0; i < DIGESTBYTES/8; i++) {
00063                 digest[0] = (uint8_t)(context->hash[i] >> 56);
00064                 digest[1] = (uint8_t)(context->hash[i] >> 48);
00065                 digest[2] = (uint8_t)(context->hash[i] >> 40);
00066                 digest[3] = (uint8_t)(context->hash[i] >> 32);
00067                 digest[4] = (uint8_t)(context->hash[i] >> 24);
00068                 digest[5] = (uint8_t)(context->hash[i] >> 16);
00069                 digest[6] = (uint8_t)(context->hash[i] >>  8);
00070                 digest[7] = (uint8_t)(context->hash[i]      );
00071                 digest += 8;
00072         }
00073         
00074         context->bits = bits;
00075         context->pos  = pos;
00076 }

void whirlpool_add ( whirlpool_t *const  context,
const unsigned char *const  src,
unsigned long  bits 
)

add bytes to the transform routine

Parameters:
[in] context whirlpool state context
[in] src source string
[in] bits number of bits in the source string

Definition at line 24 of file whirlpool_add.c.

References whirlpool_t::bits, whirlpool_t::buf, DIGESTBITS, whirlpool_t::len, whirlpool_t::pos, and whirlpool_transform().

Referenced by whirlpool_digest().

00026 {
00027         int i;
00028         uint32_t b, carry;
00029         int srcpos = 0; /* index of leftmost source uint8_t containing data (1 to 8 bits). */
00030         
00031         int gap      = (8 - ((int)srcbits & 7)) & 7; /* space on src[srcpos]. */
00032         int rem      = context->bits & 7; /* occupied bits on buf[pos]. */
00033         
00034         uint8_t *buf = context->buf;
00035         uint8_t *len = context->len;
00036         int bits     = context->bits;
00037         int pos      = context->pos;
00038         
00039         /* tally the length of the added data */
00040         uint64_t value = srcbits;
00041         
00042         for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) {
00043                 carry += len[i] + ((uint32_t)value & 0xff);
00044                 len[i] = (uint8_t)carry;
00045                 carry >>= 8;
00046                 value >>= 8;
00047         }
00048         
00049         /* process data in chunks of 8 bits */
00050         while (srcbits > 8) {
00051                 /* take a byte from the source */
00052                 b = ((src[srcpos] << gap) & 0xff) |
00053                                 ((src[srcpos + 1] & 0xff) >> (8 - gap));
00054                 
00055                 /* process this byte */
00056                 buf[pos++] |= (uint8_t)(b >> rem);
00057                 bits += 8 - rem; /* bits = 8*pos; */
00058                 
00059                 if (bits == DIGESTBITS) {
00060                         /* process data block */
00061                         whirlpool_transform(context);
00062                         
00063                         /* reset buf */
00064                         bits = pos = 0;
00065                 }
00066                 
00067                 buf[pos] = b << (8 - rem);
00068                 bits += rem;
00069                 
00070                 /* proceed to remaining data */
00071                 srcbits -= 8;
00072                 srcpos++;
00073         }
00074         
00075         /* now 0 <= srcbits <= 8;
00076          * furthermore, all data (if any is left) is in src[srcpos].
00077          */
00078         if (srcbits > 0) {
00079                 b = (src[srcpos] << gap) & 0xff; /* bits are left-justified on b. */
00080                 
00081                 /* process the remaining bits */
00082                 buf[pos] |= b >> rem;
00083         }
00084         
00085         else
00086                 b = 0;
00087         
00088         /* all remaining data fits on buf[pos],
00089          * and there still remains some space.
00090          */
00091         if (rem + srcbits < 8) 
00092                 bits += srcbits;
00093         
00094         else {
00095                 /* buf[pos] is full */
00096                 pos++;
00097                 bits += 8 - rem; /* bits = 8*pos; */
00098                 srcbits -= 8 - rem;
00099                 
00100                 /* now 0 <= srcbits < 8;
00101                  * furthermore, all data (if any is left) is in src[srcpos].
00102                  */
00103                 if (bits == DIGESTBITS) {
00104                         /* process data block */
00105                         whirlpool_transform(context);
00106                         
00107                         /* reset buf */
00108                         bits = pos = 0;
00109                 }
00110                 
00111                 buf[pos] = b << (8 - rem);
00112                 bits += (int)srcbits;
00113         }
00114         
00115         context->bits = bits;
00116         context->pos  = pos;
00117 }

char* whirlpool_digest ( const char *  str  ) 

create digest from string

Parameters:
[in] str source string
Returns:
digest string (memory obtained by malloc(3))
Note:
The caller should free obtained memory using free(3)
See also:
malloc(3)

free(3)

Definition at line 24 of file whirlpool_digest.c.

References DIGESTBYTES, stralloc_t::len, stralloc_t::s, str_dupn(), str_len(), stralloc_catf(), stralloc_free(), stralloc_init(), whirlpool_add(), whirlpool_finalize(), and whirlpool_init().

00025 {
00026         whirlpool_t ctx;
00027         stralloc_t sa;
00028         char *buf;
00029         uint8_t digest[DIGESTBYTES];
00030         int i;
00031         
00032         whirlpool_init(&ctx);
00033         whirlpool_add(&ctx, (const unsigned char * const) str, str_len(str)*8);
00034         whirlpool_finalize(&ctx, digest);
00035         
00036         stralloc_init(&sa);
00037         
00038         for (i = 0; i < DIGESTBYTES; i++)
00039                 stralloc_catf(&sa, "%02X", digest[i]);
00040         
00041         buf = str_dupn(sa.s, sa.len);
00042         
00043         stralloc_free(&sa);
00044         
00045         return buf;
00046 }


Generated on Sun Dec 3 17:46:16 2006 for lucid by  doxygen 1.5.1