gloox
1.0
|
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 }