1//////////////////////////////////////////////////////////////////////////////// 2/// Name: MD4 Class 3/// 4/// Purpose: aMule ed2k link creator 5/// 6/// Last modified by: ThePolish <thepolish@vipmail.ru> 7/// 8/// Copyright (c) 2004-2011 ThePolish ( thepolish@vipmail.ru ) 9/// 10/// Copyright (c) 2004-2011 Marcelo Roberto Jimenez ( phoenix@amule.org ) 11/// 12/// Copyright (c) 2004-2011 Alo Sarv ( madcat_@users.sourceforge.net ) 13/// 14/// Copyright (c) 2002-2011 Michael Buesch 15/// Email: mbuesch@freenet.de 16/// 17/// The algorithm is due to Ron Rivest. This code is based on code 18/// written by Colin Plumb in 1993. 19/// 20/// This code implements the MD4 message-digest algorithm. 21/// 22/// This program is free software; you can redistribute it and/or modify 23/// it under the terms of the GNU General Public License as published by 24/// the Free Software Foundation; either version 2 of the License, or 25/// (at your option) any later version. 26/// 27/// This program is distributed in the hope that it will be useful, 28/// but WITHOUT ANY WARRANTY; without even the implied warranty of 29/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30/// GNU General Public License for more details. 31/// 32/// You should have received a copy of the GNU General Public License 33/// along with this program; if not, write to the 34/// Free Software Foundation, Inc., 35/// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 36//////////////////////////////////////////////////////////////////////////////// 37 38 39#ifdef __BORLANDC__ 40 #pragma hdrstop 41#endif 42 43// For all others, include the necessary headers 44#ifndef WX_PRECOMP 45 #include "wx/wx.h" 46#endif 47 48#include <wx/ffile.h> 49 50#include "md4.h" 51#include "bithelp.h" 52 53 54/// BIG ENDIAN byte reversing 55#if wxBYTE_ORDER == wxBIG_ENDIAN 56// Note: this code is harmless on little-endian machines. 57void MD4::byteReverse(unsigned char *buf, unsigned longs) 58{ 59 uint32_t t; 60 do 61 { 62 t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | 63 ((unsigned) buf[1] << 8 | buf[0]); 64 *(uint32_t *) buf = t; 65 buf += 4; 66 } 67 while (--longs); 68} 69#else 70#define byteReverse(buf, len) do { } while (0) 71#endif 72 73/// Start MD4 accumulation. 74/// Set bit count to 0 and buffer to mysteriousinitialization constants. 75void MD4::MD4Init(struct MD4Context *ctx) 76{ 77 ctx->buf[0] = 0x67452301; 78 ctx->buf[1] = 0xefcdab89; 79 ctx->buf[2] = 0x98badcfe; 80 ctx->buf[3] = 0x10325476; 81 ctx->bits[0] = 0; 82 ctx->bits[1] = 0; 83} 84 85/// Update context to reflect the concatenation of another buffer full of bytes. 86void MD4::MD4Update(struct MD4Context *ctx, unsigned char const *buf, 87 size_t len) 88{ 89 register uint32_t t; 90 91 // Update bitcount 92 t = ctx->bits[0]; 93 if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) 94 ctx->bits[1]++; // Carry from low to high 95 ctx->bits[1] += len >> 29; 96 97 t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data 98 99 // Handle any leading odd-sized chunks 100 if (t) 101 { 102 unsigned char *p = (unsigned char *) ctx->in + t; 103 104 t = 64 - t; 105 if (len < t) 106 { 107 memcpy(p, buf, len); 108 return; 109 } 110 memcpy(p, buf, t); 111 byteReverse(ctx->in, 16); 112 MD4Transform(ctx->buf, (uint32_t *) ctx->in); 113 buf += t; 114 len -= t; 115 } 116 117 // Process data in 64-byte chunks 118 while (len >= 64) 119 { 120 memcpy(ctx->in, buf, 64); 121 byteReverse(ctx->in, 16); 122 MD4Transform(ctx->buf, (uint32_t *) ctx->in); 123 buf += 64; 124 len -= 64; 125 } 126 127 //Handle any remaining bytes of data. 128 memcpy(ctx->in, buf, len); 129} 130 131 132/// Final wrapup - pad to 64-byte boundary with the bit pattern 133/// 1 0* (64-bit count of bits processed, MSB-first) 134void MD4::MD4Final(struct MD4Context *ctx, unsigned char* digest) 135{ 136 unsigned int count; 137 unsigned char *p; 138 139 // Compute number of bytes mod 64 140 count = (ctx->bits[0] >> 3) & 0x3F; 141 142 // Set the first char of padding to 0x80. 143 //This is safe since there is always at least one byte free 144 p = ctx->in + count; 145 *p++ = 0x80; 146 147 // Bytes of padding needed to make 64 bytes 148 count = 64 - 1 - count; 149 150 // Pad out to 56 mod 64 151 if (count < 8) 152 { 153 // Two lots of padding: Pad the first block to 64 bytes 154 memset(p, 0, count); 155 byteReverse(ctx->in, 16); 156 MD4Transform(ctx->buf, (uint32_t *) ctx->in); 157 158 // Now fill the next block with 56 bytes 159 memset(ctx->in, 0, 56); 160 } 161 else 162 { 163 // Pad block to 56 bytes 164 memset(p, 0, count - 8); 165 } 166 byteReverse(ctx->in, 14); 167 168 // Append length in bits and transform 169 ((uint32_t *) ctx->in)[14] = ctx->bits[0]; 170 ((uint32_t *) ctx->in)[15] = ctx->bits[1]; 171 172 MD4Transform(ctx->buf, (uint32_t *) ctx->in); 173 byteReverse((unsigned char *) ctx->buf, 4); 174 175 if (digest!=NULL) 176 { 177 memcpy(digest, ctx->buf, 16); 178 } 179 memset(ctx, 0, sizeof(ctx)); // In case it's sensitive 180} 181 182/// The three core functions 183#define MD4_F(x, y, z) (((x) & (y)) | ((~x) & (z))) 184#define MD4_G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 185#define MD4__H(x, y, z) ((x) ^ (y) ^ (z)) 186 187#define MD4_FF(a, b, c, d, x, s) { \ 188 (a) += MD4_F ((b), (c), (d)) + (x); \ 189 (a) = rol ((a), (s)); \ 190 } 191#define MD4_GG(a, b, c, d, x, s) { \ 192 (a) += MD4_G ((b), (c), (d)) + (x) + (uint32_t)0x5a827999; \ 193 (a) = rol ((a), (s)); \ 194 } 195#define MD4_HH(a, b, c, d, x, s) { \ 196 (a) += MD4__H ((b), (c), (d)) + (x) + (uint32_t)0x6ed9eba1; \ 197 (a) = rol ((a), (s)); \ 198 } 199 200/// The core of the MD4 algorithm 201void MD4::MD4Transform(uint32_t buf[4], uint32_t const in[16]) 202{ 203 register uint32_t a, b, c, d; 204 205 a = buf[0]; 206 b = buf[1]; 207 c = buf[2]; 208 d = buf[3]; 209 210 MD4_FF(a, b, c, d, in[0], 3); /* 1 */ 211 MD4_FF(d, a, b, c, in[1], 7); /* 2 */ 212 MD4_FF(c, d, a, b, in[2], 11); /* 3 */ 213 MD4_FF(b, c, d, a, in[3], 19); /* 4 */ 214 MD4_FF(a, b, c, d, in[4], 3); /* 5 */ 215 MD4_FF(d, a, b, c, in[5], 7); /* 6 */ 216 MD4_FF(c, d, a, b, in[6], 11); /* 7 */ 217 MD4_FF(b, c, d, a, in[7], 19); /* 8 */ 218 MD4_FF(a, b, c, d, in[8], 3); /* 9 */ 219 MD4_FF(d, a, b, c, in[9], 7); /* 10 */ 220 MD4_FF(c, d, a, b, in[10], 11); /* 11 */ 221 MD4_FF(b, c, d, a, in[11], 19); /* 12 */ 222 MD4_FF(a, b, c, d, in[12], 3); /* 13 */ 223 MD4_FF(d, a, b, c, in[13], 7); /* 14 */ 224 MD4_FF(c, d, a, b, in[14], 11); /* 15 */ 225 MD4_FF(b, c, d, a, in[15], 19); /* 16 */ 226 227 MD4_GG(a, b, c, d, in[0], 3); /* 17 */ 228 MD4_GG(d, a, b, c, in[4], 5); /* 18 */ 229 MD4_GG(c, d, a, b, in[8], 9); /* 19 */ 230 MD4_GG(b, c, d, a, in[12], 13); /* 20 */ 231 MD4_GG(a, b, c, d, in[1], 3); /* 21 */ 232 MD4_GG(d, a, b, c, in[5], 5); /* 22 */ 233 MD4_GG(c, d, a, b, in[9], 9); /* 23 */ 234 MD4_GG(b, c, d, a, in[13], 13); /* 24 */ 235 MD4_GG(a, b, c, d, in[2], 3); /* 25 */ 236 MD4_GG(d, a, b, c, in[6], 5); /* 26 */ 237 MD4_GG(c, d, a, b, in[10], 9); /* 27 */ 238 MD4_GG(b, c, d, a, in[14], 13); /* 28 */ 239 MD4_GG(a, b, c, d, in[3], 3); /* 29 */ 240 MD4_GG(d, a, b, c, in[7], 5); /* 30 */ 241 MD4_GG(c, d, a, b, in[11], 9); /* 31 */ 242 MD4_GG(b, c, d, a, in[15], 13); /* 32 */ 243 244 MD4_HH(a, b, c, d, in[0], 3); /* 33 */ 245 MD4_HH(d, a, b, c, in[8], 9); /* 34 */ 246 MD4_HH(c, d, a, b, in[4], 11); /* 35 */ 247 MD4_HH(b, c, d, a, in[12], 15); /* 36 */ 248 MD4_HH(a, b, c, d, in[2], 3); /* 37 */ 249 MD4_HH(d, a, b, c, in[10], 9); /* 38 */ 250 MD4_HH(c, d, a, b, in[6], 11); /* 39 */ 251 MD4_HH(b, c, d, a, in[14], 15); /* 40 */ 252 MD4_HH(a, b, c, d, in[1], 3); /* 41 */ 253 MD4_HH(d, a, b, c, in[9], 9); /* 42 */ 254 MD4_HH(c, d, a, b, in[5], 11); /* 43 */ 255 MD4_HH(b, c, d, a, in[13], 15); /* 44 */ 256 MD4_HH(a, b, c, d, in[3], 3); /* 45 */ 257 MD4_HH(d, a, b, c, in[11], 9); /* 46 */ 258 MD4_HH(c, d, a, b, in[7], 11); /* 47 */ 259 MD4_HH(b, c, d, a, in[15], 15); /* 48 */ 260 261 buf[0] += a; 262 buf[1] += b; 263 buf[2] += c; 264 buf[3] += d; 265} 266 267/// Algorithm verification 268bool MD4::selfTest() 269{ 270 wxString test1(wxEmptyString); 271 wxString test1_md(wxT("31D6CFE0D16AE931B73C59D7E0C089C0")); 272 wxString test2(wxT("a")); 273 wxString test2_md(wxT("BDE52CB31DE33E46245E05FBDBD6FB24")); 274 wxString test3(wxT("abc")); 275 wxString test3_md(wxT("A448017AAF21D8525FC10AE87AA6729D")); 276 wxString test4(wxT("message digest")); 277 wxString test4_md(wxT("D9130A8164549FE818874806E1C7014B")); 278 wxString test5(wxT("abcdefghijklmnopqrstuvwxyz")); 279 wxString test5_md(wxT("D79E1C308AA5BBCDEEA8ED63DF412DA9")); 280 wxString test6(wxT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 281 wxString test6_md(wxT("043F8582F241DB351CE627E153E7F0E4")); 282 wxString test7(wxT("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 283 wxString test7_md(wxT("E33B4DDC9C38F2199C3E7B164FCC0536")); 284 285 MD4 md4; 286 287 if (md4.calcMd4FromString(test1) != test1_md) 288 return false; 289 if (md4.calcMd4FromString(test2) != test2_md) 290 return false; 291 if (md4.calcMd4FromString(test3) != test3_md) 292 return false; 293 if (md4.calcMd4FromString(test4) != test4_md) 294 return false; 295 if (md4.calcMd4FromString(test5) != test5_md) 296 return false; 297 if (md4.calcMd4FromString(test6) != test6_md) 298 return false; 299 if (md4.calcMd4FromString(test7) != test7_md) 300 return false; 301 302 return true; 303} 304 305/// Get Md4 hash from a string 306wxString MD4::calcMd4FromString(const wxString &buf) 307{ 308 MD4Context hdc; 309 unsigned char ret[MD4_HASHLEN_BYTE]; 310 311 MD4Init(&hdc); 312 MD4Update(&hdc, (const unsigned char*)buf.c_str(), buf.length()); 313 MD4Final(&hdc, ret); 314 315 return charToHex((const char*)ret, MD4_HASHLEN_BYTE); 316} 317 318/// Get Md4 hash from a file 319wxString MD4::calcMd4FromFile(const wxString &filename, MD4Hook hook) 320{ 321 unsigned int bufSize; 322 unsigned char ret[MD4_HASHLEN_BYTE]; 323 MD4Context hdc; 324 325 // Open file and let wxFFile destructor close the file 326 // Closing it explicitly may crash on Win32 ... 327 wxFFile file(filename, wxS("rbS")); 328 if (! file.IsOpened()) 329 { 330 return wxEmptyString; 331 } 332 else 333 { 334 bufSize = calcBufSize(file.Length()); 335 char *buf = new char[bufSize]; 336 337 bool keep_going = true; 338 size_t read = 0; 339 size_t totalread = 0; 340 341 bool goAhead = true; 342 343 MD4Init(&hdc); 344 while (!file.Eof() && keep_going) 345 { 346 if (hook) 347 { 348 goAhead = hook( (int)((double)(100.0 * totalread) / file.Length())); 349 } 350 if (goAhead) 351 { 352 read = file.Read(buf, bufSize); 353 MD4Update(&hdc, reinterpret_cast<unsigned char const *>(buf), 354 read ); 355 totalread += read; 356 } 357 else 358 { 359 return (_("Cancelled !")); 360 } 361 } 362 MD4Final(&hdc, ret); 363 364 delete [] buf; 365 366 return charToHex(reinterpret_cast<const char *>(ret), 367 MD4_HASHLEN_BYTE); 368 } 369} 370 371/// Convert hash to hexa string 372wxString MD4::charToHex(const char *buf, size_t len) 373{ 374 size_t i; 375 wxString hexString; 376 377 for (i = 0; i < len; ++i) 378 { 379 hexString += wxString::Format(wxS("%02x"), 0xFF & *(buf + i)); 380 } 381 382 // Reduce memory usage 383 hexString.Shrink(); 384 385 return (hexString); 386} 387 388/// Compute Md4 buffsize 389size_t MD4::calcBufSize(size_t filesize) 390{ 391 if (filesize < 100000) 392 { 393 filesize = 100000; 394 } 395 else if (filesize > 200000) 396 { 397 filesize = 200000; 398 } 399 400 return (filesize); 401} 402// File_checked_for_headers 403