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