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 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) |
#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) |
void whirlpool_transform | ( | whirlpool_t *const | context | ) |
internal transform routine
[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
[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
[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
[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
[in] | str | source string |
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 }