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 <cstdio>
00075 #include <string.h>
00076 
00077 namespace gloox
00078 {
00079 // #undef BYTE_ORDER    /* 1 = big-endian, -1 = little-endian, 0 = unknown */
00080 // #ifdef ARCH_IS_BIG_ENDIAN
00081 // #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
00082 // #else
00083 // #  define BYTE_ORDER 0
00084 // #endif
00085 
00086 #undef BYTE_ORDER
00087 #define BYTE_ORDER 0
00088 
00089 #define T_MASK ((unsigned int)~0)
00090 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00091 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00092 #define T3    0x242070db
00093 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00094 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00095 #define T6    0x4787c62a
00096 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00097 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00098 #define T9    0x698098d8
00099 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00100 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00101 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00102 #define T13    0x6b901122
00103 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00104 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00105 #define T16    0x49b40821
00106 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00107 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00108 #define T19    0x265e5a51
00109 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00110 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00111 #define T22    0x02441453
00112 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00113 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00114 #define T25    0x21e1cde6
00115 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00116 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00117 #define T28    0x455a14ed
00118 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00119 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00120 #define T31    0x676f02d9
00121 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00122 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00123 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00124 #define T35    0x6d9d6122
00125 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00126 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00127 #define T38    0x4bdecfa9
00128 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00129 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00130 #define T41    0x289b7ec6
00131 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00132 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00133 #define T44    0x04881d05
00134 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00135 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00136 #define T47    0x1fa27cf8
00137 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00138 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00139 #define T50    0x432aff97
00140 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00141 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00142 #define T53    0x655b59c3
00143 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00144 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00145 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00146 #define T57    0x6fa87e4f
00147 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00148 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00149 #define T60    0x4e0811a1
00150 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00151 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00152 #define T63    0x2ad7d2bb
00153 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00154 
00155 
00156   const unsigned char MD5::pad[64] =
00157   {
00158     0x80, 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     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00162   };
00163 
00164   MD5::MD5()
00165     : m_finished( false )
00166   {
00167     init();
00168   }
00169 
00170   MD5::~MD5()
00171   {
00172   }
00173 
00174   void MD5::process( const unsigned char *data /*[64]*/ )
00175   {
00176     unsigned int a = m_state.abcd[0];
00177     unsigned int b = m_state.abcd[1];
00178     unsigned int c = m_state.abcd[2];
00179     unsigned int d = m_state.abcd[3];
00180     unsigned int t;
00181 #if BYTE_ORDER > 0
00182     /* Define storage only for big-endian CPUs. */
00183     unsigned int X[16];
00184 #else
00185     /* Define storage for little-endian or both types of CPUs. */
00186     unsigned int xbuf[16];
00187     const unsigned int *X;
00188 #endif
00189 
00190     {
00191 #if BYTE_ORDER == 0
00192       /*
00193       * Determine dynamically whether this is a big-endian or
00194       * little-endian machine, since we can use a more efficient
00195       * algorithm on the latter.
00196       */
00197       static const int w = 1;
00198 
00199       if( *((const unsigned char *)&w) ) /* dynamic little-endian */
00200 #endif
00201 #if BYTE_ORDER <= 0             /* little-endian */
00202       {
00203         /*
00204         * On little-endian machines, we can process properly aligned
00205         * data without copying it.
00206         */
00207         if( !((data - (const unsigned char*)0) & 3) )
00208         {
00209           /* data are properly aligned */
00210           X = (const unsigned int*)data;
00211         }
00212         else
00213         {
00214           /* not aligned */
00215           memcpy( xbuf, data, 64 );
00216           X = xbuf;
00217         }
00218       }
00219 #endif
00220 #if BYTE_ORDER == 0
00221       else // dynamic big-endian
00222 #endif
00223 #if BYTE_ORDER >= 0 // big-endian
00224       {
00225         /*
00226         * On big-endian machines, we must arrange the bytes in the
00227         * right order.
00228         */
00229         const unsigned char *xp = data;
00230         int i;
00231 
00232 #  if BYTE_ORDER == 0
00233         X = xbuf; // (dynamic only)
00234 #  else
00235 #    define xbuf X  /* (static only) */
00236 #  endif
00237         for( i = 0; i < 16; ++i, xp += 4 )
00238           xbuf[i] = xp[0] + ( xp[1] << 8 ) + ( xp[2] << 16 ) + ( xp[3] << 24 );
00239       }
00240 #endif
00241     }
00242 
00243 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00244 
00245     /* Round 1. */
00246     /* Let [abcd k s i] denote the operation
00247        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
00248 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00249 #define SET(a, b, c, d, k, s, Ti)\
00250   t = a + F(b,c,d) + X[k] + Ti;\
00251   a = ROTATE_LEFT(t, s) + b
00252     /* Do the following 16 operations. */
00253     SET(a, b, c, d,  0,  7,  T1);
00254     SET(d, a, b, c,  1, 12,  T2);
00255     SET(c, d, a, b,  2, 17,  T3);
00256     SET(b, c, d, a,  3, 22,  T4);
00257     SET(a, b, c, d,  4,  7,  T5);
00258     SET(d, a, b, c,  5, 12,  T6);
00259     SET(c, d, a, b,  6, 17,  T7);
00260     SET(b, c, d, a,  7, 22,  T8);
00261     SET(a, b, c, d,  8,  7,  T9);
00262     SET(d, a, b, c,  9, 12, T10);
00263     SET(c, d, a, b, 10, 17, T11);
00264     SET(b, c, d, a, 11, 22, T12);
00265     SET(a, b, c, d, 12,  7, T13);
00266     SET(d, a, b, c, 13, 12, T14);
00267     SET(c, d, a, b, 14, 17, T15);
00268     SET(b, c, d, a, 15, 22, T16);
00269 #undef SET
00270 
00271      /* Round 2. */
00272      /* Let [abcd k s i] denote the operation
00273           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
00274 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00275 #define SET(a, b, c, d, k, s, Ti)\
00276   t = a + G(b,c,d) + X[k] + Ti;\
00277   a = ROTATE_LEFT(t, s) + b
00278      /* Do the following 16 operations. */
00279     SET(a, b, c, d,  1,  5, T17);
00280     SET(d, a, b, c,  6,  9, T18);
00281     SET(c, d, a, b, 11, 14, T19);
00282     SET(b, c, d, a,  0, 20, T20);
00283     SET(a, b, c, d,  5,  5, T21);
00284     SET(d, a, b, c, 10,  9, T22);
00285     SET(c, d, a, b, 15, 14, T23);
00286     SET(b, c, d, a,  4, 20, T24);
00287     SET(a, b, c, d,  9,  5, T25);
00288     SET(d, a, b, c, 14,  9, T26);
00289     SET(c, d, a, b,  3, 14, T27);
00290     SET(b, c, d, a,  8, 20, T28);
00291     SET(a, b, c, d, 13,  5, T29);
00292     SET(d, a, b, c,  2,  9, T30);
00293     SET(c, d, a, b,  7, 14, T31);
00294     SET(b, c, d, a, 12, 20, T32);
00295 #undef SET
00296 
00297      /* Round 3. */
00298      /* Let [abcd k s t] denote the operation
00299           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
00300 #define H(x, y, z) ((x) ^ (y) ^ (z))
00301 #define SET(a, b, c, d, k, s, Ti)\
00302   t = a + H(b,c,d) + X[k] + Ti;\
00303   a = ROTATE_LEFT(t, s) + b
00304      /* Do the following 16 operations. */
00305     SET(a, b, c, d,  5,  4, T33);
00306     SET(d, a, b, c,  8, 11, T34);
00307     SET(c, d, a, b, 11, 16, T35);
00308     SET(b, c, d, a, 14, 23, T36);
00309     SET(a, b, c, d,  1,  4, T37);
00310     SET(d, a, b, c,  4, 11, T38);
00311     SET(c, d, a, b,  7, 16, T39);
00312     SET(b, c, d, a, 10, 23, T40);
00313     SET(a, b, c, d, 13,  4, T41);
00314     SET(d, a, b, c,  0, 11, T42);
00315     SET(c, d, a, b,  3, 16, T43);
00316     SET(b, c, d, a,  6, 23, T44);
00317     SET(a, b, c, d,  9,  4, T45);
00318     SET(d, a, b, c, 12, 11, T46);
00319     SET(c, d, a, b, 15, 16, T47);
00320     SET(b, c, d, a,  2, 23, T48);
00321 #undef SET
00322 
00323      /* Round 4. */
00324      /* Let [abcd k s t] denote the operation
00325           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
00326 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00327 #define SET(a, b, c, d, k, s, Ti)\
00328   t = a + I(b,c,d) + X[k] + Ti;\
00329   a = ROTATE_LEFT(t, s) + b
00330      /* Do the following 16 operations. */
00331     SET(a, b, c, d,  0,  6, T49);
00332     SET(d, a, b, c,  7, 10, T50);
00333     SET(c, d, a, b, 14, 15, T51);
00334     SET(b, c, d, a,  5, 21, T52);
00335     SET(a, b, c, d, 12,  6, T53);
00336     SET(d, a, b, c,  3, 10, T54);
00337     SET(c, d, a, b, 10, 15, T55);
00338     SET(b, c, d, a,  1, 21, T56);
00339     SET(a, b, c, d,  8,  6, T57);
00340     SET(d, a, b, c, 15, 10, T58);
00341     SET(c, d, a, b,  6, 15, T59);
00342     SET(b, c, d, a, 13, 21, T60);
00343     SET(a, b, c, d,  4,  6, T61);
00344     SET(d, a, b, c, 11, 10, T62);
00345     SET(c, d, a, b,  2, 15, T63);
00346     SET(b, c, d, a,  9, 21, T64);
00347 #undef SET
00348 
00349      /* Then perform the following additions. (That is increment each
00350         of the four registers by the value it had before this block
00351         was started.) */
00352     m_state.abcd[0] += a;
00353     m_state.abcd[1] += b;
00354     m_state.abcd[2] += c;
00355     m_state.abcd[3] += d;
00356   }
00357 
00358   void MD5::init()
00359   {
00360     m_finished = false;
00361     m_state.count[0] = 0;
00362     m_state.count[1] = 0;
00363     m_state.abcd[0] = 0x67452301;
00364     m_state.abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00365     m_state.abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00366     m_state.abcd[3] = 0x10325476;
00367   }
00368 
00369   void MD5::feed( const std::string& data )
00370   {
00371     feed( (const unsigned char*)data.c_str(), data.length() );
00372   }
00373 
00374   void MD5::feed( const unsigned char *data, int bytes )
00375   {
00376     const unsigned char *p = data;
00377     int left = bytes;
00378     int offset = ( m_state.count[0] >> 3 ) & 63;
00379     unsigned int nbits = (unsigned int)( bytes << 3 );
00380 
00381     if( bytes <= 0 )
00382       return;
00383 
00384     /* Update the message length. */
00385     m_state.count[1] += bytes >> 29;
00386     m_state.count[0] += nbits;
00387     if( m_state.count[0] < nbits )
00388       m_state.count[1]++;
00389 
00390     /* Process an initial partial block. */
00391     if( offset )
00392     {
00393       int copy = ( offset + bytes > 64 ? 64 - offset : bytes );
00394 
00395       memcpy( m_state.buf + offset, p, copy );
00396       if( offset + copy < 64 )
00397         return;
00398       p += copy;
00399       left -= copy;
00400       process( m_state.buf );
00401     }
00402 
00403     /* Process full blocks. */
00404     for( ; left >= 64; p += 64, left -= 64 )
00405       process( p );
00406 
00407     /* Process a final partial block. */
00408     if( left )
00409       memcpy( m_state.buf, p, left );
00410   }
00411 
00412   void MD5::finalize()
00413   {
00414     if( m_finished )
00415       return;
00416 
00417     unsigned char data[8];
00418     int i;
00419 
00420     /* Save the length before padding. */
00421     for( i = 0; i < 8; ++i )
00422       data[i] = (unsigned char)( m_state.count[i >> 2] >> ( ( i & 3 ) << 3 ) );
00423 
00424     /* Pad to 56 bytes mod 64. */
00425     feed( pad, ( ( 55 - ( m_state.count[0] >> 3 ) ) & 63 ) + 1 );
00426 
00427     /* Append the length. */
00428     feed( data, 8 );
00429 
00430     m_finished = true;
00431   }
00432 
00433   const std::string MD5::hex()
00434   {
00435     if( !m_finished )
00436       finalize();
00437 
00438     char buf[33];
00439 
00440     for( int i = 0; i < 16; ++i )
00441       sprintf( buf + i * 2, "%02x", (unsigned char)( m_state.abcd[i >> 2] >> ( ( i & 3 ) << 3 ) ) );
00442 
00443     return buf;
00444   }
00445 
00446   const std::string MD5::binary()
00447   {
00448     if( !m_finished )
00449       finalize();
00450 
00451     unsigned char digest[16];
00452     for( int i = 0; i < 16; ++i )
00453       digest[i] = (unsigned char)( m_state.abcd[i >> 2] >> ( ( i & 3 ) << 3 ) );
00454 
00455     return std::string( (char*)digest, 16 );
00456   }
00457 
00458   void MD5::reset()
00459   {
00460     init();
00461   }
00462 
00463 }

Generated on Mon Dec 7 13:28:19 2009 for gloox by  doxygen 1.6.1