📄 shs.c
字号:
subRound( E, A, B, C, D, f4, K4, expand(shsInfo->data, 76) );
subRound( D, E, A, B, C, f4, K4, expand(shsInfo->data, 77) );
subRound( C, D, E, A, B, f4, K4, expand(shsInfo->data, 78) );
subRound( B, C, D, E, A, f4, K4, expand(shsInfo->data, 79) );
/* Build message digest */
shsInfo->digest[ 0 ] += A;
shsInfo->digest[ 1 ] += B;
shsInfo->digest[ 2 ] += C;
shsInfo->digest[ 3 ] += D;
shsInfo->digest[ 4 ] += E;
}
#endif /* !ASM */
/* When run on a little-endian CPU we need to perform byte reversal on an
array of longwords. It is possible to make the code endianness-
independant by fiddling around with data at the byte level, but this
makes for very slow code, so we rely on the user to sort out endianness
at compile time */
#ifdef LITTLE_ENDIAN
static void byteReverse( WORD32 *buffer, unsigned byteCount )
{
WORD32 value;
byteCount /= sizeof(WORD32);
while ( byteCount-- ) {
value = *buffer;
value = ( value & 0xFF00FF00L ) >> 8 | \
( value & 0x00FF00FFL ) << 8;
*buffer++ = value << 16 | value >> 16 ;
}
}
#else /* !LITTLE_ENDIAN */
#define byteReverse(buf, count) /* nothing */
#endif /* !LITTLE_ENDIAN */
/* Update SHS for a block of data. */
void shsUpdate( SHS_INFO *shsInfo, BYTE const *buffer, unsigned count )
{
WORD32 t;
/* Update bitcount */
#ifdef HAVE64
t = ( (WORD32)shsInfo->count >> 3) & 0x3f;
shsInfo->count += (WORD64)count << 3;
#else
t = shsInfo->countLo;
if ( ( shsInfo->countLo = t + ( (WORD32)count << 3) ) < t )
shsInfo->countHi++; /* Carry from low to high */
shsInfo->countHi += count >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
#endif
/* Handle any leading odd-sized chunks */
if ( t ) {
BYTE *p = (BYTE *)shsInfo->data + t;
t = 64-t;
if (count < t) {
memcpy( p, buffer, count );
return;
}
memcpy( p, buffer, t );
byteReverse( shsInfo->data, SHS_BLOCKSIZE );
shsTransform( shsInfo );
buffer += t;
count -= t;
}
/* Process data in SHS_BLOCKSIZE chunks */
while( count >= SHS_BLOCKSIZE ) {
memcpy( shsInfo->data, buffer, SHS_BLOCKSIZE );
byteReverse( shsInfo->data, SHS_BLOCKSIZE );
shsTransform( shsInfo );
buffer += SHS_BLOCKSIZE;
count -= SHS_BLOCKSIZE;
}
/* Handle any remaining bytes of data. */
memcpy( shsInfo->data, buffer, count );
}
/* Final wrapup - pad to 64-byte boundary with the bit pattern
1 0* (64-bit count of bits processed, MSB-first) */
void shsFinal( SHS_INFO *shsInfo )
{
int count;
BYTE *p;
/* Compute number of bytes mod 64 */
#ifdef HAVE64
count = (int)shsInfo->count;
#else
count = (int)shsInfo->countLo;
#endif
count = ( count >> 3 ) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = (BYTE *)shsInfo->data + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = SHS_BLOCKSIZE - 1 - count;
/* Pad out to 56 mod 64 */
if( count < 8 ) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset( p, 0, count );
byteReverse( shsInfo->data, SHS_BLOCKSIZE );
shsTransform( shsInfo );
/* Now fill the next block with 56 bytes */
memset( shsInfo->data, 0, SHS_BLOCKSIZE - 8 );
} else {
/* Pad block to 56 bytes */
memset( p, 0, count - 8 );
}
byteReverse( shsInfo->data, SHS_BLOCKSIZE-8 );
/* Append length in bits and transform */
#if HAVE64
shsInfo->data[ 14 ] = (WORD32)( shsInfo->count >> 32 );
shsInfo->data[ 15 ] = (WORD32)shsInfo->count;
#else
shsInfo->data[ 14 ] = shsInfo->countHi;
shsInfo->data[ 15 ] = shsInfo->countLo;
#endif
shsTransform( shsInfo );
}
/* ----------------------------- SHS Test code --------------------------- */
/* Size of buffer for SHS speed test data */
#define TEST_BLOCK_SIZE ( SHS_DIGESTSIZE * 100 )
/* Number of bytes of test data to process */
#define TEST_BYTES 10000000L
#define TEST_BLOCKS ( TEST_BYTES / TEST_BLOCK_SIZE )
void main( void )
{
SHS_INFO shsInfo;
BYTE data[ TEST_BLOCK_SIZE ];
time_t endTime, startTime;
long i;
/* Test output data (this is the only test data given in the SHS
document, but chances are if it works for this it'll work for
anything) */
shsInit( &shsInfo );
shsUpdate( &shsInfo, (BYTE *)"abc", 3 );
shsFinal( &shsInfo );
if( shsInfo.digest[ 0 ] != 0x0164B8A9L || \
shsInfo.digest[ 1 ] != 0x14CD2A5EL || \
shsInfo.digest[ 2 ] != 0x74C4F7FFL || \
shsInfo.digest[ 3 ] != 0x082C4D97L || \
shsInfo.digest[ 4 ] != 0xF1EDF880L )
{
puts( "Error in SHS implementation: Test 1 failed" );
exit( -1 );
}
puts("Test 1 passed");
shsInit( &shsInfo );
shsUpdate( &shsInfo, (BYTE *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 );
shsFinal( &shsInfo );
if( shsInfo.digest[ 0 ] != 0xD2516EE1L || \
shsInfo.digest[ 1 ] != 0xACFA5BAFL || \
shsInfo.digest[ 2 ] != 0x33DFC1C4L || \
shsInfo.digest[ 3 ] != 0x71E43844L || \
shsInfo.digest[ 4 ] != 0x9EF134C8L )
{
puts( "Error in SHS implementation: Test 2 failed" );
exit( -1 );
}
puts("Test 2 passed");
shsInit( &shsInfo );
for( i = 0; i < 15625; i++ )
shsUpdate( &shsInfo, (BYTE *)"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 );
shsFinal( &shsInfo );
if( shsInfo.digest[ 0 ] != 0x3232AFFAL || \
shsInfo.digest[ 1 ] != 0x48628A26L || \
shsInfo.digest[ 2 ] != 0x653B5AAAL || \
shsInfo.digest[ 3 ] != 0x44541FD9L || \
shsInfo.digest[ 4 ] != 0x0D690603L )
{
puts( "Error in SHS implementation: Test 3 failed" );
exit( -1 );
}
puts("Test 3 passed");
shsInit( &shsInfo );
for( i = 0; i < 40000; i++ )
shsUpdate( &shsInfo, (BYTE *)"aaaaaaaaaaaaaaaaaaaaaaaaa", 25 );
shsFinal( &shsInfo );
if( shsInfo.digest[ 0 ] != 0x3232AFFAL || \
shsInfo.digest[ 1 ] != 0x48628A26L || \
shsInfo.digest[ 2 ] != 0x653B5AAAL || \
shsInfo.digest[ 3 ] != 0x44541FD9L || \
shsInfo.digest[ 4 ] != 0x0D690603L )
{
puts( "Error in SHS implementation: Test 4 failed" );
exit( -1 );
}
puts("Test 4 passed");
shsInit( &shsInfo );
for( i = 0; i < 8000; i++ )
shsUpdate( &shsInfo, (BYTE *)"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 125 );
shsFinal( &shsInfo );
if( shsInfo.digest[ 0 ] != 0x3232AFFAL || \
shsInfo.digest[ 1 ] != 0x48628A26L || \
shsInfo.digest[ 2 ] != 0x653B5AAAL || \
shsInfo.digest[ 3 ] != 0x44541FD9L || \
shsInfo.digest[ 4 ] != 0x0D690603L )
{
puts( "Error in SHS implementation: Test 5 failed" );
exit( -1 );
}
puts("Test 5 passed");
/* Now perform time trial, generating MD for 10MB of data. First,
initialize the test data */
memset( data, 0, TEST_BLOCK_SIZE );
/* Get start time */
printf( "SHS time trial. Processing %ld characters...\n", TEST_BYTES );
time( &startTime );
/* Calculate SHS message digest in TEST_BLOCK_SIZE byte blocks */
shsInit( &shsInfo );
for( i = TEST_BLOCKS; i > 0; i-- )
shsUpdate( &shsInfo, data, TEST_BLOCK_SIZE );
shsFinal( &shsInfo );
/* Get finish time and time difference */
time( &endTime );
printf( "Seconds to process test input: %ld\n", endTime - startTime );
printf( "Characters processed per second: %ld\n", TEST_BYTES / ( endTime - startTime ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -