md5.cpp

00001 /*
00002   Copyright (c) 2006-2008 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 /*
00014   This class is based on a C implementation of the MD5 algorithm written by
00015   L. Peter Deutsch.
00016   The full notice as shipped with the original verson is included below.
00017 */
00018 
00019 /*
00020   Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
00021 
00022   This software is provided 'as-is', without any express or implied
00023   warranty.  In no event will the authors be held liable for any damages
00024   arising from the use of this software.
00025 
00026   Permission is granted to anyone to use this software for any purpose,
00027   including commercial applications, and to alter it and redistribute it
00028   freely, subject to the following restrictions:
00029 
00030   1. The origin of this software must not be misrepresented; you must not
00031      claim that you wrote the original software. If you use this software
00032      in a product, an acknowledgment in the product documentation would be
00033      appreciated but is not required.
00034   2. Altered source versions must be plainly marked as such, and must not be
00035      misrepresented as being the original software.
00036   3. This notice may not be removed or altered from any source distribution.
00037 
00038   L. Peter Deutsch
00039   ghost@aladdin.com
00040 
00041  */
00042 /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
00043 /*
00044   Independent implementation of MD5 (RFC 1321).
00045 
00046   This code implements the MD5 Algorithm defined in RFC 1321, whose
00047   text is available at
00048         http://www.ietf.org/rfc/rfc1321.txt
00049   The code is derived from the text of the RFC, including the test suite
00050   (section A.5) but excluding the rest of Appendix A.  It does not include
00051   any code or documentation that is identified in the RFC as being
00052   copyrighted.
00053 
00054   The original and principal author of md5.c is L. Peter Deutsch
00055   <ghost@aladdin.com>.  Other authors are noted in the change history
00056   that follows (in reverse chronological order):
00057 
00058   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
00059         either statically or dynamically; added missing #include <string.h>
00060         in library.
00061   2002-03-11 lpd Corrected argument list for main(), and added int return
00062         type, in test program and T value program.
00063   2002-02-21 lpd Added missing #include <stdio.h> in test program.
00064   2000-07-03 lpd Patched to eliminate warnings about "constant is
00065         unsigned in ANSI C, signed in traditional"; made test program
00066         self-checking.
00067   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
00068   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
00069   1999-05-03 lpd Original version.
00070  */
00071 
00072 #include "md5.h"
00073 
00074 #include <string.h>
00075 
00076 namespace gloox
00077 {
00078 // #undef BYTE_ORDER    /* 1 = big-endian, -1 = little-endian, 0 = unknown */
00079 // #ifdef ARCH_IS_BIG_ENDIAN
00080 // #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
00081 // #else
00082 // #  define BYTE_ORDER 0
00083 // #endif
00084 
00085 #undef BYTE_ORDER
00086 #define BYTE_ORDER 0
00087 
00088 #define T_MASK ((unsigned int)~0)
00089 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00090 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00091 #define T3    0x242070db
00092 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00093 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00094 #define T6    0x4787c62a
00095 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00096 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00097 #define T9    0x698098d8
00098 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00099 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00100 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00101 #define T13    0x6b901122
00102 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00103 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00104 #define T16    0x49b40821
00105 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00106 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00107 #define T19    0x265e5a51
00108 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00109 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00110 #define T22    0x02441453
00111 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00112 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00113 #define T25    0x21e1cde6
00114 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00115 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00116 #define T28    0x455a14ed
00117 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00118 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00119 #define T31    0x676f02d9
00120 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00121 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00122 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00123 #define T35    0x6d9d6122
00124 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00125 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00126 #define T38    0x4bdecfa9
00127 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00128 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00129 #define T41    0x289b7ec6
00130 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00131 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00132 #define T44    0x04881d05
00133 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00134 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00135 #define T47    0x1fa27cf8
00136 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00137 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00138 #define T50    0x432aff97
00139 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00140 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00141 #define T53    0x655b59c3
00142 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00143 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00144 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00145 #define T57    0x6fa87e4f
00146 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00147 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00148 #define T60    0x4e0811a1
00149 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00150 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00151 #define T63    0x2ad7d2bb
00152 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00153 
00154 
00155   const unsigned char MD5::pad[64] =
00156   {
00157     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00158     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00159     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00160     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00161   };
00162 
00163   MD5::MD5()
00164     : m_finished( false )
00165   {
00166     init();
00167   }
00168 
00169   MD5::~MD5()
00170   {
00171   }
00172 
00173   void MD5::process( const unsigned char *data /*[64]*/ )
00174   {
00175     unsigned int a = m_state.abcd[0];
00176     unsigned int b = m_state.abcd[1];
00177     unsigned int c = m_state.abcd[2];
00178     unsigned int d = m_state.abcd[3];
00179     unsigned int t;
00180 #if BYTE_ORDER > 0
00181     /* Define storage only for big-endian CPUs. */
00182     unsigned int X[16];
00183 #else
00184     /* Define storage for little-endian or both types of CPUs. */
00185     unsigned int xbuf[16];
00186     const unsigned int *X;
00187 #endif
00188 
00189     {
00190 #if BYTE_ORDER == 0
00191       /*
00192       * Determine dynamically whether this is a big-endian or
00193       * little-endian machine, since we can use a more efficient
00194       * algorithm on the latter.
00195       */
00196       static const int w = 1;
00197 
00198       if( *((const unsigned char *)&w) ) /* dynamic little-endian */
00199 #endif
00200 #if BYTE_ORDER <= 0             /* little-endian */
00201       {
00202         /*
00203         * On little-endian machines, we can process properly aligned
00204         * data without copying it.
00205         */
00206         if( !((data - (const unsigned char*)0) & 3) )
00207         {
00208           /* data are properly aligned */
00209           X = (const unsigned int*)data;
00210         }
00211         else
00212         {
00213           /* not aligned */
00214           memcpy( xbuf, data, 64 );
00215           X = xbuf;
00216         }
00217       }
00218 #endif
00219 #if BYTE_ORDER == 0
00220       else // dynamic big-endian
00221 #endif
00222 #if BYTE_ORDER >= 0 // big-endian
00223       {
00224         /*
00225         * On big-endian machines, we must arrange the bytes in the
00226         * right order.
00227         */
00228         const unsigned char *xp = data;
00229         int i;
00230 
00231 #  if BYTE_ORDER == 0
00232         X = xbuf; // (dynamic only)
00233 #  else
00234 #    define xbuf X  /* (static only) */
00235 #  endif
00236         for( i = 0; i < 16; ++i, xp += 4 )
00237           xbuf[i] = xp[0] + ( xp[1] << 8 ) + ( xp[2] << 16 ) + ( xp[3] << 24 );
00238       }
00239 #endif
00240     }
00241 
00242 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00243 
00244     /* Round 1. */
00245     /* Let [abcd k s i] denote the operation
00246        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
00247 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00248 #define SET(a, b, c, d, k, s, Ti)\
00249   t = a + F(b,c,d) + X[k] + Ti;\
00250   a = ROTATE_LEFT(t, s) + b
00251     /* Do the following 16 operations. */
00252     SET(a, b, c, d,  0,  7,  T1);
00253     SET(d, a, b, c,  1, 12,  T2);
00254     SET(c, d, a, b,  2, 17,  T3);
00255     SET(b, c, d, a,  3, 22,  T4);
00256     SET(a, b, c, d,  4,  7,  T5);
00257     SET(d, a, b, c,  5, 12,  T6);
00258     SET(c, d, a, b,  6, 17,  T7);
00259     SET(b, c, d, a,  7, 22,  T8);
00260     SET(a, b, c, d,  8,  7,  T9);
00261     SET(d, a, b, c,  9, 12, T10);
00262     SET(c, d, a, b, 10, 17, T11);
00263     SET(b, c, d, a, 11, 22, T12);
00264     SET(a, b, c, d, 12,  7, T13);
00265     SET(d, a, b, c, 13, 12, T14);
00266     SET(c, d, a, b, 14, 17, T15);
00267     SET(b, c, d, a, 15, 22, T16);
00268 #undef SET
00269 
00270      /* Round 2. */
00271      /* Let [abcd k s i] denote the operation
00272           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
00273 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00274 #define SET(a, b, c, d, k, s, Ti)\
00275   t = a + G(b,c,d) + X[k] + Ti;\
00276   a = ROTATE_LEFT(t, s) + b
00277      /* Do the following 16 operations. */
00278     SET(a, b, c, d,  1,  5, T17);
00279     SET(d, a, b, c,  6,  9, T18);
00280     SET(c, d, a, b, 11, 14, T19);
00281     SET(b, c, d, a,  0, 20, T20);
00282     SET(a, b, c, d,  5,  5, T21);
00283     SET(d, a, b, c, 10,  9, T22);
00284     SET(c, d, a, b, 15, 14, T23);
00285     SET(b, c, d, a,  4, 20, T24);
00286     SET(a, b, c, d,  9,  5, T25);
00287     SET(d, a, b, c, 14,  9, T26);
00288     SET(c, d, a, b,  3, 14, T27);
00289     SET(b, c, d, a,  8, 20, T28);
00290     SET(a, b, c, d, 13,  5, T29);
00291     SET(d, a, b, c,  2,  9, T30);
00292     SET(c, d, a, b,  7, 14, T31);
00293     SET(b, c, d, a, 12, 20, T32);
00294 #undef SET
00295 
00296      /* Round 3. */
00297      /* Let [abcd k s t] denote the operation
00298           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
00299 #define H(x, y, z) ((x) ^ (y) ^ (z))
00300 #define SET(a, b, c, d, k, s, Ti)\
00301   t = a + H(b,c,d) + X[k] + Ti;\
00302   a = ROTATE_LEFT(t, s) + b
00303      /* Do the following 16 operations. */
00304     SET(a, b, c, d,  5,  4, T33);
00305     SET(d, a, b, c,  8, 11, T34);
00306     SET(c, d, a, b, 11, 16, T35);
00307     SET(b, c, d, a, 14, 23, T36);
00308     SET(a, b, c, d,  1,  4, T37);
00309     SET(d, a, b, c,  4, 11, T38);
00310     SET(c, d, a, b,  7, 16, T39);
00311     SET(b, c, d, a, 10, 23, T40);
00312     SET(a, b, c, d, 13,  4, T41);
00313     SET(d, a, b, c,  0, 11, T42);
00314     SET(c, d, a, b,  3, 16, T43);
00315     SET(b, c, d, a,  6, 23, T44);
00316     SET(a, b, c, d,  9,  4, T45);
00317     SET(d, a, b, c, 12, 11, T46);
00318     SET(c, d, a, b, 15, 16, T47);
00319     SET(b, c, d, a,  2, 23, T48);
00320 #undef SET
00321 
00322      /* Round 4. */
00323      /* Let [abcd k s t] denote the operation
00324           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
00325 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00326 #define SET(a, b, c, d, k, s, Ti)\
00327   t = a + I(b,c,d) + X[k] + Ti;\
00328   a = ROTATE_LEFT(t, s) + b
00329      /* Do the following 16 operations. */
00330     SET(a, b, c, d,  0,  6, T49);
00331     SET(d, a, b, c,  7, 10, T50);
00332     SET(c, d, a, b, 14, 15, T51);
00333     SET(b, c, d, a,  5, 21, T52);
00334     SET(a, b, c, d, 12,  6, T53);
00335     SET(d, a, b, c,  3, 10, T54);
00336     SET(c, d, a, b, 10, 15, T55);
00337     SET(b, c, d, a,  1, 21, T56);
00338     SET(a, b, c, d,  8,  6, T57);
00339     SET(d, a, b, c, 15, 10, T58);
00340     SET(c, d, a, b,  6, 15, T59);
00341     SET(b, c, d, a, 13, 21, T60);
00342     SET(a, b, c, d,  4,  6, T61);
00343     SET(d, a, b, c, 11, 10, T62);
00344     SET(c, d, a, b,  2, 15, T63);
00345     SET(b, c, d, a,  9, 21, T64);
00346 #undef SET
00347 
00348      /* Then perform the following additions. (That is increment each
00349         of the four registers by the value it had before this block
00350         was started.) */
00351     m_state.abcd[0] += a;
00352     m_state.abcd[1] += b;
00353     m_state.abcd[2] += c;
00354     m_state.abcd[3] += d;
00355   }
00356 
00357   void MD5::init()
00358   {
00359     m_finished = false;
00360     m_state.count[0] = 0;
00361     m_state.count[1] = 0;
00362     m_state.abcd[0] = 0x67452301;
00363     m_state.abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00364     m_state.abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00365     m_state.abcd[3] = 0x10325476;
00366   }
00367 
00368   void MD5::feed( const std::string& data )
00369   {
00370     feed( (const unsigned char*)data.c_str(), data.length() );
00371   }
00372 
00373   void MD5::feed( const unsigned char *data, int bytes )
00374   {
00375     const unsigned char *p = data;
00376     int left = bytes;
00377     int offset = ( m_state.count[0] >> 3 ) & 63;
00378     unsigned int nbits = (unsigned int)( bytes << 3 );
00379 
00380     if( bytes <= 0 )
00381       return;
00382 
00383     /* Update the message length. */
00384     m_state.count[1] += bytes >> 29;
00385     m_state.count[0] += nbits;
00386     if( m_state.count[0] < nbits )
00387       m_state.count[1]++;
00388 
00389     /* Process an initial partial block. */
00390     if( offset )
00391     {
00392       int copy = ( offset + bytes > 64 ? 64 - offset : bytes );
00393 
00394       memcpy( m_state.buf + offset, p, copy );
00395       if( offset + copy < 64 )
00396         return;
00397       p += copy;
00398       left -= copy;
00399       process( m_state.buf );
00400     }
00401 
00402     /* Process full blocks. */
00403     for( ; left >= 64; p += 64, left -= 64 )
00404       process( p );
00405 
00406     /* Process a final partial block. */
00407     if( left )
00408       memcpy( m_state.buf, p, left );
00409   }
00410 
00411   void MD5::finalize()
00412   {
00413     if( m_finished )
00414       return;
00415 
00416     unsigned char data[8];
00417     int i;
00418 
00419     /* Save the length before padding. */
00420     for( i = 0; i < 8; ++i )
00421       data[i] = (unsigned char)( m_state.count[i >> 2] >> ( ( i & 3 ) << 3 ) );
00422 
00423     /* Pad to 56 bytes mod 64. */
00424     feed( pad, ( ( 55 - ( m_state.count[0] >> 3 ) ) & 63 ) + 1 );
00425 
00426     /* Append the length. */
00427     feed( data, 8 );
00428 
00429     m_finished = true;
00430   }
00431 
00432   const std::string MD5::hex()
00433   {
00434     if( !m_finished )
00435       finalize();
00436 
00437     char buf[33];
00438 
00439     for( int i = 0; i < 16; ++i )
00440       sprintf( buf + i * 2, "%02x", (unsigned char)( m_state.abcd[i >> 2] >> ( ( i & 3 ) << 3 ) ) );
00441 
00442     return buf;
00443   }
00444 
00445   const std::string MD5::binary()
00446   {
00447     if( !m_finished )
00448       finalize();
00449 
00450     unsigned char digest[16];
00451     for( int i = 0; i < 16; ++i )
00452       digest[i] = (unsigned char)( m_state.abcd[i >> 2] >> ( ( i & 3 ) << 3 ) );
00453 
00454     return std::string( (char*)digest, 16 );
00455   }
00456 
00457   void MD5::reset()
00458   {
00459     init();
00460   }
00461 
00462 }

Generated on Fri Oct 10 15:26:11 2008 for gloox by  doxygen 1.5.6