00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "md5.h"
00025
00026 #define GET_UINT32(n,b,i) \
00027 { \
00028 (n) = ( (uint32) (b)[(i) ] ) \
00029 | ( (uint32) (b)[(i) + 1] << 8 ) \
00030 | ( (uint32) (b)[(i) + 2] << 16 ) \
00031 | ( (uint32) (b)[(i) + 3] << 24 ); \
00032 }
00033
00034 #define PUT_UINT32(n,b,i) \
00035 { \
00036 (b)[(i) ] = (uint8) ( (n) ); \
00037 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
00038 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
00039 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
00040 }
00041
00042 void md5_starts( md5_context *ctx )
00043 {
00044 ctx->total[0] = 0;
00045 ctx->total[1] = 0;
00046
00047 ctx->state[0] = 0x67452301;
00048 ctx->state[1] = 0xEFCDAB89;
00049 ctx->state[2] = 0x98BADCFE;
00050 ctx->state[3] = 0x10325476;
00051 }
00052
00053 void md5_process( md5_context *ctx, uint8 data[64] )
00054 {
00055 uint32 X[16], A, B, C, D;
00056
00057 GET_UINT32( X[0], data, 0 );
00058 GET_UINT32( X[1], data, 4 );
00059 GET_UINT32( X[2], data, 8 );
00060 GET_UINT32( X[3], data, 12 );
00061 GET_UINT32( X[4], data, 16 );
00062 GET_UINT32( X[5], data, 20 );
00063 GET_UINT32( X[6], data, 24 );
00064 GET_UINT32( X[7], data, 28 );
00065 GET_UINT32( X[8], data, 32 );
00066 GET_UINT32( X[9], data, 36 );
00067 GET_UINT32( X[10], data, 40 );
00068 GET_UINT32( X[11], data, 44 );
00069 GET_UINT32( X[12], data, 48 );
00070 GET_UINT32( X[13], data, 52 );
00071 GET_UINT32( X[14], data, 56 );
00072 GET_UINT32( X[15], data, 60 );
00073
00074 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00075
00076 #define P(a,b,c,d,k,s,t) \
00077 { \
00078 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
00079 }
00080
00081 A = ctx->state[0];
00082 B = ctx->state[1];
00083 C = ctx->state[2];
00084 D = ctx->state[3];
00085
00086 #define F(x,y,z) (z ^ (x & (y ^ z)))
00087
00088 P( A, B, C, D, 0, 7, 0xD76AA478 );
00089 P( D, A, B, C, 1, 12, 0xE8C7B756 );
00090 P( C, D, A, B, 2, 17, 0x242070DB );
00091 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
00092 P( A, B, C, D, 4, 7, 0xF57C0FAF );
00093 P( D, A, B, C, 5, 12, 0x4787C62A );
00094 P( C, D, A, B, 6, 17, 0xA8304613 );
00095 P( B, C, D, A, 7, 22, 0xFD469501 );
00096 P( A, B, C, D, 8, 7, 0x698098D8 );
00097 P( D, A, B, C, 9, 12, 0x8B44F7AF );
00098 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00099 P( B, C, D, A, 11, 22, 0x895CD7BE );
00100 P( A, B, C, D, 12, 7, 0x6B901122 );
00101 P( D, A, B, C, 13, 12, 0xFD987193 );
00102 P( C, D, A, B, 14, 17, 0xA679438E );
00103 P( B, C, D, A, 15, 22, 0x49B40821 );
00104
00105 #undef F
00106
00107 #define F(x,y,z) (y ^ (z & (x ^ y)))
00108
00109 P( A, B, C, D, 1, 5, 0xF61E2562 );
00110 P( D, A, B, C, 6, 9, 0xC040B340 );
00111 P( C, D, A, B, 11, 14, 0x265E5A51 );
00112 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
00113 P( A, B, C, D, 5, 5, 0xD62F105D );
00114 P( D, A, B, C, 10, 9, 0x02441453 );
00115 P( C, D, A, B, 15, 14, 0xD8A1E681 );
00116 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
00117 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
00118 P( D, A, B, C, 14, 9, 0xC33707D6 );
00119 P( C, D, A, B, 3, 14, 0xF4D50D87 );
00120 P( B, C, D, A, 8, 20, 0x455A14ED );
00121 P( A, B, C, D, 13, 5, 0xA9E3E905 );
00122 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
00123 P( C, D, A, B, 7, 14, 0x676F02D9 );
00124 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00125
00126 #undef F
00127
00128 #define F(x,y,z) (x ^ y ^ z)
00129
00130 P( A, B, C, D, 5, 4, 0xFFFA3942 );
00131 P( D, A, B, C, 8, 11, 0x8771F681 );
00132 P( C, D, A, B, 11, 16, 0x6D9D6122 );
00133 P( B, C, D, A, 14, 23, 0xFDE5380C );
00134 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
00135 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
00136 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
00137 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00138 P( A, B, C, D, 13, 4, 0x289B7EC6 );
00139 P( D, A, B, C, 0, 11, 0xEAA127FA );
00140 P( C, D, A, B, 3, 16, 0xD4EF3085 );
00141 P( B, C, D, A, 6, 23, 0x04881D05 );
00142 P( A, B, C, D, 9, 4, 0xD9D4D039 );
00143 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00144 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00145 P( B, C, D, A, 2, 23, 0xC4AC5665 );
00146
00147 #undef F
00148
00149 #define F(x,y,z) (y ^ (x | ~z))
00150
00151 P( A, B, C, D, 0, 6, 0xF4292244 );
00152 P( D, A, B, C, 7, 10, 0x432AFF97 );
00153 P( C, D, A, B, 14, 15, 0xAB9423A7 );
00154 P( B, C, D, A, 5, 21, 0xFC93A039 );
00155 P( A, B, C, D, 12, 6, 0x655B59C3 );
00156 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
00157 P( C, D, A, B, 10, 15, 0xFFEFF47D );
00158 P( B, C, D, A, 1, 21, 0x85845DD1 );
00159 P( A, B, C, D, 8, 6, 0x6FA87E4F );
00160 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00161 P( C, D, A, B, 6, 15, 0xA3014314 );
00162 P( B, C, D, A, 13, 21, 0x4E0811A1 );
00163 P( A, B, C, D, 4, 6, 0xF7537E82 );
00164 P( D, A, B, C, 11, 10, 0xBD3AF235 );
00165 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
00166 P( B, C, D, A, 9, 21, 0xEB86D391 );
00167
00168 #undef F
00169
00170 ctx->state[0] += A;
00171 ctx->state[1] += B;
00172 ctx->state[2] += C;
00173 ctx->state[3] += D;
00174 }
00175
00176 void md5_update( md5_context *ctx, uint8 *input, uint32 length )
00177 {
00178 uint32 left, fill;
00179
00180 if( ! length ) return;
00181
00182 left = ctx->total[0] & 0x3F;
00183 fill = 64 - left;
00184
00185 ctx->total[0] += length;
00186 ctx->total[0] &= 0xFFFFFFFF;
00187
00188 if( ctx->total[0] < length )
00189 ctx->total[1]++;
00190
00191 if( left && length >= fill )
00192 {
00193 memcpy( (void *) (ctx->buffer + left),
00194 (void *) input, fill );
00195 md5_process( ctx, ctx->buffer );
00196 length -= fill;
00197 input += fill;
00198 left = 0;
00199 }
00200
00201 while( length >= 64 )
00202 {
00203 md5_process( ctx, input );
00204 length -= 64;
00205 input += 64;
00206 }
00207
00208 if( length )
00209 {
00210 memcpy( (void *) (ctx->buffer + left),
00211 (void *) input, length );
00212 }
00213 }
00214
00215 static uint8 md5_padding[64] =
00216 {
00217 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00221 };
00222
00223 void md5_finish( md5_context *ctx, uint8 digest[16] )
00224 {
00225 uint32 last, padn;
00226 uint32 high, low;
00227 uint8 msglen[8];
00228
00229 high = ( ctx->total[0] >> 29 )
00230 | ( ctx->total[1] << 3 );
00231 low = ( ctx->total[0] << 3 );
00232
00233 PUT_UINT32( low, msglen, 0 );
00234 PUT_UINT32( high, msglen, 4 );
00235
00236 last = ctx->total[0] & 0x3F;
00237 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00238
00239 md5_update( ctx, md5_padding, padn );
00240 md5_update( ctx, msglen, 8 );
00241
00242 PUT_UINT32( ctx->state[0], digest, 0 );
00243 PUT_UINT32( ctx->state[1], digest, 4 );
00244 PUT_UINT32( ctx->state[2], digest, 8 );
00245 PUT_UINT32( ctx->state[3], digest, 12 );
00246 }
00247
00248 void md5(char *result, char *data)
00249 {
00250 unsigned char digest[16];
00251 md5_context ctx;
00252
00253 md5_starts(&ctx);
00254 md5_update(&ctx, (unsigned char *)data, strlen(data));
00255 md5_finish(&ctx, digest);
00256 sprintf(result, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
00257 }
00258
00259 #ifdef TEST
00260
00261 #include <stdlib.h>
00262 #include <stdio.h>
00263
00264
00265
00266
00267
00268 static char *msg[] =
00269 {
00270 "",
00271 "a",
00272 "abc",
00273 "message digest",
00274 "abcdefghijklmnopqrstuvwxyz",
00275 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
00276 "12345678901234567890123456789012345678901234567890123456789012" \
00277 "345678901234567890"
00278 };
00279
00280 static char *val[] =
00281 {
00282 "d41d8cd98f00b204e9800998ecf8427e",
00283 "0cc175b9c0f1b6a831c399e269772661",
00284 "900150983cd24fb0d6963f7d28e17f72",
00285 "f96b697d7cb7938d525a2f31aaf161d0",
00286 "c3fcd3d76192e4007dfb496cca67e13b",
00287 "d174ab98d277d9f5a5611c2c9f419d9f",
00288 "57edf4a22be3c955ac49da2e2107b67a"
00289 };
00290
00291 int main( int argc, char *argv[] )
00292 {
00293 FILE *f;
00294 int i, j;
00295 char output[33];
00296 md5_context ctx;
00297 unsigned char buf[1000];
00298 unsigned char md5sum[16];
00299
00300 if( argc < 2 )
00301 {
00302 printf( "\n MD5 Validation Tests:\n\n" );
00303
00304 for( i = 0; i < 7; i++ )
00305 {
00306 printf( " Test %d ", i + 1 );
00307
00308 md5_starts( &ctx );
00309 md5_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) );
00310 md5_finish( &ctx, md5sum );
00311
00312 for( j = 0; j < 16; j++ )
00313 {
00314 sprintf( output + j * 2, "%02x", md5sum[j] );
00315 }
00316
00317 if( memcmp( output, val[i], 32 ) )
00318 {
00319 printf( "failed!\n" );
00320 return( 1 );
00321 }
00322
00323 printf( "passed.\n" );
00324 }
00325
00326 printf( "\n" );
00327 }
00328 else
00329 {
00330 if( ! ( f = fopen( argv[1], "rb" ) ) )
00331 {
00332 perror( "fopen" );
00333 return( 1 );
00334 }
00335
00336 md5_starts( &ctx );
00337
00338 while( ( i = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00339 {
00340 md5_update( &ctx, buf, i );
00341 }
00342
00343 md5_finish( &ctx, md5sum );
00344
00345 for( j = 0; j < 16; j++ )
00346 {
00347 printf( "%02x", md5sum[j] );
00348 }
00349
00350 printf( " %s\n", argv[1] );
00351 }
00352
00353 return( 0 );
00354 }
00355
00356 #endif