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