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