Main Page | Class List | File List | Class Members | File Members

md5.c

Go to the documentation of this file.
00001 /*
00002  *  $Id: md5.c,v 1.7 2006/04/17 22:45:19 ghost666 Exp $
00003  *
00004  *  RFC 1321 compliant MD5 implementation
00005  *
00006  *  Copyright (C) 2001-2003  Christophe Devine
00007  *                2005, 2006 Piotr 'GhosT' Wydrych
00008  *
00009  *  This program is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  This program is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with this program; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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  * those are the standard RFC 1321 test vectors
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

Generated on Fri May 26 08:40:18 2006 for RSSbgr by doxygen 1.3.6