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 45 of file whirlpool.h.

Referenced by whirlpool_digest(), and whirlpool_finalize().

#define DIGESTBITS   (8*DIGESTBYTES)

number of bits in the digest

Definition at line 48 of file whirlpool.h.

Referenced by whirlpool_add().

#define WBLOCKBYTES   64

number of bytes in the input buffer

Definition at line 52 of file whirlpool.h.

Referenced by whirlpool_finalize().

#define WBLOCKBITS   (8*WBLOCKBYTES)

number of bits in the input buffer

Definition at line 55 of file whirlpool.h.

#define LENGTHBYTES   32

number of hashed bytes

Definition at line 59 of file whirlpool.h.

Referenced by whirlpool_finalize(), and whirlpool_init().

#define LENGTHBITS   (8*LENGTHBYTES)

number of hashed bits

Definition at line 62 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 26 of file whirlpool_transform.c.

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

Referenced by whirlpool_add(), and whirlpool_finalize().

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

void whirlpool_init ( whirlpool_t *const  context  ) 

initialize whirlpool state context

Parameters:
[in] context whirlpool state context

Definition at line 24 of file whirlpool_init.c.

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

Referenced by whirlpool_digest().

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

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 24 of file whirlpool_finalize.c.

References whirlpool_t::bits, whirlpool_t::buf, DIGESTBYTES, whirlpool_t::hash, whirlpool_t::len, LENGTHBYTES, mem_cpy(), mem_set(), whirlpool_t::pos, 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                         mem_set(&buf[pos], 0, 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                 mem_set(&buf[pos], 0, (WBLOCKBYTES - LENGTHBYTES) - pos);
00052 
00053         pos = WBLOCKBYTES - LENGTHBYTES;
00054 
00055         /* append bit length of hashed data */
00056         mem_cpy(&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 23 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().

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

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 26 of file whirlpool_digest.c.

References DIGESTBYTES, str_len(), stralloc_catf(), stralloc_finalize(), stralloc_free(), stralloc_init(), whirlpool_add(), whirlpool_finalize(), and whirlpool_init().

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


Generated on Tue Jun 19 20:38:45 2007 for lucid by  doxygen 1.5.2