00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "Common/Md5.h"
00015
00016
00017 #define uint8 unsigned char
00018 #define uint32 unsigned long int
00019
00020 struct md5_context
00021 {
00022 uint32 total[2];
00023 uint32 state[4];
00024 uint8 buffer[64];
00025 };
00026
00027 void md5_starts( struct md5_context *ctx );
00028 void md5_update( struct md5_context *ctx, uint8 *input, uint32 length );
00029 void md5_finish( struct md5_context *ctx, uint8 digest[16] );
00030
00031 #define GET_UINT32(n,b,i) \
00032 { \
00033 (n) = (uint32) ((uint8 *) b)[(i)] \
00034 | (((uint32) ((uint8 *) b)[(i)+1]) << 8) \
00035 | (((uint32) ((uint8 *) b)[(i)+2]) << 16) \
00036 | (((uint32) ((uint8 *) b)[(i)+3]) << 24); \
00037 }
00038
00039 #define PUT_UINT32(n,b,i) \
00040 { \
00041 (((uint8 *) b)[(i)] ) = (uint8) (((n) ) & 0xFF); \
00042 (((uint8 *) b)[(i)+1]) = (uint8) (((n) >> 8) & 0xFF); \
00043 (((uint8 *) b)[(i)+2]) = (uint8) (((n) >> 16) & 0xFF); \
00044 (((uint8 *) b)[(i)+3]) = (uint8) (((n) >> 24) & 0xFF); \
00045 }
00046
00047 void md5_starts( struct md5_context *ctx )
00048 {
00049 ctx->total[0] = 0;
00050 ctx->total[1] = 0;
00051 ctx->state[0] = 0x67452301;
00052 ctx->state[1] = 0xEFCDAB89;
00053 ctx->state[2] = 0x98BADCFE;
00054 ctx->state[3] = 0x10325476;
00055 }
00056
00057 void md5_process( struct md5_context *ctx, uint8 data[64] )
00058 {
00059 uint32 A, B, C, D, X[16];
00060
00061 GET_UINT32( X[0], data, 0 );
00062 GET_UINT32( X[1], data, 4 );
00063 GET_UINT32( X[2], data, 8 );
00064 GET_UINT32( X[3], data, 12 );
00065 GET_UINT32( X[4], data, 16 );
00066 GET_UINT32( X[5], data, 20 );
00067 GET_UINT32( X[6], data, 24 );
00068 GET_UINT32( X[7], data, 28 );
00069 GET_UINT32( X[8], data, 32 );
00070 GET_UINT32( X[9], data, 36 );
00071 GET_UINT32( X[10], data, 40 );
00072 GET_UINT32( X[11], data, 44 );
00073 GET_UINT32( X[12], data, 48 );
00074 GET_UINT32( X[13], data, 52 );
00075 GET_UINT32( X[14], data, 56 );
00076 GET_UINT32( X[15], data, 60 );
00077
00078 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00079
00080 #define P(a,b,c,d,k,s,t) \
00081 { \
00082 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
00083 }
00084
00085 A = ctx->state[0];
00086 B = ctx->state[1];
00087 C = ctx->state[2];
00088 D = ctx->state[3];
00089
00090 #define F(x,y,z) (z ^ (x & (y ^ z)))
00091
00092 P( A, B, C, D, 0, 7, 0xD76AA478 );
00093 P( D, A, B, C, 1, 12, 0xE8C7B756 );
00094 P( C, D, A, B, 2, 17, 0x242070DB );
00095 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
00096 P( A, B, C, D, 4, 7, 0xF57C0FAF );
00097 P( D, A, B, C, 5, 12, 0x4787C62A );
00098 P( C, D, A, B, 6, 17, 0xA8304613 );
00099 P( B, C, D, A, 7, 22, 0xFD469501 );
00100 P( A, B, C, D, 8, 7, 0x698098D8 );
00101 P( D, A, B, C, 9, 12, 0x8B44F7AF );
00102 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00103 P( B, C, D, A, 11, 22, 0x895CD7BE );
00104 P( A, B, C, D, 12, 7, 0x6B901122 );
00105 P( D, A, B, C, 13, 12, 0xFD987193 );
00106 P( C, D, A, B, 14, 17, 0xA679438E );
00107 P( B, C, D, A, 15, 22, 0x49B40821 );
00108
00109 #undef F
00110
00111 #define F(x,y,z) (y ^ (z & (x ^ y)))
00112
00113 P( A, B, C, D, 1, 5, 0xF61E2562 );
00114 P( D, A, B, C, 6, 9, 0xC040B340 );
00115 P( C, D, A, B, 11, 14, 0x265E5A51 );
00116 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
00117 P( A, B, C, D, 5, 5, 0xD62F105D );
00118 P( D, A, B, C, 10, 9, 0x02441453 );
00119 P( C, D, A, B, 15, 14, 0xD8A1E681 );
00120 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
00121 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
00122 P( D, A, B, C, 14, 9, 0xC33707D6 );
00123 P( C, D, A, B, 3, 14, 0xF4D50D87 );
00124 P( B, C, D, A, 8, 20, 0x455A14ED );
00125 P( A, B, C, D, 13, 5, 0xA9E3E905 );
00126 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
00127 P( C, D, A, B, 7, 14, 0x676F02D9 );
00128 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00129
00130 #undef F
00131
00132 #define F(x,y,z) (x ^ y ^ z)
00133
00134 P( A, B, C, D, 5, 4, 0xFFFA3942 );
00135 P( D, A, B, C, 8, 11, 0x8771F681 );
00136 P( C, D, A, B, 11, 16, 0x6D9D6122 );
00137 P( B, C, D, A, 14, 23, 0xFDE5380C );
00138 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
00139 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
00140 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
00141 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00142 P( A, B, C, D, 13, 4, 0x289B7EC6 );
00143 P( D, A, B, C, 0, 11, 0xEAA127FA );
00144 P( C, D, A, B, 3, 16, 0xD4EF3085 );
00145 P( B, C, D, A, 6, 23, 0x04881D05 );
00146 P( A, B, C, D, 9, 4, 0xD9D4D039 );
00147 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00148 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00149 P( B, C, D, A, 2, 23, 0xC4AC5665 );
00150
00151 #undef F
00152
00153 #define F(x,y,z) (y ^ (x | ~z))
00154
00155 P( A, B, C, D, 0, 6, 0xF4292244 );
00156 P( D, A, B, C, 7, 10, 0x432AFF97 );
00157 P( C, D, A, B, 14, 15, 0xAB9423A7 );
00158 P( B, C, D, A, 5, 21, 0xFC93A039 );
00159 P( A, B, C, D, 12, 6, 0x655B59C3 );
00160 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
00161 P( C, D, A, B, 10, 15, 0xFFEFF47D );
00162 P( B, C, D, A, 1, 21, 0x85845DD1 );
00163 P( A, B, C, D, 8, 6, 0x6FA87E4F );
00164 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00165 P( C, D, A, B, 6, 15, 0xA3014314 );
00166 P( B, C, D, A, 13, 21, 0x4E0811A1 );
00167 P( A, B, C, D, 4, 6, 0xF7537E82 );
00168 P( D, A, B, C, 11, 10, 0xBD3AF235 );
00169 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
00170 P( B, C, D, A, 9, 21, 0xEB86D391 );
00171
00172 #undef F
00173
00174 ctx->state[0] += A;
00175 ctx->state[1] += B;
00176 ctx->state[2] += C;
00177 ctx->state[3] += D;
00178 }
00179
00180 void md5_update( struct md5_context *ctx, uint8 *input, uint32 length )
00181 {
00182 uint32 left, fill;
00183
00184 if( ! length ) return;
00185
00186 left = ( ctx->total[0] >> 3 ) & 0x3F;
00187 fill = 64 - left;
00188
00189 ctx->total[0] += length << 3;
00190 ctx->total[1] += length >> 29;
00191
00192 ctx->total[0] &= 0xFFFFFFFF;
00193 ctx->total[1] += ctx->total[0] < length << 3;
00194
00195 if( left && length >= fill )
00196 {
00197 memcpy( (void *) (ctx->buffer + left), (void *) input, fill );
00198 md5_process( ctx, ctx->buffer );
00199 length -= fill;
00200 input += fill;
00201 left = 0;
00202 }
00203
00204 while( length >= 64 )
00205 {
00206 md5_process( ctx, input );
00207 length -= 64;
00208 input += 64;
00209 }
00210
00211 if( length )
00212 {
00213 memcpy( (void *) (ctx->buffer + left), (void *) input, length );
00214 }
00215 }
00216
00217 static uint8 md5_padding[64] =
00218 {
00219 0x80, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00223 };
00224
00225 void md5_finish( struct md5_context *ctx, uint8 digest[16] )
00226 {
00227 uint32 last, padn;
00228 uint8 msglen[8];
00229
00230 PUT_UINT32( ctx->total[0], msglen, 0 );
00231 PUT_UINT32( ctx->total[1], msglen, 4 );
00232
00233 last = ( ctx->total[0] >> 3 ) & 0x3F;
00234 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00235
00236 md5_update( ctx, md5_padding, padn );
00237 md5_update( ctx, msglen, 8 );
00238
00239 PUT_UINT32( ctx->state[0], digest, 0 );
00240 PUT_UINT32( ctx->state[1], digest, 4 );
00241 PUT_UINT32( ctx->state[2], digest, 8 );
00242 PUT_UINT32( ctx->state[3], digest, 12 );
00243 }
00244
00245
00246 KStr md5( KStr& sString )
00247 {
00248 md5_context ctx;
00249 char output[33];
00250 unsigned char md5sum[16];
00251
00252 md5_starts( &ctx );
00253 md5_update( &ctx, (uint8 *)sString.GetpString(), sString.GetLength() );
00254 md5_finish( &ctx, md5sum );
00255
00256 for( int j = 0; j < 16; j++ )
00257 {
00258 sprintf( output + j * 2, "%02x", md5sum[j] );
00259 }
00260
00261 return KStr( output );
00262 }