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