Cryptography Reference
In-Depth Information
This single function is now responsible for computing both MD5 and SHA-1
hashes. To compute an MD5 hash, call
unsigned int hash[ 4 ];
memcpy( hash, md5_initial_hash, 4 * sizeof( unsigned int ) );
digest_hash( argv[ 2 ], strlen( argv[ 2 ] ), hash, 4, md5_block_operate,
md5_finalize );
and to compute an SHA-1 hash, call
unsigned int hash[ 5 ];
memcpy( hash, sha1_initial_hash, 5 * sizeof( unsigned int ) );
digest_hash( argv[ 2 ], strlen( argv[ 2 ] ), hash, 5, sha1_block_operate,
sha1_finalize );
If you were paying close attention, you may have also noticed that the fi rst
four integers of the sha1_initial_hash array are the same as the fi rst four
integers of the md5_initial_hash array. Technically you could even use one
initial_hash array and share it between the two operations.
There's one fi nal problem you run into when trying to use digest as in Listing 4-13.
The output of md5 is given in big-endian format, whereas the output of SHA-1
is given in little-endian format. In and of itself, this isn't really a problem, but
you want to be able to treat digest as a black box and not care which algorithm
it encloses. As a result, you need to decide which format you want to follow.
Arbitrarily, pick the MD5 format, and reverse the SHA-1 computations at each
stage. The changes to sha.c are detailed in Listing 4-14.
Listing 4-14: “sha.c” SHA-1 in little-endian format
unsigned int sha1_initial_hash[ ] = {
0x01234567,
0x89abcdef,
0xfedcba98,
0x76543210,
0xf0e1d2c3
};
...
void sha1_block_operate( const unsigned char *block, unsigned int hash[ 5 ] )
{
...
W[ t ] = ( W[ t ] << 1 ) | ( ( W[ t ] & 0x80000000 ) >> 31 );
}
}
hash[ 0 ] = ntohl( hash[ 0 ] );
hash[ 1 ] = ntohl( hash[ 1 ] );
hash[ 2 ] = ntohl( hash[ 2 ] );
hash[ 3 ] = ntohl( hash[ 3 ] );
hash[ 4 ] = ntohl( hash[ 4 ] );
 
Search WWH ::




Custom Search