Cryptography Reference
In-Depth Information
{
opad[ i ] ^= key[ i ];
}
update_digest( digest, opad, DIGEST_BLOCK_SIZE );
update_digest( digest, ( unsigned char * ) hash1.hash,
hash1.hash_len * sizeof( int ) );
finalize_digest( digest );
free( hash1.hash );
}
Although update_digest and finalize_digest themselves are practi-
cally impenetrable if you don't already know what they're doing, HMAC is
actually much easier to read now that you've shunted memory management
off to update_digest . Now you simply XOR the key with a block of 0x36s,
update the digest, update it again with the text, fi nalize, XOR the key with
another block of 0x5Cs, update another digest, update it again with the result
of the fi rst digest, and fi nalize that. The only real “magic” in the function
is at the beginning.
memcpy( &hash1, digest, sizeof( digest_ctx ) );
hash1.hash = ( unsigned int * ) malloc(
hash1.hash_len * sizeof( unsigned int ) );
memcpy( hash1.hash, digest->hash, hash1.hash_len * sizeof( unsigned int ) );
Remember that the hmac function can be called with an MD5, SHA-1, or SHA-
256 context. However, the function has no way of knowing which it was called
with. There are multitudes of ways to work around that: You could pass in a
fl ag or add an initializer function to the digest_ctx structure, but the simplest
way is to just memcpy the whole initialized structure at the start of the function.
You know it was initialized prior to invocation; the only thing to be careful of
is that hash was dynamically allocated, so you need to reallocate and recopy it.
If you were doing this in C
, this would be the sort of thing you'd use a copy
constructor for. OK, really, I promise to stop talking C
now.
You can develop a main routine in Listing 4-28 to test this out.
Listing 4-28: “hmac.c” main routine
#ifdef TEST_HMAC
int main( int argc, char *argv[ ] )
{
int i;
digest_ctx digest;
int key_len;
unsigned char *key;
int text_len;
unsigned char *text;
(Continued)
 
Search WWH ::




Custom Search