Cryptography Reference
In-Depth Information
while ( ( bytes_read = read( f, buf, 400 ) ) > 0 )
{
update_digest( &context, buf, bytes_read );
}
finalize_digest( &context );
if ( bytes_read == -1 )
{
fprintf( stderr, “Error reading file '%s': “, filename );
perror( “” );
}
close( f );
{
unsigned char *hash = ( unsigned char * ) context.hash;
for ( i = 0; i < ( context.hash_len * 4 ); i )
{
printf( “%.02x”, hash[ i ] );
}
printf( “\n” );
}
free( context.hash );
Pay special attention to how this works:
1. A new MD5 digest structure is initialized by calling new_md5_digest from
Listing 4-24.
2. The fi le is opened and read, 400 bytes at a time.
3. These 400-byte blocks are passed into update_digest from Listing 4-22,
which is responsible for computing the hash “so far,” on top of the hash
that's already been computed.
4. Before completing, finalize_digest from Listing 4-23 is called to append
the total length of the fi le as required by the digest structure and the fi nal
hash is computed.
5. At this point, the context parameter can no longer be reused; if you wanted
to compute another hash, you'd have to initialize another context.
The benefi t of this approach is that rather than reading the whole fi le into
memory and calling md5_hash from Listing 4-7 (which would produce the exact
same result), the whole fi le doesn't need to be stored in memory all at once.
The hash is converted to a char array at the end so that it prints out in canonical
order — remember that MD5 is little-endian; however, it's customary to display
a hash value in big-endian order anyway.
Search WWH ::




Custom Search