md5.C

Go to the documentation of this file.
00001 /*!@file Util/md5.C general md5 (128-bit) message-digest implementation */
00002 
00003 // This code is from http://www.cr0.net:8040/code/crypto/md5/, also
00004 // under the GPL (see original copyright notice below)
00005 
00006 /*
00007  *  RFC 1321 compliant MD5 implementation
00008  *
00009  *  Copyright (C) 2001-2003  Christophe Devine
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  */
00025 
00026 //
00027 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00028 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Util/md5.C $
00029 // $Id: md5.C 5368 2005-08-22 21:51:52Z rjpeters $
00030 //
00031 
00032 #ifndef UTIL_MD5_C_DEFINED
00033 #define UTIL_MD5_C_DEFINED
00034 
00035 #include "Util/md5.H"
00036 
00037 #include <string.h>
00038 
00039 typedef byte uint8;
00040 
00041 #define GET_UINT32(n,b,i)                       \
00042 {                                               \
00043     (n) = ( (uint32) (b)[(i)    ]       )       \
00044         | ( (uint32) (b)[(i) + 1] <<  8 )       \
00045         | ( (uint32) (b)[(i) + 2] << 16 )       \
00046         | ( (uint32) (b)[(i) + 3] << 24 );      \
00047 }
00048 
00049 #define PUT_UINT32(n,b,i)                       \
00050 {                                               \
00051     (b)[(i)    ] = (uint8) ( (n)       );       \
00052     (b)[(i) + 1] = (uint8) ( (n) >>  8 );       \
00053     (b)[(i) + 2] = (uint8) ( (n) >> 16 );       \
00054     (b)[(i) + 3] = (uint8) ( (n) >> 24 );       \
00055 }
00056 
00057 void md5_starts( md5_context *ctx )
00058 {
00059     ctx->total[0] = 0;
00060     ctx->total[1] = 0;
00061 
00062     ctx->state[0] = 0x67452301;
00063     ctx->state[1] = 0xEFCDAB89;
00064     ctx->state[2] = 0x98BADCFE;
00065     ctx->state[3] = 0x10325476;
00066 }
00067 
00068 void md5_process( md5_context *ctx, const uint8 data[64] )
00069 {
00070     uint32 X[16], A, B, C, D;
00071 
00072     GET_UINT32( X[0],  data,  0 );
00073     GET_UINT32( X[1],  data,  4 );
00074     GET_UINT32( X[2],  data,  8 );
00075     GET_UINT32( X[3],  data, 12 );
00076     GET_UINT32( X[4],  data, 16 );
00077     GET_UINT32( X[5],  data, 20 );
00078     GET_UINT32( X[6],  data, 24 );
00079     GET_UINT32( X[7],  data, 28 );
00080     GET_UINT32( X[8],  data, 32 );
00081     GET_UINT32( X[9],  data, 36 );
00082     GET_UINT32( X[10], data, 40 );
00083     GET_UINT32( X[11], data, 44 );
00084     GET_UINT32( X[12], data, 48 );
00085     GET_UINT32( X[13], data, 52 );
00086     GET_UINT32( X[14], data, 56 );
00087     GET_UINT32( X[15], data, 60 );
00088 
00089 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00090 
00091 #define P(a,b,c,d,k,s,t)                                \
00092 {                                                       \
00093     a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
00094 }
00095 
00096     A = ctx->state[0];
00097     B = ctx->state[1];
00098     C = ctx->state[2];
00099     D = ctx->state[3];
00100 
00101 #define F(x,y,z) (z ^ (x & (y ^ z)))
00102 
00103     P( A, B, C, D,  0,  7, 0xD76AA478 );
00104     P( D, A, B, C,  1, 12, 0xE8C7B756 );
00105     P( C, D, A, B,  2, 17, 0x242070DB );
00106     P( B, C, D, A,  3, 22, 0xC1BDCEEE );
00107     P( A, B, C, D,  4,  7, 0xF57C0FAF );
00108     P( D, A, B, C,  5, 12, 0x4787C62A );
00109     P( C, D, A, B,  6, 17, 0xA8304613 );
00110     P( B, C, D, A,  7, 22, 0xFD469501 );
00111     P( A, B, C, D,  8,  7, 0x698098D8 );
00112     P( D, A, B, C,  9, 12, 0x8B44F7AF );
00113     P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00114     P( B, C, D, A, 11, 22, 0x895CD7BE );
00115     P( A, B, C, D, 12,  7, 0x6B901122 );
00116     P( D, A, B, C, 13, 12, 0xFD987193 );
00117     P( C, D, A, B, 14, 17, 0xA679438E );
00118     P( B, C, D, A, 15, 22, 0x49B40821 );
00119 
00120 #undef F
00121 
00122 #define F(x,y,z) (y ^ (z & (x ^ y)))
00123 
00124     P( A, B, C, D,  1,  5, 0xF61E2562 );
00125     P( D, A, B, C,  6,  9, 0xC040B340 );
00126     P( C, D, A, B, 11, 14, 0x265E5A51 );
00127     P( B, C, D, A,  0, 20, 0xE9B6C7AA );
00128     P( A, B, C, D,  5,  5, 0xD62F105D );
00129     P( D, A, B, C, 10,  9, 0x02441453 );
00130     P( C, D, A, B, 15, 14, 0xD8A1E681 );
00131     P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
00132     P( A, B, C, D,  9,  5, 0x21E1CDE6 );
00133     P( D, A, B, C, 14,  9, 0xC33707D6 );
00134     P( C, D, A, B,  3, 14, 0xF4D50D87 );
00135     P( B, C, D, A,  8, 20, 0x455A14ED );
00136     P( A, B, C, D, 13,  5, 0xA9E3E905 );
00137     P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
00138     P( C, D, A, B,  7, 14, 0x676F02D9 );
00139     P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00140 
00141 #undef F
00142 
00143 #define F(x,y,z) (x ^ y ^ z)
00144 
00145     P( A, B, C, D,  5,  4, 0xFFFA3942 );
00146     P( D, A, B, C,  8, 11, 0x8771F681 );
00147     P( C, D, A, B, 11, 16, 0x6D9D6122 );
00148     P( B, C, D, A, 14, 23, 0xFDE5380C );
00149     P( A, B, C, D,  1,  4, 0xA4BEEA44 );
00150     P( D, A, B, C,  4, 11, 0x4BDECFA9 );
00151     P( C, D, A, B,  7, 16, 0xF6BB4B60 );
00152     P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00153     P( A, B, C, D, 13,  4, 0x289B7EC6 );
00154     P( D, A, B, C,  0, 11, 0xEAA127FA );
00155     P( C, D, A, B,  3, 16, 0xD4EF3085 );
00156     P( B, C, D, A,  6, 23, 0x04881D05 );
00157     P( A, B, C, D,  9,  4, 0xD9D4D039 );
00158     P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00159     P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00160     P( B, C, D, A,  2, 23, 0xC4AC5665 );
00161 
00162 #undef F
00163 
00164 #define F(x,y,z) (y ^ (x | ~z))
00165 
00166     P( A, B, C, D,  0,  6, 0xF4292244 );
00167     P( D, A, B, C,  7, 10, 0x432AFF97 );
00168     P( C, D, A, B, 14, 15, 0xAB9423A7 );
00169     P( B, C, D, A,  5, 21, 0xFC93A039 );
00170     P( A, B, C, D, 12,  6, 0x655B59C3 );
00171     P( D, A, B, C,  3, 10, 0x8F0CCC92 );
00172     P( C, D, A, B, 10, 15, 0xFFEFF47D );
00173     P( B, C, D, A,  1, 21, 0x85845DD1 );
00174     P( A, B, C, D,  8,  6, 0x6FA87E4F );
00175     P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00176     P( C, D, A, B,  6, 15, 0xA3014314 );
00177     P( B, C, D, A, 13, 21, 0x4E0811A1 );
00178     P( A, B, C, D,  4,  6, 0xF7537E82 );
00179     P( D, A, B, C, 11, 10, 0xBD3AF235 );
00180     P( C, D, A, B,  2, 15, 0x2AD7D2BB );
00181     P( B, C, D, A,  9, 21, 0xEB86D391 );
00182 
00183 #undef F
00184 
00185     ctx->state[0] += A;
00186     ctx->state[1] += B;
00187     ctx->state[2] += C;
00188     ctx->state[3] += D;
00189 }
00190 
00191 void md5_update( md5_context *ctx, const uint8 *input, uint32 length )
00192 {
00193     uint32 left, fill;
00194 
00195     if( ! length ) return;
00196 
00197     left = ctx->total[0] & 0x3F;
00198     fill = 64 - left;
00199 
00200     ctx->total[0] += length;
00201     ctx->total[0] &= 0xFFFFFFFF;
00202 
00203     if( ctx->total[0] < length )
00204         ctx->total[1]++;
00205 
00206     if( left && length >= fill )
00207     {
00208         memcpy( (void *) (ctx->buffer + left),
00209                 (void *) input, fill );
00210         md5_process( ctx, ctx->buffer );
00211         length -= fill;
00212         input  += fill;
00213         left = 0;
00214     }
00215 
00216     while( length >= 64 )
00217     {
00218         md5_process( ctx, input );
00219         length -= 64;
00220         input  += 64;
00221     }
00222 
00223     if( length )
00224     {
00225         memcpy( (void *) (ctx->buffer + left),
00226                 (void *) input, length );
00227     }
00228 }
00229 
00230 static uint8 md5_padding[64] =
00231 {
00232  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00233     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00234     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00235     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00236 };
00237 
00238 void md5_finish( md5_context *ctx, uint8 digest[16] )
00239 {
00240     uint32 last, padn;
00241     uint32 high, low;
00242     uint8 msglen[8];
00243 
00244     high = ( ctx->total[0] >> 29 )
00245          | ( ctx->total[1] <<  3 );
00246     low  = ( ctx->total[0] <<  3 );
00247 
00248     PUT_UINT32( low,  msglen, 0 );
00249     PUT_UINT32( high, msglen, 4 );
00250 
00251     last = ctx->total[0] & 0x3F;
00252     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00253 
00254     md5_update( ctx, md5_padding, padn );
00255     md5_update( ctx, msglen, 8 );
00256 
00257     PUT_UINT32( ctx->state[0], digest,  0 );
00258     PUT_UINT32( ctx->state[1], digest,  4 );
00259     PUT_UINT32( ctx->state[2], digest,  8 );
00260     PUT_UINT32( ctx->state[3], digest, 12 );
00261 }
00262 
00263 // ######################################################################
00264 /* So things look consistent in everyone's emacs... */
00265 /* Local Variables: */
00266 /* indent-tabs-mode: nil */
00267 /* End: */
00268 
00269 #endif // UTIL_MD5_C_DEFINED
Generated on Sun May 8 08:06:58 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3