1 ////////////////////////////////////////////////////////////////////////////////
4 /// Purpose: aMule ed2k link creator
6 /// Last modified by: ThePolish <thepolish@vipmail.ru>
8 /// Copyright (c) 2004-2008 ThePolish ( thepolish@vipmail.ru )
10 /// Copyright (c) 2004-2008 Marcelo Roberto Jimenez ( phoenix@amule.org )
12 /// Copyright (c) 2004-2008 Alo Sarv ( madcat_@users.sourceforge.net )
14 /// Copyright (c) 2002-2008 Michael Buesch
15 /// Email: mbuesch@freenet.de
17 /// The algorithm is due to Ron Rivest. This code is based on code
18 /// written by Colin Plumb in 1993.
20 /// This code implements the MD4 message-digest algorithm.
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.
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.
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 ////////////////////////////////////////////////////////////////////////////////
43 // For all others, include the necessary headers
54 /// BIG ENDIAN byte reversing
55 #if wxBYTE_ORDER == wxBIG_ENDIAN
56 // Note: this code is harmless on little-endian machines.
57 void MD4::byteReverse(unsigned char *buf
, unsigned longs
)
62 t
= (uint32_t) ((unsigned) buf
[3] << 8 | buf
[2]) << 16 |
63 ((unsigned) buf
[1] << 8 | buf
[0]);
64 *(uint32_t *) buf
= t
;
70 #define byteReverse(buf, len) do { } while (0)
73 /// Start MD4 accumulation.
74 /// Set bit count to 0 and buffer to mysteriousinitialization constants.
75 void MD4::MD4Init(struct MD4Context
*ctx
)
77 ctx
->buf
[0] = 0x67452301;
78 ctx
->buf
[1] = 0xefcdab89;
79 ctx
->buf
[2] = 0x98badcfe;
80 ctx
->buf
[3] = 0x10325476;
85 /// Update context to reflect the concatenation of another buffer full of bytes.
86 void MD4::MD4Update(struct MD4Context
*ctx
, unsigned char const *buf
,
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;
97 t
= (t
>> 3) & 0x3f; // Bytes already in shsInfo->data
99 // Handle any leading odd-sized chunks
102 unsigned char *p
= (unsigned char *) ctx
->in
+ t
;
111 byteReverse(ctx
->in
, 16);
112 MD4Transform(ctx
->buf
, (uint32_t *) ctx
->in
);
117 // Process data in 64-byte chunks
120 memcpy(ctx
->in
, buf
, 64);
121 byteReverse(ctx
->in
, 16);
122 MD4Transform(ctx
->buf
, (uint32_t *) ctx
->in
);
127 //Handle any remaining bytes of data.
128 memcpy(ctx
->in
, buf
, len
);
132 /// Final wrapup - pad to 64-byte boundary with the bit pattern
133 /// 1 0* (64-bit count of bits processed, MSB-first)
134 void MD4::MD4Final(struct MD4Context
*ctx
, unsigned char* digest
)
139 // Compute number of bytes mod 64
140 count
= (ctx
->bits
[0] >> 3) & 0x3F;
142 // Set the first char of padding to 0x80.
143 //This is safe since there is always at least one byte free
147 // Bytes of padding needed to make 64 bytes
148 count
= 64 - 1 - count
;
150 // Pad out to 56 mod 64
153 // Two lots of padding: Pad the first block to 64 bytes
155 byteReverse(ctx
->in
, 16);
156 MD4Transform(ctx
->buf
, (uint32_t *) ctx
->in
);
158 // Now fill the next block with 56 bytes
159 memset(ctx
->in
, 0, 56);
163 // Pad block to 56 bytes
164 memset(p
, 0, count
- 8);
166 byteReverse(ctx
->in
, 14);
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];
172 MD4Transform(ctx
->buf
, (uint32_t *) ctx
->in
);
173 byteReverse((unsigned char *) ctx
->buf
, 4);
177 memcpy(digest
, ctx
->buf
, 16);
179 memset(ctx
, 0, sizeof(ctx
)); // In case it's sensitive
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))
187 #define MD4_FF(a, b, c, d, x, s) { \
188 (a) += MD4_F ((b), (c), (d)) + (x); \
189 (a) = rol ((a), (s)); \
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)); \
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)); \
200 /// The core of the MD4 algorithm
201 void MD4::MD4Transform(uint32_t buf
[4], uint32_t const in
[16])
203 register uint32_t a
, b
, c
, d
;
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 */
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 */
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 */
267 /// Algorithm verification
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"));
287 if (md4
.calcMd4FromString(test1
) != test1_md
)
289 if (md4
.calcMd4FromString(test2
) != test2_md
)
291 if (md4
.calcMd4FromString(test3
) != test3_md
)
293 if (md4
.calcMd4FromString(test4
) != test4_md
)
295 if (md4
.calcMd4FromString(test5
) != test5_md
)
297 if (md4
.calcMd4FromString(test6
) != test6_md
)
299 if (md4
.calcMd4FromString(test7
) != test7_md
)
305 /// Get Md4 hash from a string
306 wxString
MD4::calcMd4FromString(const wxString
&buf
)
309 unsigned char ret
[MD4_HASHLEN_BYTE
];
312 MD4Update(&hdc
, (const unsigned char*)buf
.c_str(), buf
.length());
315 return charToHex((const char*)ret
, MD4_HASHLEN_BYTE
);
318 /// Get Md4 hash from a file
319 wxString
MD4::calcMd4FromFile(const wxString
&filename
, MD4Hook hook
)
321 unsigned int bufSize
;
322 unsigned char ret
[MD4_HASHLEN_BYTE
];
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())
330 return wxEmptyString
;
334 bufSize
= calcBufSize(file
.Length());
335 char *buf
= new char[bufSize
];
337 bool keep_going
= true;
339 size_t totalread
= 0;
344 while (!file
.Eof() && keep_going
)
348 goAhead
= hook( (int)((double)(100.0 * totalread
) / file
.Length()));
352 read
= file
.Read(buf
, bufSize
);
353 MD4Update(&hdc
, reinterpret_cast<unsigned char const *>(buf
),
359 return (_("Cancelled !"));
366 return charToHex(reinterpret_cast<const char *>(ret
),
371 /// Convert hash to hexa string
372 wxString
MD4::charToHex(const char *buf
, size_t len
)
377 for (i
= 0; i
< len
; ++i
)
379 hexString
+= wxString::Format(wxS("%02x"), 0xFF & *(buf
+ i
));
382 // Reduce memory usage
388 /// Compute Md4 buffsize
389 size_t MD4::calcBufSize(size_t filesize
)
391 if (filesize
< 100000)
395 else if (filesize
> 200000)
402 // File_checked_for_headers