source: trunk/CrypPlugins/MD5Collider/Algorithm/StevensCollider.cs @ 1187

Last change on this file since 1187 was 1187, checked in by pretzsch, 12 years ago

+ MD5Collider: Added logging / display for amount of different binary block permutations tried

File size: 103.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Security.Cryptography;
6using System.Threading;
7
8namespace Cryptool.Plugins.MD5Collider.Algorithm
9{
10    class StevensCollider : MD5ColliderBase
11    {
12        protected override void PerformFindCollision()
13        {
14            IsStopped = false;
15
16            byte[] seedBytesMd5 = MD5.Create().ComputeHash(RandomSeed);
17            seed32_1 = (UInt32)(BitConverter.ToInt32(seedBytesMd5, 0) ^ BitConverter.ToInt32(seedBytesMd5, 4));
18            seed32_2 = (UInt32)(BitConverter.ToInt32(seedBytesMd5, 8) ^ BitConverter.ToInt32(seedBytesMd5, 12));
19
20            UInt32[] startIV = new UInt32[4];
21            startIV[0] = toLittleEndianInteger(IHV, 0);
22            startIV[1] = toLittleEndianInteger(IHV, 4);
23            startIV[2] = toLittleEndianInteger(IHV, 8);
24            startIV[3] = toLittleEndianInteger(IHV, 12);
25
26            UInt32[] m1b0 = new UInt32[16], m1b1 = new UInt32[16], m2b0 = new UInt32[16], m2b1 = new UInt32[16];
27            find_collision(startIV, m1b0, m1b1, m2b0, m2b1);
28
29            if (IsStopped)
30                return;
31
32            byte[] firstMessage = new byte[128];
33            byte[] secondMessage = new byte[128];
34
35            dumpLittleEndianIntegers(m1b0, firstMessage, 0);
36            dumpLittleEndianIntegers(m1b1, firstMessage, 64);
37
38            dumpLittleEndianIntegers(m2b0, secondMessage, 0);
39            dumpLittleEndianIntegers(m2b1, secondMessage, 64);
40
41            FirstCollidingData = firstMessage;
42            SecondCollidingData = secondMessage;
43        }
44
45        private void dumpLittleEndianIntegers(UInt32[] sourceArray, byte[] targetArray, int targetOffset)
46        {
47            for (int i = 0; i < sourceArray.Length; i++)
48                dumpLittleEndianInteger(sourceArray[i], targetArray, targetOffset + i * 4);
49        }
50
51        private void dumpLittleEndianInteger(UInt32 integerValue, byte[] targetArray, int targetOffset)
52        {
53            byte[] result = BitConverter.GetBytes(integerValue);
54            if (!BitConverter.IsLittleEndian)
55                Array.Reverse(result);
56
57            Array.Copy(result, 0, targetArray, targetOffset, 4);
58        }
59
60        private UInt32 toLittleEndianInteger(byte[] bytes, int offset)
61        {
62            byte[] bytesInProperOrder = new byte[4];
63            Array.Copy(bytes, offset, bytesInProperOrder, 0, 4);
64            if (!BitConverter.IsLittleEndian)
65                Array.Reverse(bytesInProperOrder);
66
67            return BitConverter.ToUInt32(bytesInProperOrder, 0);
68        }
69        private UInt32 toLittleEndianInteger(byte[] bytes)
70        {
71            return toLittleEndianInteger(bytes, 0);
72        }
73
74        void find_collision(UInt32[] IV, UInt32[] msg1block0, UInt32[] msg1block1, UInt32[] msg2block0, UInt32[] msg2block1)
75        {
76            find_block0(msg1block0, IV);
77
78            if (IsStopped)
79                return;
80
81            UInt32[] IHV = new[] { IV[0], IV[1], IV[2], IV[3] };
82            md5_compress(IHV, msg1block0);
83
84            find_block1(msg1block1, IHV);
85
86            if (IsStopped)
87                return;
88
89            for (int t = 0; t < 16; ++t)
90            {
91                msg2block0[t] = msg1block0[t];
92                msg2block1[t] = msg1block1[t];
93            }
94
95            msg2block0[4] += (UInt32)1 << 31; msg2block0[11] += 1 << 15; msg2block0[14] += (UInt32)1 << 31;
96            msg2block1[4] += (UInt32)1 << 31; msg2block1[11] -= 1 << 15; msg2block1[14] += (UInt32)1 << 31;
97        }
98
99        UInt32 xrng64()
100        {
101            UInt32 t = seed32_1 ^ (seed32_1 << 10);
102            seed32_1 = seed32_2;
103            seed32_2 = (seed32_2 ^ (seed32_2 >> 10)) ^ (t ^ (t >> 13));
104
105            return seed32_1;
106        }
107
108        UInt32 seed32_1, seed32_2;
109
110        private readonly int Qoff = 3;
111        delegate UInt32 RoundFunctionDelegate(UInt32 b, UInt32 c, UInt32 d);
112
113        UInt32 FF(UInt32 b, UInt32 c, UInt32 d)
114        { return d ^ (b & (c ^ d)); }
115
116        UInt32 GG(UInt32 b, UInt32 c, UInt32 d)
117        { return c ^ (d & (b ^ c)); }
118
119        UInt32 HH(UInt32 b, UInt32 c, UInt32 d)
120        { return b ^ c ^ d; }
121
122        UInt32 II(UInt32 b, UInt32 c, UInt32 d)
123        { return c ^ (b | ~d); }
124
125        UInt32 RL(UInt32 x, int n)
126        { return (x << n) | (x >> (32 - n)); }
127
128        UInt32 RR(UInt32 x, int n)
129        { return (x >> n) | (x << (32 - n)); }
130
131
132        void MD5_REVERSE_STEP(UInt32[] block, UInt32[] Q, int t, UInt32 AC, int RC)
133        {
134            block[t] = Q[Qoff + t + 1] - Q[Qoff + t];
135            block[t] = RR(block[t], RC) - FF(Q[Qoff + t], Q[Qoff + t - 1], Q[Qoff + t - 2]) - Q[Qoff + t - 3] - AC;
136        }
137
138        void find_block0(UInt32[] block, UInt32[] IV)
139        {
140            MatchProgressMax = 28;
141            MatchProgress = 0;
142
143            UInt32[] Q = new UInt32[68];
144            Q[0] = IV[0];
145            Q[1] = IV[3];
146            Q[2] = IV[2];
147            Q[3] = IV[1];
148
149            UInt32[] q4mask = new UInt32[1 << 4];
150            for (UInt32 k = 0; k < q4mask.Length; ++k)
151                q4mask[k] = ((k << 2) ^ (k << 26)) & 0x38000004;
152
153            UInt32[] q9q10mask = new UInt32[1 << 3];
154            for (UInt32 k = 0; k < q9q10mask.Length; ++k)
155                q9q10mask[k] = ((k << 13) ^ (k << 4)) & 0x2060;
156
157            UInt32[] q9mask = new UInt32[1 << 16];
158            for (UInt32 k = 0; k < q9mask.Length; ++k)
159                q9mask[k] = ((k << 1) ^ (k << 2) ^ (k << 5) ^ (k << 7) ^ (k << 8) ^ (k << 10) ^ (k << 11) ^ (k << 13)) & 0x0eb94f16;
160
161            while (true)
162            {
163                if (IsStopped)
164                    return;
165
166                Q[Qoff + 1] = xrng64();
167                Q[Qoff + 3] = (xrng64() & 0xfe87bc3f) | 0x017841c0;
168                Q[Qoff + 4] = (xrng64() & 0x44000033) | 0x000002c0 | (Q[Qoff + 3] & 0x0287bc00);
169                Q[Qoff + 5] = 0x41ffffc8 | (Q[Qoff + 4] & 0x04000033);
170                Q[Qoff + 6] = 0xb84b82d6;
171                Q[Qoff + 7] = (xrng64() & 0x68000084) | 0x02401b43;
172                Q[Qoff + 8] = (xrng64() & 0x2b8f6e04) | 0x005090d3 | (~Q[Qoff + 7] & 0x40000000);
173                Q[Qoff + 9] = 0x20040068 | (Q[Qoff + 8] & 0x00020000) | (~Q[Qoff + 8] & 0x40000000);
174                Q[Qoff + 10] = (xrng64() & 0x40000000) | 0x1040b089;
175                Q[Qoff + 11] = (xrng64() & 0x10408008) | 0x0fbb7f16 | (~Q[Qoff + 10] & 0x40000000);
176                Q[Qoff + 12] = (xrng64() & 0x1ed9df7f) | 0x00022080 | (~Q[Qoff + 11] & 0x40200000);
177                Q[Qoff + 13] = (xrng64() & 0x5efb4f77) | 0x20049008;
178                Q[Qoff + 14] = (xrng64() & 0x1fff5f77) | 0x0000a088 | (~Q[Qoff + 13] & 0x40000000);
179                Q[Qoff + 15] = (xrng64() & 0x5efe7ff7) | 0x80008000 | (~Q[Qoff + 14] & 0x00010000);
180                Q[Qoff + 16] = (xrng64() & 0x1ffdffff) | 0xa0000000 | (~Q[Qoff + 15] & 0x40020000);
181
182                MD5_REVERSE_STEP(block, Q, 0, 0xd76aa478, 7);
183                MD5_REVERSE_STEP(block, Q, 6, 0xa8304613, 17);
184                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
185                MD5_REVERSE_STEP(block, Q, 11, 0x895cd7be, 22);
186                MD5_REVERSE_STEP(block, Q, 14, 0xa679438e, 17);
187                MD5_REVERSE_STEP(block, Q, 15, 0x49b40821, 22);
188
189                UInt32 tt1 = FF(Q[Qoff + 1], Q[Qoff + 0], Q[Qoff - 1]) + Q[Qoff - 2] + 0xe8c7b756;
190                UInt32 tt17 = GG(Q[Qoff + 16], Q[Qoff + 15], Q[Qoff + 14]) + Q[Qoff + 13] + 0xf61e2562;
191                UInt32 tt18 = Q[Qoff + 14] + 0xc040b340 + block[6];
192                UInt32 tt19 = Q[Qoff + 15] + 0x265e5a51 + block[11];
193                UInt32 tt20 = Q[Qoff + 16] + 0xe9b6c7aa + block[0];
194                UInt32 tt5 = RR(Q[Qoff + 6] - Q[Qoff + 5], 12) - FF(Q[Qoff + 5], Q[Qoff + 4], Q[Qoff + 3]) - 0x4787c62a;
195
196                // change q17 until conditions are met on q18, q19 and q20
197                UInt32 counter = 0;
198                while (counter < (1 << 7))
199                {
200                    if (IsStopped)
201                        return;
202
203
204                    UInt32 q16 = Q[Qoff + 16];
205                    UInt32 q17 = ((xrng64() & 0x3ffd7ff7) | (q16 & 0xc0008008)) ^ 0x40000000;
206                    ++counter;
207
208                    UInt32 q18 = GG(q17, q16, Q[Qoff + 15]) + tt18;
209                    q18 = RL(q18, 9); q18 += q17;
210                    if (0x00020000 != ((q18 ^ q17) & 0xa0020000))
211                    {
212                        LogReturn(1);
213                        continue;
214                    }
215
216                    UInt32 q19 = GG(q18, q17, q16) + tt19;
217                    q19 = RL(q19, 14); q19 += q18;
218                    if (0x80000000 != (q19 & 0x80020000))
219                    {
220                        LogReturn(2);
221                        continue;
222                    }
223
224                    UInt32 q20 = GG(q19, q18, q17) + tt20;
225                    q20 = RL(q20, 20); q20 += q19;
226                    if (0x00040000 != ((q20 ^ q19) & 0x80040000))
227                    {
228                        LogReturn(3);
229                        continue;
230                    }
231
232                    block[1] = q17 - q16; block[1] = RR(block[1], 5); block[1] -= tt17;
233                    UInt32 q2 = block[1] + tt1; q2 = RL(q2, 12); q2 += Q[Qoff + 1];
234                    block[5] = tt5 - q2;
235
236                    Q[Qoff + 2] = q2;
237                    Q[Qoff + 17] = q17;
238                    Q[Qoff + 18] = q18;
239                    Q[Qoff + 19] = q19;
240                    Q[Qoff + 20] = q20;
241                    MD5_REVERSE_STEP(block, Q, 2, 0x242070db, 17);
242
243                    counter = 0;
244                    break;
245                }
246                if (counter != 0)
247                {
248                    LogReturn(4);
249                    continue;
250                }
251
252                UInt32 q4 = Q[Qoff + 4];
253                UInt32 q9backup = Q[Qoff + 9];
254                UInt32 tt21 = GG(Q[Qoff + 20], Q[Qoff + 19], Q[Qoff + 18]) + Q[Qoff + 17] + 0xd62f105d;
255
256                // iterate over possible changes of q4
257                // while keeping all conditions on q1-q20 intact
258                // this changes m3, m4, m5 and m7
259                UInt32 counter2 = 0;
260                while (counter2 < (1 << 4))
261                {
262                    if (IsStopped)
263                        return;
264
265
266                    Q[Qoff + 4] = q4 ^ q4mask[counter2];
267                    ++counter2;
268                    MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
269                    UInt32 q21 = tt21 + block[5];
270                    q21 = RL(q21, 5); q21 += Q[Qoff + 20];
271                    if (0 != ((q21 ^ Q[Qoff + 20]) & 0x80020000))
272                    {
273                        LogReturn(5);
274                        continue;
275                    }
276
277                    Q[Qoff + 21] = q21;
278                    MD5_REVERSE_STEP(block, Q, 3, 0xc1bdceee, 22);
279                    MD5_REVERSE_STEP(block, Q, 4, 0xf57c0faf, 7);
280                    MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
281
282                    UInt32 tt22 = GG(Q[Qoff + 21], Q[Qoff + 20], Q[Qoff + 19]) + Q[Qoff + 18] + 0x02441453;
283                    UInt32 tt23 = Q[Qoff + 19] + 0xd8a1e681 + block[15];
284                    UInt32 tt24 = Q[Qoff + 20] + 0xe7d3fbc8 + block[4];
285
286                    UInt32 tt9 = Q[Qoff + 6] + 0x8b44f7af;
287                    UInt32 tt10 = Q[Qoff + 7] + 0xffff5bb1;
288                    UInt32 tt8 = FF(Q[Qoff + 8], Q[Qoff + 7], Q[Qoff + 6]) + Q[Qoff + 5] + 0x698098d8;
289                    UInt32 tt12 = RR(Q[Qoff + 13] - Q[Qoff + 12], 7) - 0x6b901122;
290                    UInt32 tt13 = RR(Q[Qoff + 14] - Q[Qoff + 13], 12) - FF(Q[Qoff + 13], Q[Qoff + 12], Q[Qoff + 11]) - 0xfd987193;
291
292                    // iterate over possible changes of q9 and q10
293                    // while keeping conditions on q1-q21 intact
294                    // this changes m8, m9, m10, m12 and m13 (and not m11!)
295                    // the possible changes of q9 that also do not change m10 are used below
296                    for (UInt32 counter3 = 0; counter3 < (1 << 3); )
297                    {
298                        if (IsStopped)
299                            return;
300
301
302                        UInt32 q10 = Q[Qoff + 10] ^ (q9q10mask[counter3] & 0x60);
303                        Q[Qoff + 9] = q9backup ^ (q9q10mask[counter3] & 0x2000);
304                        ++counter3;
305                        UInt32 m10 = RR(Q[Qoff + 11] - q10, 17);
306                        m10 -= FF(q10, Q[Qoff + 9], Q[Qoff + 8]) + tt10;
307
308                        UInt32 aa = Q[Qoff + 21];
309                        UInt32 dd = tt22 + m10; dd = RL(dd, 9) + aa;
310                        if (0x80000000 != (dd & 0x80000000))
311                        {
312                            LogReturn(6);
313                            continue;
314                        }
315
316                        UInt32 bb = Q[Qoff + 20];
317                        UInt32 cc = tt23 + GG(dd, aa, bb);
318                        if (0 != (cc & 0x20000))
319                        {
320                            LogReturn(7);
321                            continue;
322                        }
323
324                        cc = RL(cc, 14) + dd;
325                        if (0 != (cc & 0x80000000))
326                        {
327                            LogReturn(8);
328                            continue;
329                        }
330
331                        bb = tt24 + GG(cc, dd, aa); bb = RL(bb, 20) + cc;
332                        if (0 == (bb & 0x80000000))
333                        {
334                            LogReturn(9);
335                            continue;
336                        }
337
338                        block[10] = m10;
339                        block[13] = tt13 - q10;
340
341                        // iterate over possible changes of q9
342                        // while keeping intact conditions on q1-q24
343                        // this changes m8, m9 and m12 (but not m10!)
344                        for (UInt32 counter4 = 0; counter4 < (1 << 16); ++counter4)
345                        {
346                            if (IsStopped)
347                                return;
348
349
350                            UInt32 q9 = Q[Qoff + 9] ^ q9mask[counter4];
351                            block[12] = tt12 - FF(Q[Qoff + 12], Q[Qoff + 11], q10) - q9;
352                            UInt32 m8 = q9 - Q[Qoff + 8];
353                            block[8] = RR(m8, 7) - tt8;
354                            UInt32 m9 = q10 - q9;
355                            block[9] = RR(m9, 12) - FF(q9, Q[Qoff + 8], Q[Qoff + 7]) - tt9;
356
357                            UInt32 a = aa, b = bb, c = cc, d = dd;
358                            MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
359                            MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
360                            MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
361                            MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
362                            MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
363                            MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
364                            MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
365                            MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
366                            MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
367                            MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
368
369                            c += HH(d, a, b) + block[11] + 0x6d9d6122;
370                            if (0 != (c & (1 << 15)))
371                            {
372                                LogReturn(10);
373                                continue;
374                            }
375                            c = (c << 16 | c >> 16) + d;
376
377
378                            MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
379                            MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
380                            MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
381                            MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
382                            MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
383                            MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
384                            MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
385                            MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
386                            MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
387                            MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
388                            MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
389                            MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
390                            MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
391                            if (0 != ((b ^ d) & 0x80000000))
392                            {
393                                LogReturn(11);
394                                continue;
395                            }
396
397
398                            MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
399                            if (0 != ((a ^ c) >> 31))
400                            {
401                                LogReturn(12);
402                                continue;
403                            }
404                            MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
405                            if (0 == ((b ^ d) >> 31))
406                            {
407                                LogReturn(13);
408                                continue;
409                            }
410                            MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
411                            if (0 != ((a ^ c) >> 31))
412                            {
413                                LogReturn(14);
414                                continue;
415                            }
416                            MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
417                            if (0 != ((b ^ d) >> 31))
418                            {
419                                LogReturn(15);
420                                continue;
421                            }
422                            MD5_STEP(II, ref a, b, c, d, block[12], 0x655b59c3, 6);
423                            if (0 != ((a ^ c) >> 31))
424                            {
425                                LogReturn(16);
426                                continue;
427                            }
428                            MD5_STEP(II, ref d, a, b, c, block[3], 0x8f0ccc92, 10);
429                            if (0 != ((b ^ d) >> 31))
430                            {
431                                LogReturn(17);
432                                continue;
433                            }
434                            MD5_STEP(II, ref c, d, a, b, block[10], 0xffeff47d, 15);
435                            if (0 != ((a ^ c) >> 31))
436                            {
437                                LogReturn(18);
438                                continue;
439                            }
440                            MD5_STEP(II, ref b, c, d, a, block[1], 0x85845dd1, 21);
441                            if (0 != ((b ^ d) >> 31))
442                            {
443                                LogReturn(19);
444                                continue;
445                            }
446                            MD5_STEP(II, ref a, b, c, d, block[8], 0x6fa87e4f, 6);
447                            if (0 != ((a ^ c) >> 31))
448                            {
449                                LogReturn(20);
450                                continue;
451                            }
452                            MD5_STEP(II, ref d, a, b, c, block[15], 0xfe2ce6e0, 10);
453                            if (0 != ((b ^ d) >> 31))
454                            {
455                                LogReturn(21);
456                                continue;
457                            }
458                            MD5_STEP(II, ref c, d, a, b, block[6], 0xa3014314, 15);
459                            if (0 != ((a ^ c) >> 31))
460                            {
461                                LogReturn(22);
462                                continue;
463                            }
464                            MD5_STEP(II, ref b, c, d, a, block[13], 0x4e0811a1, 21);
465                            if (0 == ((b ^ d) >> 31))
466                            {
467                                LogReturn(23);
468                                continue;
469                            }
470                            MD5_STEP(II, ref a, b, c, d, block[4], 0xf7537e82, 6);
471                            if (0 != ((a ^ c) >> 31))
472                            {
473                                LogReturn(24);
474                                continue;
475                            }
476                            MD5_STEP(II, ref d, a, b, c, block[11], 0xbd3af235, 10);
477                            if (0 != ((b ^ d) >> 31))
478                            {
479                                LogReturn(25);
480                                continue;
481                            }
482                            MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
483                            if (0 != ((a ^ c) >> 31))
484                            {
485                                LogReturn(26);
486                                continue;
487                            }
488                            MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
489
490                            UInt32 IHV1 = b + IV[1];
491                            UInt32 IHV2 = c + IV[2];
492                            UInt32 IHV3 = d + IV[3];
493
494                            bool wang = true;
495                            if (0x02000000 != ((IHV2 ^ IHV1) & 0x86000000)) wang = false;
496                            if (0 != ((IHV1 ^ IHV3) & 0x82000000)) wang = false;
497                            if (0 != (IHV1 & 0x06000020)) wang = false;
498
499                            bool stevens = true;
500                            if (((IHV1 ^ IHV2) >> 31) != 0 || ((IHV1 ^ IHV3) >> 31) != 0) stevens = false;
501                            if ((IHV3 & (1 << 25)) != 0 || (IHV2 & (1 << 25)) != 0 || (IHV1 & (1 << 25)) != 0
502                                || ((IHV2 ^ IHV1) & 1) != 0) stevens = false;
503
504                            if (!(wang || stevens))
505                            {
506                                LogReturn(27);
507                                continue;
508                            }
509
510                            UInt32[] IV1 = new UInt32[4], IV2 = new UInt32[4];
511                            for (int t = 0; t < 4; ++t)
512                                IV2[t] = IV1[t] = IV[t];
513
514                            UInt32[] block2 = new UInt32[16];
515                            for (int t = 0; t < 16; ++t)
516                                block2[t] = block[t];
517                            block2[4] += (UInt32)1 << 31;
518                            block2[11] += 1 << 15;
519                            block2[14] += (UInt32)1 << 31;
520
521                            md5_compress(IV1, block);
522                            md5_compress(IV2, block2);
523                            if ((IV2[0] == IV1[0] + (1 << 31))
524                                    && (IV2[1] == IV1[1] + (1 << 31) + (1 << 25))
525                                    && (IV2[2] == IV1[2] + (1 << 31) + (1 << 25))
526                                    && (IV2[3] == IV1[3] + (1 << 31) + (1 << 25)))
527                            {
528                                LogReturn(28);
529                                return;
530                            }
531
532                            //if (IV2[0] != IV1[0] + (1<<31))
533                            //  std::cout << "!" << std::flush;
534                        }
535                    }
536                }
537            }
538        }
539
540
541        void md5_compress(UInt32[] ihv, UInt32[] block)
542        {
543            UInt32 a = ihv[0];
544            UInt32 b = ihv[1];
545            UInt32 c = ihv[2];
546            UInt32 d = ihv[3];
547
548            MD5_STEP(FF, ref a, b, c, d, block[0], 0xd76aa478, 7);
549            MD5_STEP(FF, ref d, a, b, c, block[1], 0xe8c7b756, 12);
550            MD5_STEP(FF, ref c, d, a, b, block[2], 0x242070db, 17);
551            MD5_STEP(FF, ref b, c, d, a, block[3], 0xc1bdceee, 22);
552            MD5_STEP(FF, ref a, b, c, d, block[4], 0xf57c0faf, 7);
553            MD5_STEP(FF, ref d, a, b, c, block[5], 0x4787c62a, 12);
554            MD5_STEP(FF, ref c, d, a, b, block[6], 0xa8304613, 17);
555            MD5_STEP(FF, ref b, c, d, a, block[7], 0xfd469501, 22);
556            MD5_STEP(FF, ref a, b, c, d, block[8], 0x698098d8, 7);
557            MD5_STEP(FF, ref d, a, b, c, block[9], 0x8b44f7af, 12);
558            MD5_STEP(FF, ref c, d, a, b, block[10], 0xffff5bb1, 17);
559            MD5_STEP(FF, ref b, c, d, a, block[11], 0x895cd7be, 22);
560            MD5_STEP(FF, ref a, b, c, d, block[12], 0x6b901122, 7);
561            MD5_STEP(FF, ref d, a, b, c, block[13], 0xfd987193, 12);
562            MD5_STEP(FF, ref c, d, a, b, block[14], 0xa679438e, 17);
563            MD5_STEP(FF, ref b, c, d, a, block[15], 0x49b40821, 22);
564            MD5_STEP(GG, ref a, b, c, d, block[1], 0xf61e2562, 5);
565            MD5_STEP(GG, ref d, a, b, c, block[6], 0xc040b340, 9);
566            MD5_STEP(GG, ref c, d, a, b, block[11], 0x265e5a51, 14);
567            MD5_STEP(GG, ref b, c, d, a, block[0], 0xe9b6c7aa, 20);
568            MD5_STEP(GG, ref a, b, c, d, block[5], 0xd62f105d, 5);
569            MD5_STEP(GG, ref d, a, b, c, block[10], 0x02441453, 9);
570            MD5_STEP(GG, ref c, d, a, b, block[15], 0xd8a1e681, 14);
571            MD5_STEP(GG, ref b, c, d, a, block[4], 0xe7d3fbc8, 20);
572            MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
573            MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
574            MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
575            MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
576            MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
577            MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
578            MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
579            MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
580            MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
581            MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
582            MD5_STEP(HH, ref c, d, a, b, block[11], 0x6d9d6122, 16);
583            MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
584            MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
585            MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
586            MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
587            MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
588            MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
589            MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
590            MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
591            MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
592            MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
593            MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
594            MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
595            MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
596            MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
597            MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
598            MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
599            MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
600            MD5_STEP(II, ref  a, b, c, d, block[12], 0x655b59c3, 6);
601            MD5_STEP(II, ref  d, a, b, c, block[3], 0x8f0ccc92, 10);
602            MD5_STEP(II, ref  c, d, a, b, block[10], 0xffeff47d, 15);
603            MD5_STEP(II, ref  b, c, d, a, block[1], 0x85845dd1, 21);
604            MD5_STEP(II, ref  a, b, c, d, block[8], 0x6fa87e4f, 6);
605            MD5_STEP(II, ref  d, a, b, c, block[15], 0xfe2ce6e0, 10);
606            MD5_STEP(II, ref c, d, a, b, block[6], 0xa3014314, 15);
607            MD5_STEP(II, ref b, c, d, a, block[13], 0x4e0811a1, 21);
608            MD5_STEP(II, ref a, b, c, d, block[4], 0xf7537e82, 6);
609            MD5_STEP(II, ref d, a, b, c, block[11], 0xbd3af235, 10);
610            MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
611            MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
612
613            ihv[0] += a;
614            ihv[1] += b;
615            ihv[2] += c;
616            ihv[3] += d;
617        }
618
619        void MD5_STEP(RoundFunctionDelegate f, ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 m, UInt32 ac, Int32 rc)
620        {
621            a += f(b, c, d) + m + ac;
622            a = (a << rc | a >> (32 - rc)) + b;
623        }
624
625
626        void find_block1(UInt32[] block, UInt32[] IV)
627        {
628            if (((IV[1] ^ IV[2]) & (1 << 31)) == 0 && ((IV[1] ^ IV[3]) & (1 << 31)) == 0
629                && (IV[3] & (1 << 25)) == 0 && (IV[2] & (1 << 25)) == 0 && (IV[1] & (1 << 25)) == 0 && ((IV[2] ^ IV[1]) & 1) == 0
630               )
631            {
632                UInt32[] IV2 = new UInt32[] { (UInt32)(IV[0] + (1 << 31)), (UInt32)(IV[1] + (1 << 31) + (1 << 25)), (UInt32)(IV[2] + (1 << 31) + (1 << 25)), (UInt32)(IV[3] + (1 << 31) + (1 << 25)) };
633                if ((IV[1] & (1 << 6)) != 0 && (IV[1] & 1) != 0)
634                {
635                    find_block1_stevens_11(block, IV2);
636                }
637                else if ((IV[1] & (1 << 6)) != 0 && (IV[1] & 1) == 0)
638                {
639                    find_block1_stevens_10(block, IV2);
640                }
641                else if ((IV[1] & (1 << 6)) == 0 && (IV[1] & 1) != 0)
642                {
643                    find_block1_stevens_01(block, IV2);
644                }
645                else
646                {
647                    find_block1_stevens_00(block, IV2);
648                }
649                block[4] += (UInt32)1 << 31;
650                block[11] += 1 << 15;
651                block[14] += (UInt32)1 << 31;
652            }
653            else
654            {
655                find_block1_wang(block, IV);
656            }
657        }
658
659
660        void find_block1_stevens_00(UInt32[] block, UInt32[] IV)
661        {
662            MatchProgressMax = 29;
663            MatchProgress = 0;
664
665            UInt32[] Q = new UInt32[68];
666            Q[0] = IV[0];
667            Q[1] = IV[3];
668            Q[2] = IV[2];
669            Q[3] = IV[1];
670
671            UInt32[] q9q10mask = new UInt32[1 << 3];
672            for (UInt32 k = 0; k < q9q10mask.Length; ++k)
673                q9q10mask[k] = ((k << 5) ^ (k << 12) ^ (k << 25)) & 0x08002020;
674
675            UInt32[] q9mask = new UInt32[1 << 9];
676            for (UInt32 k = 0; k < q9mask.Length; ++k)
677                q9mask[k] = ((k << 1) ^ (k << 3) ^ (k << 6) ^ (k << 8) ^ (k << 11) ^ (k << 14) ^ (k << 18)) & 0x04310d12;
678
679            while (true)
680            {
681                if (IsStopped)
682                    return;
683
684                UInt32 aa1 = Q[Qoff] & 0x80000000;
685
686                Q[Qoff + 2] = (xrng64() & 0x49a0e73e) | 0x221f00c1 | aa1;
687                Q[Qoff + 3] = (xrng64() & 0x0000040c) | 0x3fce1a71 | (Q[Qoff + 2] & 0x8000e000);
688                Q[Qoff + 4] = (xrng64() & 0x00000004) | (0xa5f281a2 ^ (Q[Qoff + 3] & 0x80000008));
689                Q[Qoff + 5] = (xrng64() & 0x00000004) | 0x67fd823b;
690                Q[Qoff + 6] = (xrng64() & 0x00001044) | 0x15e5829a;
691                Q[Qoff + 7] = (xrng64() & 0x00200806) | 0x950430b0;
692                Q[Qoff + 8] = (xrng64() & 0x60050110) | 0x1bd29ca2 | (Q[Qoff + 7] & 0x00000004);
693                Q[Qoff + 9] = (xrng64() & 0x40044000) | 0xb8820004;
694                Q[Qoff + 10] = 0xf288b209 | (Q[Qoff + 9] & 0x00044000);
695                Q[Qoff + 11] = (xrng64() & 0x12888008) | 0x85712f57;
696                Q[Qoff + 12] = (xrng64() & 0x1ed98d7f) | 0xc0023080 | (~Q[Qoff + 11] & 0x00200000);
697                Q[Qoff + 13] = (xrng64() & 0x0efb1d77) | 0x1000c008;
698                Q[Qoff + 14] = (xrng64() & 0x0fff5d77) | 0xa000a288;
699                Q[Qoff + 15] = (xrng64() & 0x0efe7ff7) | 0xe0008000 | (~Q[Qoff + 14] & 0x00010000);
700                Q[Qoff + 16] = (xrng64() & 0x0ffdffff) | 0xf0000000 | (~Q[Qoff + 15] & 0x00020000);
701
702                MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
703                MD5_REVERSE_STEP(block, Q, 6, 0xa8304613, 17);
704                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
705                MD5_REVERSE_STEP(block, Q, 11, 0x895cd7be, 22);
706                MD5_REVERSE_STEP(block, Q, 14, 0xa679438e, 17);
707                MD5_REVERSE_STEP(block, Q, 15, 0x49b40821, 22);
708
709                UInt32 tt17 = GG(Q[Qoff + 16], Q[Qoff + 15], Q[Qoff + 14]) + Q[Qoff + 13] + 0xf61e2562;
710                UInt32 tt18 = Q[Qoff + 14] + 0xc040b340 + block[6];
711                UInt32 tt19 = Q[Qoff + 15] + 0x265e5a51 + block[11];
712
713                UInt32 tt0 = FF(Q[Qoff + 0], Q[Qoff - 1], Q[Qoff - 2]) + Q[Qoff - 3] + 0xd76aa478;
714                UInt32 tt1 = Q[Qoff - 2] + 0xe8c7b756;
715                UInt32 q1a = 0x02020801 | (Q[Qoff + 0] & 0x80000000);
716
717                UInt32 counter = 0;
718                while (counter < (1 << 12))
719                {
720                    if (IsStopped)
721                        return;
722
723                    ++counter;
724
725                    UInt32 q1 = q1a | (xrng64() & 0x7dfdf7be);
726                    UInt32 m1 = Q[Qoff + 2] - q1;
727                    m1 = RR(m1, 12) - FF(q1, Q[Qoff + 0], Q[Qoff - 1]) - tt1;
728
729                    UInt32 q16 = Q[Qoff + 16];
730                    UInt32 q17 = tt17 + m1;
731                    q17 = RL(q17, 5) + q16;
732                    if (0x80000000 != ((q17 ^ q16) & 0x80008008))
733                    {
734                        LogReturn(1);
735                        continue;
736                    }
737
738                    if (0 != (q17 & 0x00020000))
739                    {
740                        LogReturn(2);
741                        continue;
742                    }
743
744                    UInt32 q18 = GG(q17, q16, Q[Qoff + 15]) + tt18;
745                    q18 = RL(q18, 9); q18 += q17;
746                    if (0x80020000 != ((q18 ^ q17) & 0xa0020000))
747                    {
748                        LogReturn(3);
749                        continue;
750                    }
751
752                    UInt32 q19 = GG(q18, q17, q16) + tt19;
753                    q19 = RL(q19, 14); q19 += q18;
754                    if (0x80000000 != (q19 & 0x80020000))
755                    {
756                        LogReturn(4);
757                        continue;
758                    }
759
760                    UInt32 m0 = q1 - Q[Qoff + 0];
761                    m0 = RR(m0, 7) - tt0;
762
763                    UInt32 q20 = GG(q19, q18, q17) + q16 + 0xe9b6c7aa + m0;
764                    q20 = RL(q20, 20); q20 += q19;
765                    if (0x00040000 != ((q20 ^ q19) & 0x80040000))
766                    {
767                        LogReturn(5);
768                        continue;
769                    }
770
771                    Q[Qoff + 1] = q1;
772                    Q[Qoff + 17] = q17;
773                    Q[Qoff + 18] = q18;
774                    Q[Qoff + 19] = q19;
775                    Q[Qoff + 20] = q20;
776
777                    block[0] = m0;
778                    block[1] = m1;
779
780                    MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
781                    UInt32 q21 = GG(Q[Qoff + 20], Q[Qoff + 19], Q[Qoff + 18]) + Q[Qoff + 17] + 0xd62f105d + block[5];
782                    q21 = RL(q21, 5); q21 += Q[Qoff + 20];
783                    if (0 != ((q21 ^ Q[Qoff + 20]) & 0x80020000))
784                    {
785                        LogReturn(6);
786                        continue;
787                    }
788                    Q[Qoff + 21] = q21;
789
790                    counter = 0;
791                    break;
792                }
793                if (counter != 0)
794                {
795                    LogReturn(7);
796                    continue;
797                }
798
799                UInt32 q9b = Q[Qoff + 9];
800                UInt32 q10b = Q[Qoff + 10];
801
802                MD5_REVERSE_STEP(block, Q, 2, 0x242070db, 17);
803                MD5_REVERSE_STEP(block, Q, 3, 0xc1bdceee, 22);
804                MD5_REVERSE_STEP(block, Q, 4, 0xf57c0faf, 7);
805                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
806
807                UInt32 tt10 = Q[Qoff + 7] + 0xffff5bb1;
808                UInt32 tt22 = GG(Q[Qoff + 21], Q[Qoff + 20], Q[Qoff + 19]) + Q[Qoff + 18] + 0x02441453;
809                UInt32 tt23 = Q[Qoff + 19] + 0xd8a1e681 + block[15];
810                UInt32 tt24 = Q[Qoff + 20] + 0xe7d3fbc8 + block[4];
811
812                for (UInt32 k10 = 0; k10 < (1 << 3); ++k10)
813                {
814                    if (IsStopped)
815                        return;
816
817                    UInt32 q10 = q10b | (q9q10mask[k10] & 0x08000020);
818                    UInt32 m10 = RR(Q[Qoff + 11] - q10, 17);
819                    UInt32 q9 = q9b | (q9q10mask[k10] & 0x00002000);
820
821                    m10 -= FF(q10, q9, Q[Qoff + 8]) + tt10;
822
823                    UInt32 aa = Q[Qoff + 21];
824                    UInt32 dd = tt22 + m10; dd = RL(dd, 9) + aa;
825                    if (0 == (dd & 0x80000000))
826                    {
827                        LogReturn(8);
828                        continue;
829                    }
830
831                    UInt32 bb = Q[Qoff + 20];
832                    UInt32 cc = tt23 + GG(dd, aa, bb);
833                    if (0 != (cc & 0x20000))
834                    {
835                        LogReturn(9);
836                        continue;
837                    }
838                    cc = RL(cc, 14) + dd;
839                    if (0 != (cc & 0x80000000))
840                    {
841                        LogReturn(10);
842                        continue;
843                    }
844
845                    bb = tt24 + GG(cc, dd, aa); bb = RL(bb, 20) + cc;
846                    if (0 == (bb & 0x80000000))
847                    {
848                        LogReturn(11);
849                        continue;
850                    }
851
852                    block[10] = m10;
853                    Q[Qoff + 9] = q9;
854                    Q[Qoff + 10] = q10;
855                    MD5_REVERSE_STEP(block, Q, 13, 0xfd987193, 12);
856
857                    for (UInt32 k9 = 0; k9 < (1 << 9); ++k9)
858                    {
859                        if (IsStopped)
860                            return;
861
862                        UInt32 a = aa, b = bb, c = cc, d = dd;
863                        Q[Qoff + 9] = q9 ^ q9mask[k9];
864                        MD5_REVERSE_STEP(block, Q, 8, 0x698098d8, 7);
865                        MD5_REVERSE_STEP(block, Q, 9, 0x8b44f7af, 12);
866                        MD5_REVERSE_STEP(block, Q, 12, 0x6b901122, 7);
867
868                        MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
869                        MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
870                        MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
871                        MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
872                        MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
873                        MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
874                        MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
875                        MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
876                        MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
877                        MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
878
879                        c += HH(d, a, b) + block[11] + 0x6d9d6122;
880                        if (0 != (c & (1 << 15)))
881                        {
882                            LogReturn(12);
883                            continue;
884                        }
885                        c = (c << 16 | c >> 16) + d;
886
887                        MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
888                        MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
889                        MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
890                        MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
891                        MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
892                        MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
893                        MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
894                        MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
895                        MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
896                        MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
897                        MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
898                        MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
899                        MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
900                        if (0 != ((b ^ d) & 0x80000000))
901                        {
902                            LogReturn(13);
903                            continue;
904                        }
905
906                        MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
907                        if (0 != ((a ^ c) >> 31))
908                        {
909                            LogReturn(14);
910                            continue;
911                        }
912                        MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
913                        if (0 == ((b ^ d) >> 31))
914                        {
915                            LogReturn(15);
916                            continue;
917                        }
918                        MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
919                        if (0 != ((a ^ c) >> 31))
920                        {
921                            LogReturn(16);
922                            continue;
923                        }
924                        MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
925                        if (0 != ((b ^ d) >> 31))
926                        {
927                            LogReturn(17);
928                            continue;
929                        }
930                        MD5_STEP(II, ref a, b, c, d, block[12], 0x655b59c3, 6);
931                        if (0 != ((a ^ c) >> 31))
932                        {
933                            LogReturn(18);
934                            continue;
935                        }
936                        MD5_STEP(II, ref d, a, b, c, block[3], 0x8f0ccc92, 10);
937                        if (0 != ((b ^ d) >> 31))
938                        {
939                            LogReturn(19);
940                            continue;
941                        }
942                        MD5_STEP(II, ref c, d, a, b, block[10], 0xffeff47d, 15);
943                        if (0 != ((a ^ c) >> 31))
944                        {
945                            LogReturn(20);
946                            continue;
947                        }
948                        MD5_STEP(II, ref b, c, d, a, block[1], 0x85845dd1, 21);
949                        if (0 != ((b ^ d) >> 31))
950                        {
951                            LogReturn(21);
952                            continue;
953                        }
954                        MD5_STEP(II, ref a, b, c, d, block[8], 0x6fa87e4f, 6);
955                        if (0 != ((a ^ c) >> 31))
956                        {
957                            LogReturn(22);
958                            continue;
959                        }
960                        MD5_STEP(II, ref d, a, b, c, block[15], 0xfe2ce6e0, 10);
961                        if (0 != ((b ^ d) >> 31))
962                        {
963                            LogReturn(23);
964                            continue;
965                        }
966                        MD5_STEP(II, ref c, d, a, b, block[6], 0xa3014314, 15);
967                        if (0 != ((a ^ c) >> 31))
968                        {
969                            LogReturn(24);
970                            continue;
971                        }
972                        MD5_STEP(II, ref b, c, d, a, block[13], 0x4e0811a1, 21);
973                        if (0 == ((b ^ d) >> 31))
974                        {
975                            LogReturn(25);
976                            continue;
977                        }
978                        MD5_STEP(II, ref  a, b, c, d, block[4], 0xf7537e82, 6);
979                        if (0 != ((a ^ c) >> 31))
980                        {
981                            LogReturn(26);
982                            continue;
983                        }
984                        MD5_STEP(II, ref d, a, b, c, block[11], 0xbd3af235, 10);
985                        if (0 != ((b ^ d) >> 31))
986                        {
987                            LogReturn(27);
988                            continue;
989                        }
990                        MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
991                        if (0 != ((a ^ c) >> 31))
992                        {
993                            LogReturn(28);
994                            continue;
995                        }
996                        MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
997
998                        UInt32[] block2 = new UInt32[16];
999                        UInt32[] IV1 = new UInt32[4], IV2 = new UInt32[4];
1000                        for (int t = 0; t < 4; ++t)
1001                        {
1002                            IV1[t] = IV[t];
1003                            IV2[t] = IV[t] + ((UInt32)1 << 31);
1004                        }
1005                        IV2[1] -= (1 << 25);
1006                        IV2[2] -= (1 << 25);
1007                        IV2[3] -= (1 << 25);
1008
1009                        for (int t = 0; t < 16; ++t)
1010                            block2[t] = block[t];
1011                        block2[4] += (UInt32)1 << 31;
1012                        block2[11] += 1 << 15;
1013                        block2[14] += (UInt32)1 << 31;
1014
1015                        md5_compress(IV1, block);
1016                        md5_compress(IV2, block2);
1017                        if (IV2[0] == IV1[0] && IV2[1] == IV1[1] && IV2[2] == IV1[2] && IV2[3] == IV1[3])
1018                        {
1019                            LogReturn(29);
1020                            return;
1021                        }
1022
1023                        //if (IV2[0] != IV1[0])
1024                        //              std::cout << "!" << std::flush;
1025                    }
1026                }
1027            }
1028        }
1029
1030        void find_block1_stevens_01(UInt32[] block, UInt32[] IV)
1031        {
1032            MatchProgressMax = 30;
1033            MatchProgress = 0;
1034
1035            UInt32[] Q = new UInt32[68];
1036            Q[0] = IV[0];
1037            Q[1] = IV[3];
1038            Q[2] = IV[2];
1039            Q[3] = IV[1];
1040
1041            UInt32[] q9q10mask = new UInt32[1 << 5];
1042            for (UInt32 k = 0; k < q9q10mask.Length; ++k)
1043                q9q10mask[k] = ((k << 4) ^ (k << 11) ^ (k << 24) ^ (k << 27)) & 0x88002030;
1044
1045            UInt32[] q9mask = new UInt32[1 << 9];
1046            for (UInt32 k = 0; k < q9mask.Length; ++k)
1047                q9mask[k] = ((k << 1) ^ (k << 7) ^ (k << 9) ^ (k << 12) ^ (k << 15) ^ (k << 19) ^ (k << 22)) & 0x44310d02;
1048
1049            while (true)
1050            {
1051                if (IsStopped)
1052                    return;
1053
1054
1055                UInt32 aa1 = Q[Qoff] & 0x80000000;
1056
1057                Q[Qoff + 2] = (xrng64() & 0x4db0e03e) | 0x32460441 | aa1;
1058                Q[Qoff + 3] = (xrng64() & 0x0c000008) | 0x123c3af1 | (Q[Qoff + 2] & 0x80800002);
1059                Q[Qoff + 4] = 0xe398f812 ^ (Q[Qoff + 3] & 0x88000000);
1060                Q[Qoff + 5] = (xrng64() & 0x82000000) | 0x4c66e99e;
1061                Q[Qoff + 6] = (xrng64() & 0x80000000) | 0x27180590;
1062                Q[Qoff + 7] = (xrng64() & 0x00010130) | 0x51ea9e47;
1063                Q[Qoff + 8] = (xrng64() & 0x40200800) | 0xb7c291e5;
1064                Q[Qoff + 9] = (xrng64() & 0x00044000) | 0x380002b4;
1065                Q[Qoff + 10] = 0xb282b208 | (Q[Qoff + 9] & 0x00044000);
1066                Q[Qoff + 11] = (xrng64() & 0x12808008) | 0xc5712f47;
1067                Q[Qoff + 12] = (xrng64() & 0x1ef18d7f) | 0x000a3080;
1068                Q[Qoff + 13] = (xrng64() & 0x1efb1d77) | 0x4004c008;
1069                Q[Qoff + 14] = (xrng64() & 0x1fff5d77) | 0x6000a288;
1070                Q[Qoff + 15] = (xrng64() & 0x1efe7ff7) | 0xa0008000 | (~Q[Qoff + 14] & 0x00010000);
1071                Q[Qoff + 16] = (xrng64() & 0x1ffdffff) | 0x20000000 | (~Q[Qoff + 15] & 0x00020000);
1072
1073                MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
1074                MD5_REVERSE_STEP(block, Q, 6, 0xa8304613, 17);
1075                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
1076                MD5_REVERSE_STEP(block, Q, 11, 0x895cd7be, 22);
1077                MD5_REVERSE_STEP(block, Q, 14, 0xa679438e, 17);
1078                MD5_REVERSE_STEP(block, Q, 15, 0x49b40821, 22);
1079
1080                UInt32 tt17 = GG(Q[Qoff + 16], Q[Qoff + 15], Q[Qoff + 14]) + Q[Qoff + 13] + 0xf61e2562;
1081                UInt32 tt18 = Q[Qoff + 14] + 0xc040b340 + block[6];
1082                UInt32 tt19 = Q[Qoff + 15] + 0x265e5a51 + block[11];
1083
1084                UInt32 tt0 = FF(Q[Qoff + 0], Q[Qoff - 1], Q[Qoff - 2]) + Q[Qoff - 3] + 0xd76aa478;
1085                UInt32 tt1 = Q[Qoff - 2] + 0xe8c7b756;
1086
1087                UInt32 q1a = 0x02000021 ^ (Q[Qoff + 0] & 0x80000020);
1088
1089                UInt32 counter = 0;
1090                while (counter < (1 << 12))
1091                {
1092                    if (IsStopped)
1093                        return;
1094
1095
1096                    ++counter;
1097
1098                    UInt32 q1 = q1a | (xrng64() & 0x7dfff39e);
1099                    UInt32 m1 = Q[Qoff + 2] - q1;
1100                    m1 = RR(m1, 12) - FF(q1, Q[Qoff + 0], Q[Qoff - 1]) - tt1;
1101
1102                    UInt32 q16 = Q[Qoff + 16];
1103                    UInt32 q17 = tt17 + m1;
1104                    q17 = RL(q17, 5) + q16;
1105                    if (0x80000000 != ((q17 ^ q16) & 0x80008008))
1106                    {
1107                        LogReturn(1);
1108                        continue;
1109                    }
1110                    if (0 != (q17 & 0x00020000))
1111                    {
1112                        LogReturn(2);
1113                        continue;
1114                    }
1115
1116                    UInt32 q18 = GG(q17, q16, Q[Qoff + 15]) + tt18;
1117                    q18 = RL(q18, 9); q18 += q17;
1118                    if (0x80020000 != ((q18 ^ q17) & 0xa0020000))
1119                    {
1120                        LogReturn(3);
1121                        continue;
1122                    }
1123
1124                    UInt32 q19 = GG(q18, q17, q16) + tt19;
1125                    q19 = RL(q19, 14); q19 += q18;
1126                    if (0 != (q19 & 0x80020000))
1127                    {
1128                        LogReturn(4);
1129                        continue;
1130                    }
1131
1132                    UInt32 m0 = q1 - Q[Qoff + 0];
1133                    m0 = RR(m0, 7) - tt0;
1134
1135                    UInt32 q20 = GG(q19, q18, q17) + q16 + 0xe9b6c7aa + m0;
1136                    q20 = RL(q20, 20); q20 += q19;
1137                    if (0x00040000 != ((q20 ^ q19) & 0x80040000))
1138                    {
1139                        LogReturn(5);
1140                        continue;
1141                    }
1142
1143                    Q[Qoff + 1] = q1;
1144                    Q[Qoff + 17] = q17;
1145                    Q[Qoff + 18] = q18;
1146                    Q[Qoff + 19] = q19;
1147                    Q[Qoff + 20] = q20;
1148
1149                    block[0] = m0;
1150                    block[1] = m1;
1151
1152                    MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
1153                    UInt32 q21 = GG(Q[Qoff + 20], Q[Qoff + 19], Q[Qoff + 18]) + Q[Qoff + 17] + 0xd62f105d + block[5];
1154                    q21 = RL(q21, 5); q21 += Q[Qoff + 20];
1155                    if (0 != ((q21 ^ Q[Qoff + 20]) & 0x80020000))
1156                    {
1157                        LogReturn(6);
1158                        continue;
1159                    }
1160
1161                    Q[Qoff + 21] = q21;
1162
1163                    counter = 0;
1164
1165                    LogReturn(7);
1166                    break;
1167                }
1168                if (counter != 0)
1169                {
1170                    LogReturn(8);
1171                    continue;
1172                }
1173
1174                UInt32 q9b = Q[Qoff + 9];
1175                UInt32 q10b = Q[Qoff + 10];
1176
1177                MD5_REVERSE_STEP(block, Q, 2, 0x242070db, 17);
1178                MD5_REVERSE_STEP(block, Q, 3, 0xc1bdceee, 22);
1179                MD5_REVERSE_STEP(block, Q, 4, 0xf57c0faf, 7);
1180                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
1181
1182                UInt32 tt10 = Q[Qoff + 7] + 0xffff5bb1;
1183                UInt32 tt22 = GG(Q[Qoff + 21], Q[Qoff + 20], Q[Qoff + 19]) + Q[Qoff + 18] + 0x02441453;
1184                UInt32 tt23 = Q[Qoff + 19] + 0xd8a1e681 + block[15];
1185                UInt32 tt24 = Q[Qoff + 20] + 0xe7d3fbc8 + block[4];
1186
1187                for (UInt32 k10 = 0; k10 < (1 << 5); ++k10)
1188                {
1189                    if (IsStopped)
1190                        return;
1191
1192
1193                    UInt32 q10 = q10b | (q9q10mask[k10] & 0x08000030);
1194                    UInt32 m10 = RR(Q[Qoff + 11] - q10, 17);
1195                    UInt32 q9 = q9b | (q9q10mask[k10] & 0x80002000);
1196
1197                    m10 -= FF(q10, q9, Q[Qoff + 8]) + tt10;
1198
1199                    UInt32 aa = Q[Qoff + 21];
1200                    UInt32 dd = tt22 + m10; dd = RL(dd, 9) + aa;
1201                    if (0 != (dd & 0x80000000))
1202                    {
1203                        LogReturn(9);
1204                        continue;
1205                    }
1206
1207                    UInt32 bb = Q[Qoff + 20];
1208                    UInt32 cc = tt23 + GG(dd, aa, bb);
1209                    if (0 != (cc & 0x20000))
1210                    {
1211                        LogReturn(10);
1212                        continue;
1213                    }
1214                    cc = RL(cc, 14) + dd;
1215                    if (0 != (cc & 0x80000000))
1216                    {
1217                        LogReturn(11);
1218                        continue;
1219                    }
1220
1221                    bb = tt24 + GG(cc, dd, aa); bb = RL(bb, 20) + cc;
1222                    if (0 == (bb & 0x80000000))
1223                    {
1224                        LogReturn(12);
1225                        continue;
1226                    }
1227
1228                    block[10] = m10;
1229                    Q[Qoff + 9] = q9;
1230                    Q[Qoff + 10] = q10;
1231                    MD5_REVERSE_STEP(block, Q, 13, 0xfd987193, 12);
1232
1233                    for (UInt32 k9 = 0; k9 < (1 << 9); ++k9)
1234                    {
1235                        if (IsStopped)
1236                            return;
1237
1238
1239                        UInt32 a = aa, b = bb, c = cc, d = dd;
1240                        Q[Qoff + 9] = q9 ^ q9mask[k9];
1241                        MD5_REVERSE_STEP(block, Q, 8, 0x698098d8, 7);
1242                        MD5_REVERSE_STEP(block, Q, 9, 0x8b44f7af, 12);
1243                        MD5_REVERSE_STEP(block, Q, 12, 0x6b901122, 7);
1244
1245                        MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
1246                        MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
1247                        MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
1248                        MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
1249                        MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
1250                        MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
1251                        MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
1252                        MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
1253                        MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
1254                        MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
1255
1256                        c += HH(d, a, b) + block[11] + 0x6d9d6122;
1257                        if (0 != (c & (1 << 15)))
1258                        {
1259                            LogReturn(13);
1260                            continue;
1261                        }
1262                        c = (c << 16 | c >> 16) + d;
1263
1264                        MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
1265                        MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
1266                        MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
1267                        MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
1268                        MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
1269                        MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
1270                        MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
1271                        MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
1272                        MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
1273                        MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
1274                        MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
1275                        MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
1276                        MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
1277                        if (0 != ((b ^ d) & 0x80000000))
1278                        {
1279                            LogReturn(14);
1280                            continue;
1281                        }
1282
1283                        MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
1284                        if (0 != ((a ^ c) >> 31))
1285                        {
1286                            LogReturn(15);
1287                            continue;
1288                        }
1289                        MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
1290                        if (0 == ((b ^ d) >> 31))
1291                        {
1292                            LogReturn(16);
1293                            continue;
1294                        }
1295                        MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
1296                        if (0 != ((a ^ c) >> 31))
1297                        {
1298                            LogReturn(17);
1299                            continue;
1300                        }
1301                        MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
1302                        if (0 != ((b ^ d) >> 31))
1303                        {
1304                            LogReturn(18);
1305                            continue;
1306                        }
1307                        MD5_STEP(II, ref a, b, c, d, block[12], 0x655b59c3, 6);
1308                        if (0 != ((a ^ c) >> 31))
1309                        {
1310                            LogReturn(19);
1311                            continue;
1312                        }
1313                        MD5_STEP(II, ref d, a, b, c, block[3], 0x8f0ccc92, 10);
1314                        if (0 != ((b ^ d) >> 31))
1315                        {
1316                            LogReturn(20);
1317                            continue;
1318                        }
1319                        MD5_STEP(II, ref c, d, a, b, block[10], 0xffeff47d, 15);
1320                        if (0 != ((a ^ c) >> 31))
1321                        {
1322                            LogReturn(21);
1323                            continue;
1324                        }
1325                        MD5_STEP(II, ref b, c, d, a, block[1], 0x85845dd1, 21);
1326                        if (0 != ((b ^ d) >> 31))
1327                        {
1328                            LogReturn(22);
1329                            continue;
1330                        }
1331                        MD5_STEP(II, ref a, b, c, d, block[8], 0x6fa87e4f, 6);
1332                        if (0 != ((a ^ c) >> 31))
1333                        {
1334                            LogReturn(23);
1335                            continue;
1336                        }
1337                        MD5_STEP(II, ref d, a, b, c, block[15], 0xfe2ce6e0, 10);
1338                        if (0 != ((b ^ d) >> 31))
1339                        {
1340                            LogReturn(24);
1341                            continue;
1342                        }
1343                        MD5_STEP(II, ref c, d, a, b, block[6], 0xa3014314, 15);
1344                        if (0 != ((a ^ c) >> 31))
1345                        {
1346                            LogReturn(25);
1347                            continue;
1348                        }
1349                        MD5_STEP(II, ref b, c, d, a, block[13], 0x4e0811a1, 21);
1350                        if (0 == ((b ^ d) >> 31))
1351                        {
1352                            LogReturn(26);
1353                            continue;
1354                        }
1355                        MD5_STEP(II, ref a, b, c, d, block[4], 0xf7537e82, 6);
1356                        if (0 != ((a ^ c) >> 31))
1357                        {
1358                            LogReturn(27);
1359                            continue;
1360                        }
1361                        MD5_STEP(II, ref d, a, b, c, block[11], 0xbd3af235, 10);
1362                        if (0 != ((b ^ d) >> 31))
1363                        {
1364                            LogReturn(28);
1365                            continue;
1366                        }
1367                        MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
1368                        if (0 != ((a ^ c) >> 31))
1369                        {
1370                            LogReturn(29);
1371                            continue;
1372                        }
1373                        MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
1374
1375                        UInt32[] block2 = new UInt32[16];
1376                        UInt32[] IV1 = new UInt32[4], IV2 = new UInt32[4];
1377                        for (int t = 0; t < 4; ++t)
1378                        {
1379                            IV1[t] = IV[t];
1380                            IV2[t] = IV[t] + ((UInt32)1 << 31);
1381                        }
1382                        IV2[1] -= (1 << 25);
1383                        IV2[2] -= (1 << 25);
1384                        IV2[3] -= (1 << 25);
1385
1386                        for (int t = 0; t < 16; ++t)
1387                            block2[t] = block[t];
1388                        block2[4] += (UInt32)1 << 31;
1389                        block2[11] += 1 << 15;
1390                        block2[14] += (UInt32)1 << 31;
1391
1392                        md5_compress(IV1, block);
1393                        md5_compress(IV2, block2);
1394                        if (IV2[0] == IV1[0] && IV2[1] == IV1[1] && IV2[2] == IV1[2] && IV2[3] == IV1[3])
1395                        {
1396                            LogReturn(30);
1397                            return;
1398                        }
1399
1400                        //if (IV2[0] != IV1[0])
1401                        //              std::cout << "!" << std::flush;
1402                    }
1403                }
1404            }
1405        }
1406
1407
1408        void find_block1_stevens_10(UInt32[] block, UInt32[] IV)
1409        {
1410            MatchProgressMax = 30;
1411            MatchProgress = 0;
1412
1413            UInt32[] Q = new UInt32[68];
1414            Q[0] = IV[0];
1415            Q[1] = IV[3];
1416            Q[2] = IV[2];
1417            Q[3] = IV[1];
1418
1419            UInt32[] q9q10mask = new UInt32[1 << 4];
1420            for (UInt32 k = 0; k < q9q10mask.Length; ++k)
1421                q9q10mask[k] = ((k << 2) ^ (k << 8) ^ (k << 11) ^ (k << 25)) & 0x08004204;
1422
1423            UInt32[] q9mask = new UInt32[1 << 10];
1424            for (UInt32 k = 0; k < q9mask.Length; ++k)
1425                q9mask[k] = ((k << 1) ^ (k << 2) ^ (k << 3) ^ (k << 7) ^ (k << 12) ^ (k << 15) ^ (k << 18) ^ (k << 20)) & 0x2471042a;
1426
1427            while (true)
1428            {
1429                if (IsStopped)
1430                    return;
1431
1432
1433                UInt32 aa1 = Q[Qoff] & 0x80000000;
1434
1435                Q[Qoff + 2] = (xrng64() & 0x79b0c6ba) | 0x024c3841 | aa1;
1436                Q[Qoff + 3] = (xrng64() & 0x19300210) | 0x2603096d | (Q[Qoff + 2] & 0x80000082);
1437                Q[Qoff + 4] = (xrng64() & 0x10300000) | 0xe4cae30c | (Q[Qoff + 3] & 0x01000030);
1438                Q[Qoff + 5] = (xrng64() & 0x10000000) | 0x63494061 | (Q[Qoff + 4] & 0x00300000);
1439                Q[Qoff + 6] = 0x7deaff68;
1440                Q[Qoff + 7] = (xrng64() & 0x20444000) | 0x09091ee0;
1441                Q[Qoff + 8] = (xrng64() & 0x09040000) | 0xb2529f6d;
1442                Q[Qoff + 9] = (xrng64() & 0x00040000) | 0x10885184;
1443                Q[Qoff + 10] = (xrng64() & 0x00000080) | 0x428afb11 | (Q[Qoff + 9] & 0x00040000);
1444                Q[Qoff + 11] = (xrng64() & 0x128a8110) | 0x6571266b | (Q[Qoff + 10] & 0x0000080);
1445                Q[Qoff + 12] = (xrng64() & 0x3ef38d7f) | 0x00003080 | (~Q[Qoff + 11] & 0x00080000);
1446                Q[Qoff + 13] = (xrng64() & 0x3efb1d77) | 0x0004c008;
1447                Q[Qoff + 14] = (xrng64() & 0x5fff5d77) | 0x8000a288;
1448                Q[Qoff + 15] = (xrng64() & 0x1efe7ff7) | 0xe0008000 | (~Q[Qoff + 14] & 0x00010000);
1449                Q[Qoff + 16] = (xrng64() & 0x5ffdffff) | 0x20000000 | (~Q[Qoff + 15] & 0x00020000);
1450
1451                MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
1452                MD5_REVERSE_STEP(block, Q, 6, 0xa8304613, 17);
1453                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
1454                MD5_REVERSE_STEP(block, Q, 11, 0x895cd7be, 22);
1455                MD5_REVERSE_STEP(block, Q, 14, 0xa679438e, 17);
1456                MD5_REVERSE_STEP(block, Q, 15, 0x49b40821, 22);
1457
1458                UInt32 tt17 = GG(Q[Qoff + 16], Q[Qoff + 15], Q[Qoff + 14]) + Q[Qoff + 13] + 0xf61e2562;
1459                UInt32 tt18 = Q[Qoff + 14] + 0xc040b340 + block[6];
1460                UInt32 tt19 = Q[Qoff + 15] + 0x265e5a51 + block[11];
1461
1462                UInt32 tt0 = FF(Q[Qoff + 0], Q[Qoff - 1], Q[Qoff - 2]) + Q[Qoff - 3] + 0xd76aa478;
1463                UInt32 tt1 = Q[Qoff - 2] + 0xe8c7b756;
1464
1465                UInt32 q1a = 0x02000941 ^ (Q[Qoff + 0] & 0x80000000);
1466
1467                UInt32 counter = 0;
1468                while (counter < (1 << 12))
1469                {
1470                    if (IsStopped)
1471                        return;
1472
1473
1474                    ++counter;
1475
1476                    UInt32 q1 = q1a | (xrng64() & 0x7dfdf6be);
1477                    UInt32 m1 = Q[Qoff + 2] - q1;
1478                    m1 = RR(m1, 12) - FF(q1, Q[Qoff + 0], Q[Qoff - 1]) - tt1;
1479
1480                    UInt32 q16 = Q[Qoff + 16];
1481                    UInt32 q17 = tt17 + m1;
1482                    q17 = RL(q17, 5) + q16;
1483                    if (0x80000000 != ((q17 ^ q16) & 0x80008008)) { LogReturn(1); continue; }
1484                    if (0 != (q17 & 0x00020000)) { LogReturn(2); continue; }
1485
1486                    UInt32 q18 = GG(q17, q16, Q[Qoff + 15]) + tt18;
1487                    q18 = RL(q18, 9); q18 += q17;
1488                    if (0x80020000 != ((q18 ^ q17) & 0xa0020000)) { LogReturn(3); continue; }
1489
1490                    UInt32 q19 = GG(q18, q17, q16) + tt19;
1491                    q19 = RL(q19, 14); q19 += q18;
1492                    if (0 != (q19 & 0x80020000)) { LogReturn(4); continue; }
1493
1494                    UInt32 m0 = q1 - Q[Qoff + 0];
1495                    m0 = RR(m0, 7) - tt0;
1496
1497                    UInt32 q20 = GG(q19, q18, q17) + q16 + 0xe9b6c7aa + m0;
1498                    q20 = RL(q20, 20); q20 += q19;
1499                    if (0x00040000 != ((q20 ^ q19) & 0x80040000)) { LogReturn(5); continue; }
1500
1501                    Q[Qoff + 1] = q1;
1502                    Q[Qoff + 17] = q17;
1503                    Q[Qoff + 18] = q18;
1504                    Q[Qoff + 19] = q19;
1505                    Q[Qoff + 20] = q20;
1506
1507                    block[0] = m0;
1508                    block[1] = m1;
1509
1510                    MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
1511                    UInt32 q21 = GG(Q[Qoff + 20], Q[Qoff + 19], Q[Qoff + 18]) + Q[Qoff + 17] + 0xd62f105d + block[5];
1512                    q21 = RL(q21, 5); q21 += Q[Qoff + 20];
1513                    if (0 != ((q21 ^ Q[Qoff + 20]) & 0x80020000)) { LogReturn(6); continue; }
1514                    Q[Qoff + 21] = q21;
1515
1516                    counter = 0;
1517                    LogReturn(7);
1518                    break;
1519                }
1520                if (counter != 0)
1521                    { LogReturn(8); continue; }
1522
1523                UInt32 q9b = Q[Qoff + 9];
1524                UInt32 q10b = Q[Qoff + 10];
1525
1526                MD5_REVERSE_STEP(block, Q, 2, 0x242070db, 17);
1527                MD5_REVERSE_STEP(block, Q, 3, 0xc1bdceee, 22);
1528                MD5_REVERSE_STEP(block, Q, 4, 0xf57c0faf, 7);
1529                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
1530
1531                UInt32 tt10 = Q[Qoff + 7] + 0xffff5bb1;
1532                UInt32 tt22 = GG(Q[Qoff + 21], Q[Qoff + 20], Q[Qoff + 19]) + Q[Qoff + 18] + 0x02441453;
1533                UInt32 tt23 = Q[Qoff + 19] + 0xd8a1e681 + block[15];
1534                UInt32 tt24 = Q[Qoff + 20] + 0xe7d3fbc8 + block[4];
1535
1536                for (UInt32 k10 = 0; k10 < (1 << 4); ++k10)
1537                {
1538                    if (IsStopped)
1539                        return;
1540
1541
1542                    UInt32 q10 = q10b | (q9q10mask[k10] & 0x08000004);
1543                    UInt32 m10 = RR(Q[Qoff + 11] - q10, 17);
1544                    UInt32 q9 = q9b | (q9q10mask[k10] & 0x00004200);
1545
1546                    m10 -= FF(q10, q9, Q[Qoff + 8]) + tt10;
1547
1548                    UInt32 aa = Q[Qoff + 21];
1549                    UInt32 dd = tt22 + m10; dd = RL(dd, 9) + aa;
1550                    if (0 != (dd & 0x80000000)) { LogReturn(9); continue; }
1551
1552                    UInt32 bb = Q[Qoff + 20];
1553                    UInt32 cc = tt23 + GG(dd, aa, bb);
1554                    if (0 != (cc & 0x20000)) { LogReturn(10); continue; }
1555                    cc = RL(cc, 14) + dd;
1556                    if (0 != (cc & 0x80000000)) { LogReturn(11); continue; }
1557
1558                    bb = tt24 + GG(cc, dd, aa); bb = RL(bb, 20) + cc;
1559                    if (0 == (bb & 0x80000000)) { LogReturn(12); continue; }
1560
1561                    block[10] = m10;
1562                    Q[Qoff + 9] = q9;
1563                    Q[Qoff + 10] = q10;
1564                    MD5_REVERSE_STEP(block, Q, 13, 0xfd987193, 12);
1565
1566                    for (UInt32 k9 = 0; k9 < (1 << 10); ++k9)
1567                    {
1568                        if (IsStopped)
1569                            return;
1570
1571
1572                        UInt32 a = aa, b = bb, c = cc, d = dd;
1573                        Q[Qoff + 9] = q9 ^ q9mask[k9];
1574                        MD5_REVERSE_STEP(block, Q, 8, 0x698098d8, 7);
1575                        MD5_REVERSE_STEP(block, Q, 9, 0x8b44f7af, 12);
1576                        MD5_REVERSE_STEP(block, Q, 12, 0x6b901122, 7);
1577
1578                        MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
1579                        MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
1580                        MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
1581                        MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
1582                        MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
1583                        MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
1584                        MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
1585                        MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
1586                        MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
1587                        MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
1588
1589                        c += HH(d, a, b) + block[11] + 0x6d9d6122;
1590                        if (0 != (c & (1 << 15)))
1591                            { LogReturn(13); continue; }
1592                        c = (c << 16 | c >> 16) + d;
1593
1594                        MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
1595                        MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
1596                        MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
1597                        MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
1598                        MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
1599                        MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
1600                        MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
1601                        MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
1602                        MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
1603                        MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
1604                        MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
1605                        MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
1606                        MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
1607                        if (0 != ((b ^ d) & 0x80000000))
1608                            { LogReturn(14); continue; }
1609
1610                        MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
1611                        if (0 != ((a ^ c) >> 31)) { LogReturn(15); continue; }
1612                        MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
1613                        if (0 == ((b ^ d) >> 31)) { LogReturn(16); continue; }
1614                        MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
1615                        if (0 != ((a ^ c) >> 31)) { LogReturn(17); continue; }
1616                        MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
1617                        if (0 != ((b ^ d) >> 31)) { LogReturn(18); continue; }
1618                        MD5_STEP(II, ref a, b, c, d, block[12], 0x655b59c3, 6);
1619                        if (0 != ((a ^ c) >> 31)) { LogReturn(19); continue; }
1620                        MD5_STEP(II, ref d, a, b, c, block[3], 0x8f0ccc92, 10);
1621                        if (0 != ((b ^ d) >> 31)) { LogReturn(20); continue; }
1622                        MD5_STEP(II, ref c, d, a, b, block[10], 0xffeff47d, 15);
1623                        if (0 != ((a ^ c) >> 31)) { LogReturn(21); continue; }
1624                        MD5_STEP(II, ref b, c, d, a, block[1], 0x85845dd1, 21);
1625                        if (0 != ((b ^ d) >> 31)) { LogReturn(22); continue; }
1626                        MD5_STEP(II, ref  a, b, c, d, block[8], 0x6fa87e4f, 6);
1627                        if (0 != ((a ^ c) >> 31)) { LogReturn(23); continue; }
1628                        MD5_STEP(II, ref d, a, b, c, block[15], 0xfe2ce6e0, 10);
1629                        if (0 != ((b ^ d) >> 31)) { LogReturn(24); continue; }
1630                        MD5_STEP(II, ref c, d, a, b, block[6], 0xa3014314, 15);
1631                        if (0 != ((a ^ c) >> 31)) { LogReturn(25); continue; }
1632                        MD5_STEP(II, ref b, c, d, a, block[13], 0x4e0811a1, 21);
1633                        if (0 == ((b ^ d) >> 31)) { LogReturn(26); continue; }
1634                        MD5_STEP(II, ref a, b, c, d, block[4], 0xf7537e82, 6);
1635                        if (0 != ((a ^ c) >> 31)) { LogReturn(27); continue; }
1636                        MD5_STEP(II, ref d, a, b, c, block[11], 0xbd3af235, 10);
1637                        if (0 != ((b ^ d) >> 31)) { LogReturn(28); continue; }
1638                        MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
1639                        if (0 != ((a ^ c) >> 31)) { LogReturn(29); continue; }
1640                        MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
1641
1642                        //std::cout << "." << std::flush;
1643
1644                        UInt32[] block2 = new UInt32[16];
1645                        UInt32[] IV1 = new UInt32[4], IV2 = new UInt32[4];
1646                        for (int t = 0; t < 4; ++t)
1647                        {
1648                            IV1[t] = IV[t];
1649                            IV2[t] = IV[t] + ((UInt32)1 << 31);
1650                        }
1651                        IV2[1] -= (1 << 25);
1652                        IV2[2] -= (1 << 25);
1653                        IV2[3] -= (1 << 25);
1654
1655                        for (int t = 0; t < 16; ++t)
1656                            block2[t] = block[t];
1657                        block2[4] += (UInt32)1 << 31;
1658                        block2[11] += 1 << 15;
1659                        block2[14] += (UInt32)1 << 31;
1660
1661                        md5_compress(IV1, block);
1662                        md5_compress(IV2, block2);
1663                        if (IV2[0] == IV1[0] && IV2[1] == IV1[1] && IV2[2] == IV1[2] && IV2[3] == IV1[3])
1664                        {
1665                            LogReturn(30);
1666                            return;
1667                        }
1668
1669                        //if (IV2[0] != IV1[0])
1670                        //              std::cout << "!" << std::flush;
1671                    }
1672                }
1673            }
1674        }
1675
1676
1677        void find_block1_stevens_11(UInt32[] block, UInt32[] IV)
1678        {
1679            MatchProgressMax = 30;
1680            MatchProgress = 0;
1681
1682            UInt32[] Q = new UInt32[68];
1683            Q[0] = IV[0];
1684            Q[1] = IV[3];
1685            Q[2] = IV[2];
1686            Q[3] = IV[1];
1687
1688            UInt32[] q9q10mask = new UInt32[1 << 5];
1689            for (UInt32 k = 0; k < q9q10mask.Length; ++k)
1690                q9q10mask[k] = ((k << 5) ^ (k << 6) ^ (k << 7) ^ (k << 24) ^ (k << 27)) & 0x880002a0;
1691
1692            UInt32[] q9mask = new UInt32[1 << 9];
1693            for (UInt32 k = 0; k < q9mask.Length; ++k)
1694                q9mask[k] = ((k << 1) ^ (k << 3) ^ (k << 8) ^ (k << 12) ^ (k << 15) ^ (k << 18)) & 0x04710c12;
1695
1696            while (true)
1697            {
1698                if (IsStopped)
1699                    return;
1700
1701
1702                UInt32 aa1 = Q[Qoff] & 0x80000000;
1703
1704                Q[Qoff + 2] = (xrng64() & 0x75bef63e) | 0x0a410041 | aa1;
1705                Q[Qoff + 3] = (xrng64() & 0x10345614) | 0x0202a9e1 | (Q[Qoff + 2] & 0x84000002);
1706                Q[Qoff + 4] = (xrng64() & 0x00145400) | 0xe84ba909 | (Q[Qoff + 3] & 0x00000014);
1707                Q[Qoff + 5] = (xrng64() & 0x80000000) | 0x75e90b1d | (Q[Qoff + 4] & 0x00145400);
1708                Q[Qoff + 6] = 0x7c23ff5a | (Q[Qoff + 5] & 0x80000000);
1709                Q[Qoff + 7] = (xrng64() & 0x40000880) | 0x114bf41a;
1710                Q[Qoff + 8] = (xrng64() & 0x00002090) | 0xb352dd01;
1711                Q[Qoff + 9] = (xrng64() & 0x00044000) | 0x7a803124;
1712                Q[Qoff + 10] = (xrng64() & 0x00002000) | 0xf28a92c9 | (Q[Qoff + 9] & 0x00044000);
1713                Q[Qoff + 11] = (xrng64() & 0x128a8108) | 0xc5710ed7 | (Q[Qoff + 10] & 0x00002000);
1714                Q[Qoff + 12] = (xrng64() & 0x9edb8d7f) | 0x20003080 | (~Q[Qoff + 11] & 0x00200000);
1715                Q[Qoff + 13] = (xrng64() & 0x3efb1d77) | 0x4004c008 | (Q[Qoff + 12] & 0x80000000);
1716                Q[Qoff + 14] = (xrng64() & 0x1fff5d77) | 0x0000a288;
1717                Q[Qoff + 15] = (xrng64() & 0x1efe7ff7) | 0x20008000 | (~Q[Qoff + 14] & 0x00010000);
1718                Q[Qoff + 16] = (xrng64() & 0x1ffdffff) | 0x20000000 | (~Q[Qoff + 15] & 0x40020000);
1719
1720                MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
1721                MD5_REVERSE_STEP(block, Q, 6, 0xa8304613, 17);
1722                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
1723                MD5_REVERSE_STEP(block, Q, 11, 0x895cd7be, 22);
1724                MD5_REVERSE_STEP(block, Q, 14, 0xa679438e, 17);
1725                MD5_REVERSE_STEP(block, Q, 15, 0x49b40821, 22);
1726
1727                UInt32 tt17 = GG(Q[Qoff + 16], Q[Qoff + 15], Q[Qoff + 14]) + Q[Qoff + 13] + 0xf61e2562;
1728                UInt32 tt18 = Q[Qoff + 14] + 0xc040b340 + block[6];
1729                UInt32 tt19 = Q[Qoff + 15] + 0x265e5a51 + block[11];
1730
1731                UInt32 tt0 = FF(Q[Qoff + 0], Q[Qoff - 1], Q[Qoff - 2]) + Q[Qoff - 3] + 0xd76aa478;
1732                UInt32 tt1 = Q[Qoff - 2] + 0xe8c7b756;
1733
1734                UInt32 q1a = 0x02000861 ^ (Q[Qoff + 0] & 0x80000020);
1735
1736                UInt32 counter = 0;
1737                while (counter < (1 << 12))
1738                {
1739                    if (IsStopped)
1740                        return;
1741
1742
1743                    ++counter;
1744
1745                    UInt32 q1 = q1a | (xrng64() & 0x7dfff79e);
1746                    UInt32 m1 = Q[Qoff + 2] - q1;
1747                    m1 = RR(m1, 12) - FF(q1, Q[Qoff + 0], Q[Qoff - 1]) - tt1;
1748
1749                    UInt32 q16 = Q[Qoff + 16];
1750                    UInt32 q17 = tt17 + m1;
1751                    q17 = RL(q17, 5) + q16;
1752                    if (0x40000000 != ((q17 ^ q16) & 0xc0008008)) { LogReturn(1); continue; }
1753                    if (0 != (q17 & 0x00020000)) { LogReturn(2); continue; }
1754
1755                    UInt32 q18 = GG(q17, q16, Q[Qoff + 15]) + tt18;
1756                    q18 = RL(q18, 9); q18 += q17;
1757                    if (0x80020000 != ((q18 ^ q17) & 0xa0020000)) { LogReturn(3); continue; }
1758
1759                    UInt32 q19 = GG(q18, q17, q16) + tt19;
1760                    q19 = RL(q19, 14); q19 += q18;
1761                    if (0x80000000 != (q19 & 0x80020000)) { LogReturn(4); continue; }
1762
1763                    UInt32 m0 = q1 - Q[Qoff + 0];
1764                    m0 = RR(m0, 7) - tt0;
1765
1766                    UInt32 q20 = GG(q19, q18, q17) + q16 + 0xe9b6c7aa + m0;
1767                    q20 = RL(q20, 20); q20 += q19;
1768                    if (0x00040000 != ((q20 ^ q19) & 0x80040000)) { LogReturn(5); continue; }
1769
1770                    Q[Qoff + 1] = q1;
1771                    Q[Qoff + 17] = q17;
1772                    Q[Qoff + 18] = q18;
1773                    Q[Qoff + 19] = q19;
1774                    Q[Qoff + 20] = q20;
1775
1776                    block[0] = m0;
1777                    block[1] = m1;
1778
1779                    MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
1780                    UInt32 q21 = GG(Q[Qoff + 20], Q[Qoff + 19], Q[Qoff + 18]) + Q[Qoff + 17] + 0xd62f105d + block[5];
1781                    q21 = RL(q21, 5); q21 += Q[Qoff + 20];
1782                    if (0 != ((q21 ^ Q[Qoff + 20]) & 0x80020000)) { LogReturn(6); continue; }
1783
1784                    Q[Qoff + 21] = q21;
1785
1786                    counter = 0;
1787                    LogReturn(7);
1788                    break;
1789                }
1790                if (counter != 0)
1791                    { LogReturn(8); continue; }
1792
1793                UInt32 q9b = Q[Qoff + 9];
1794                UInt32 q10b = Q[Qoff + 10];
1795
1796                MD5_REVERSE_STEP(block, Q, 2, 0x242070db, 17);
1797                MD5_REVERSE_STEP(block, Q, 3, 0xc1bdceee, 22);
1798                MD5_REVERSE_STEP(block, Q, 4, 0xf57c0faf, 7);
1799                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
1800
1801                UInt32 tt10 = Q[Qoff + 7] + 0xffff5bb1;
1802                UInt32 tt22 = GG(Q[Qoff + 21], Q[Qoff + 20], Q[Qoff + 19]) + Q[Qoff + 18] + 0x02441453;
1803                UInt32 tt23 = Q[Qoff + 19] + 0xd8a1e681 + block[15];
1804                UInt32 tt24 = Q[Qoff + 20] + 0xe7d3fbc8 + block[4];
1805
1806                for (UInt32 k10 = 0; k10 < (1 << 5); ++k10)
1807                {
1808                    if (IsStopped)
1809                        return;
1810
1811
1812                    UInt32 q10 = q10b | (q9q10mask[k10] & 0x08000040);
1813                    UInt32 m10 = RR(Q[Qoff + 11] - q10, 17);
1814                    UInt32 q9 = q9b | (q9q10mask[k10] & 0x80000280);
1815
1816                    m10 -= FF(q10, q9, Q[Qoff + 8]) + tt10;
1817
1818                    UInt32 aa = Q[Qoff + 21];
1819                    UInt32 dd = tt22 + m10; dd = RL(dd, 9) + aa;
1820                    if (0 == (dd & 0x80000000)) { LogReturn(9); continue; }
1821
1822                    UInt32 bb = Q[Qoff + 20];
1823                    UInt32 cc = tt23 + GG(dd, aa, bb);
1824                    if (0 != (cc & 0x20000)) { LogReturn(10); continue; }
1825                    cc = RL(cc, 14) + dd;
1826                    if (0 != (cc & 0x80000000)) { LogReturn(11); continue; }
1827
1828                    bb = tt24 + GG(cc, dd, aa); bb = RL(bb, 20) + cc;
1829                    if (0 == (bb & 0x80000000)) { LogReturn(12); continue; }
1830
1831                    block[10] = m10;
1832                    Q[Qoff + 9] = q9;
1833                    Q[Qoff + 10] = q10;
1834                    MD5_REVERSE_STEP(block, Q, 13, 0xfd987193, 12);
1835
1836                    for (UInt32 k9 = 0; k9 < (1 << 9); ++k9)
1837                    {
1838                        if (IsStopped)
1839                            return;
1840
1841
1842                        UInt32 a = aa, b = bb, c = cc, d = dd;
1843                        Q[Qoff + 9] = q9 ^ q9mask[k9];
1844                        MD5_REVERSE_STEP(block, Q, 8, 0x698098d8, 7);
1845                        MD5_REVERSE_STEP(block, Q, 9, 0x8b44f7af, 12);
1846                        MD5_REVERSE_STEP(block, Q, 12, 0x6b901122, 7);
1847
1848                        MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
1849                        MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
1850                        MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
1851                        MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
1852                        MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
1853                        MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
1854                        MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
1855                        MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
1856                        MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
1857                        MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
1858
1859                        c += HH(d, a, b) + block[11] + 0x6d9d6122;
1860                        if (0 != (c & (1 << 15)))
1861                            { LogReturn(13); continue; }
1862                        c = (c << 16 | c >> 16) + d;
1863
1864                        MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
1865                        MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
1866                        MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
1867                        MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
1868                        MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
1869                        MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
1870                        MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
1871                        MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
1872                        MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
1873                        MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
1874                        MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
1875                        MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
1876                        MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
1877                        if (0 != ((b ^ d) & 0x80000000))
1878                            { LogReturn(14); continue; }
1879
1880                        MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
1881                        if (0 != ((a ^ c) >> 31)) { LogReturn(15); continue; }
1882                        MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
1883                        if (0 == ((b ^ d) >> 31)) { LogReturn(16); continue; }
1884                        MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
1885                        if (0 != ((a ^ c) >> 31)) { LogReturn(17); continue; }
1886                        MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
1887                        if (0 != ((b ^ d) >> 31)) { LogReturn(18); continue; }
1888                        MD5_STEP(II, ref a, b, c, d, block[12], 0x655b59c3, 6);
1889                        if (0 != ((a ^ c) >> 31)) { LogReturn(19); continue; }
1890                        MD5_STEP(II, ref d, a, b, c, block[3], 0x8f0ccc92, 10);
1891                        if (0 != ((b ^ d) >> 31)) { LogReturn(20); continue; }
1892                        MD5_STEP(II, ref c, d, a, b, block[10], 0xffeff47d, 15);
1893                        if (0 != ((a ^ c) >> 31)) { LogReturn(21); continue; }
1894                        MD5_STEP(II, ref b, c, d, a, block[1], 0x85845dd1, 21);
1895                        if (0 != ((b ^ d) >> 31)) { LogReturn(22); continue; }
1896                        MD5_STEP(II, ref a, b, c, d, block[8], 0x6fa87e4f, 6);
1897                        if (0 != ((a ^ c) >> 31)) { LogReturn(23); continue; }
1898                        MD5_STEP(II, ref d, a, b, c, block[15], 0xfe2ce6e0, 10);
1899                        if (0 != ((b ^ d) >> 31)) { LogReturn(24); continue; }
1900                        MD5_STEP(II, ref c, d, a, b, block[6], 0xa3014314, 15);
1901                        if (0 != ((a ^ c) >> 31)) { LogReturn(25); continue; }
1902                        MD5_STEP(II, ref  b, c, d, a, block[13], 0x4e0811a1, 21);
1903                        if (0 == ((b ^ d) >> 31)) { LogReturn(26); continue; }
1904                        MD5_STEP(II, ref  a, b, c, d, block[4], 0xf7537e82, 6);
1905                        if (0 != ((a ^ c) >> 31)) { LogReturn(27); continue; }
1906                        MD5_STEP(II, ref  d, a, b, c, block[11], 0xbd3af235, 10);
1907                        if (0 != ((b ^ d) >> 31)) { LogReturn(28); continue; }
1908                        MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
1909                        if (0 != ((a ^ c) >> 31)) { LogReturn(29); continue; }
1910                        MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
1911
1912                        //std::cout << "." << std::flush;
1913
1914                        UInt32[] block2 = new UInt32[16];
1915                        UInt32[] IV1 = new UInt32[4], IV2 = new UInt32[4];
1916                        for (int t = 0; t < 4; ++t)
1917                        {
1918                            IV1[t] = IV[t];
1919                            IV2[t] = IV[t] + ((UInt32)1 << 31);
1920                        }
1921                        IV2[1] -= (1 << 25);
1922                        IV2[2] -= (1 << 25);
1923                        IV2[3] -= (1 << 25);
1924
1925                        for (int t = 0; t < 16; ++t)
1926                            block2[t] = block[t];
1927                        block2[4] += (UInt32)1 << 31;
1928                        block2[11] += 1 << 15;
1929                        block2[14] += (UInt32)1 << 31;
1930
1931                        md5_compress(IV1, block);
1932                        md5_compress(IV2, block2);
1933                        if (IV2[0] == IV1[0] && IV2[1] == IV1[1] && IV2[2] == IV1[2] && IV2[3] == IV1[3])
1934                        {
1935                            LogReturn(30);
1936                            return;
1937                        }
1938
1939                        //if (IV2[0] != IV1[0])
1940                        //              std::cout << "!" << std::flush;
1941                    }
1942                }
1943            }
1944        }
1945
1946
1947        void find_block1_wang(UInt32[] block, UInt32[] IV)
1948        {
1949            MatchProgressMax = 30;
1950            MatchProgress = 0;
1951
1952            UInt32[] Q = new UInt32[68];
1953            Q[0] = IV[0];
1954            Q[1] = IV[3];
1955            Q[2] = IV[2];
1956            Q[3] = IV[1];
1957
1958            UInt32[] q4mask = new UInt32[1 << 6];
1959            for (UInt32 k = 0; k < q4mask.Length; ++k)
1960                q4mask[k] = ((k << 13) ^ (k << 19)) & 0x01c0e000;
1961
1962            UInt32[] q9mask = new UInt32[1 << 5], q10mask = new UInt32[1 << 5];
1963            for (UInt32 k = 0; k < q9mask.Length; ++k)
1964            {
1965                UInt32 msk = (k << 5) ^ (k << 13) ^ (k << 17) ^ (k << 24);
1966                q9mask[k] = msk & 0x00084000;
1967                q10mask[k] = msk & 0x18000020;
1968            }
1969
1970            UInt32[] q9mask2 = new UInt32[1 << 10];
1971            for (UInt32 k = 0; k < q9mask2.Length; ++k)
1972                q9mask2[k] = ((k << 1) ^ (k << 7) ^ (k << 14) ^ (k << 15) ^ (k << 22)) & 0x6074041c;
1973
1974            while (true)
1975            {
1976                if (IsStopped)
1977                    return;
1978
1979
1980                UInt32 aa1 = Q[Qoff] & 0x80000000;
1981                UInt32 bb1 = 0x80000000 ^ aa1;
1982
1983                Q[Qoff + 2] = (xrng64() & 0x71de7799) | 0x0c008840 | bb1;
1984                Q[Qoff + 3] = (xrng64() & 0x01c06601) | 0x3e1f0966 | (Q[Qoff + 2] & 0x80000018);
1985                Q[Qoff + 4] = 0x3a040010 | (Q[Qoff + 3] & 0x80000601);
1986                Q[Qoff + 5] = (xrng64() & 0x03c0e000) | 0x482f0e50 | aa1;
1987                Q[Qoff + 6] = (xrng64() & 0x600c0000) | 0x05e2ec56 | aa1;
1988                Q[Qoff + 7] = (xrng64() & 0x604c203e) | 0x16819e01 | bb1 | (Q[Qoff + 6] & 0x01000000);
1989                Q[Qoff + 8] = (xrng64() & 0x604c7c1c) | 0x043283e0 | (Q[Qoff + 7] & 0x80000002);
1990                Q[Qoff + 9] = (xrng64() & 0x00002800) | 0x1c0101c1 | (Q[Qoff + 8] & 0x80001000);
1991                Q[Qoff + 10] = 0x078bcbc0 | bb1;
1992                Q[Qoff + 11] = (xrng64() & 0x07800000) | 0x607dc7df | bb1;
1993                Q[Qoff + 12] = (xrng64() & 0x00f00f7f) | 0x00081080 | (Q[Qoff + 11] & 0xe7000000);
1994                Q[Qoff + 13] = (xrng64() & 0x00701f77) | 0x3f0fe008 | aa1;
1995                Q[Qoff + 14] = (xrng64() & 0x00701f77) | 0x408be088 | aa1;
1996                Q[Qoff + 15] = (xrng64() & 0x00ff3ff7) | 0x7d000000;
1997                Q[Qoff + 16] = (xrng64() & 0x4ffdffff) | 0x20000000 | (~Q[Qoff + 15] & 0x00020000);
1998
1999                MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
2000                MD5_REVERSE_STEP(block, Q, 6, 0xa8304613, 17);
2001                MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
2002                MD5_REVERSE_STEP(block, Q, 11, 0x895cd7be, 22);
2003                MD5_REVERSE_STEP(block, Q, 14, 0xa679438e, 17);
2004                MD5_REVERSE_STEP(block, Q, 15, 0x49b40821, 22);
2005
2006                UInt32 tt17 = GG(Q[Qoff + 16], Q[Qoff + 15], Q[Qoff + 14]) + Q[Qoff + 13] + 0xf61e2562;
2007                UInt32 tt18 = Q[Qoff + 14] + 0xc040b340 + block[6];
2008                UInt32 tt19 = Q[Qoff + 15] + 0x265e5a51 + block[11];
2009
2010                UInt32 tt0 = FF(Q[Qoff + 0], Q[Qoff - 1], Q[Qoff - 2]) + Q[Qoff - 3] + 0xd76aa478;
2011                UInt32 tt1 = Q[Qoff - 2] + 0xe8c7b756;
2012
2013                UInt32 q1a = 0x04200040 | (Q[Qoff + 2] & 0xf01e1080);
2014
2015                UInt32 counter = 0;
2016                while (counter < (1 << 12))
2017                {
2018                    if (IsStopped)
2019                        return;
2020
2021
2022                    ++counter;
2023
2024                    UInt32 q1 = q1a | (xrng64() & 0x01c0e71f);
2025                    UInt32 m1 = Q[Qoff + 2] - q1;
2026                    m1 = RR(m1, 12) - FF(q1, Q[Qoff + 0], Q[Qoff - 1]) - tt1;
2027
2028                    UInt32 q16 = Q[Qoff + 16];
2029                    UInt32 q17 = tt17 + m1;
2030                    q17 = RL(q17, 5) + q16;
2031                    if (0x40000000 != ((q17 ^ q16) & 0xc0008008)) { LogReturn(1); continue; }
2032                    if (0 != (q17 & 0x00020000)) { LogReturn(2); continue; }
2033
2034                    UInt32 q18 = GG(q17, q16, Q[Qoff + 15]) + tt18;
2035                    q18 = RL(q18, 9); q18 += q17;
2036                    if (0x00020000 != ((q18 ^ q17) & 0xa0020000)) { LogReturn(3); continue; }
2037
2038                    UInt32 q19 = GG(q18, q17, q16) + tt19;
2039                    q19 = RL(q19, 14); q19 += q18;
2040                    if (0 != (q19 & 0x80020000)) { LogReturn(4); continue; }
2041
2042                    UInt32 m0 = q1 - Q[Qoff + 0];
2043                    m0 = RR(m0, 7) - tt0;
2044
2045                    UInt32 q20 = GG(q19, q18, q17) + q16 + 0xe9b6c7aa + m0;
2046                    q20 = RL(q20, 20); q20 += q19;
2047                    if (0x00040000 != ((q20 ^ q19) & 0x80040000)) { LogReturn(5); continue; }
2048
2049                    Q[Qoff + 1] = q1;
2050                    Q[Qoff + 17] = q17;
2051                    Q[Qoff + 18] = q18;
2052                    Q[Qoff + 19] = q19;
2053                    Q[Qoff + 20] = q20;
2054
2055                    block[0] = m0;
2056                    block[1] = m1;
2057                    MD5_REVERSE_STEP(block, Q, 2, 0x242070db, 17);
2058
2059                    counter = 0;
2060                    LogReturn(6);
2061                    break;
2062                }
2063                if (counter != 0)
2064                    { LogReturn(7); continue; }
2065
2066                UInt32 q4b = Q[Qoff + 4];
2067                UInt32 q9b = Q[Qoff + 9];
2068                UInt32 q10b = Q[Qoff + 10];
2069                UInt32 tt21 = GG(Q[Qoff + 20], Q[Qoff + 19], Q[Qoff + 18]) + Q[Qoff + 17] + 0xd62f105d;
2070
2071                counter = 0;
2072                while (counter < (1 << 6))
2073                {
2074                    if (IsStopped)
2075                        return;
2076
2077
2078                    Q[Qoff + 4] = q4b ^ q4mask[counter];
2079                    ++counter;
2080                    MD5_REVERSE_STEP(block, Q, 5, 0x4787c62a, 12);
2081                    UInt32 q21 = tt21 + block[5];
2082                    q21 = RL(q21, 5); q21 += Q[Qoff + 20];
2083                    if (0 != ((q21 ^ Q[Qoff + 20]) & 0x80020000)) { LogReturn(8); continue; }
2084
2085                    Q[Qoff + 21] = q21;
2086                    MD5_REVERSE_STEP(block, Q, 3, 0xc1bdceee, 22);
2087                    MD5_REVERSE_STEP(block, Q, 4, 0xf57c0faf, 7);
2088                    MD5_REVERSE_STEP(block, Q, 7, 0xfd469501, 22);
2089
2090                    UInt32 tt10 = Q[Qoff + 7] + 0xffff5bb1;
2091                    UInt32 tt22 = GG(Q[Qoff + 21], Q[Qoff + 20], Q[Qoff + 19]) + Q[Qoff + 18] + 0x02441453;
2092                    UInt32 tt23 = Q[Qoff + 19] + 0xd8a1e681 + block[15];
2093                    UInt32 tt24 = Q[Qoff + 20] + 0xe7d3fbc8 + block[4];
2094
2095                    UInt32 counter2 = 0;
2096                    while (counter2 < (1 << 5))
2097                    {
2098                        if (IsStopped)
2099                            return;
2100
2101
2102                        UInt32 q10 = q10b ^ q10mask[counter2];
2103                        UInt32 m10 = RR(Q[Qoff + 11] - q10, 17);
2104                        UInt32 q9 = q9b ^ q9mask[counter2];
2105                        ++counter2;
2106
2107                        m10 -= FF(q10, q9, Q[Qoff + 8]) + tt10;
2108
2109                        UInt32 aa = Q[Qoff + 21];
2110                        UInt32 dd = tt22 + m10; dd = RL(dd, 9) + aa;
2111                        if (0 != (dd & 0x80000000)) { LogReturn(9); continue; }
2112
2113                        UInt32 bb = Q[Qoff + 20];
2114                        UInt32 cc = tt23 + GG(dd, aa, bb);
2115                        if (0 != (cc & 0x20000)) { LogReturn(10); continue; }
2116                        cc = RL(cc, 14) + dd;
2117                        if (0 != (cc & 0x80000000)) { LogReturn(11); continue; }
2118
2119                        bb = tt24 + GG(cc, dd, aa); bb = RL(bb, 20) + cc;
2120                        if (0 == (bb & 0x80000000)) { LogReturn(12); continue; }
2121
2122                        block[10] = m10;
2123                        Q[Qoff + 9] = q9;
2124                        Q[Qoff + 10] = q10;
2125                        MD5_REVERSE_STEP(block, Q, 13, 0xfd987193, 12);
2126
2127                        for (UInt32 k9 = 0; k9 < (1 << 10); )
2128                        {
2129                            if (IsStopped)
2130                                return;
2131
2132
2133                            UInt32 a = aa, b = bb, c = cc, d = dd;
2134                            Q[Qoff + 9] = q9 ^ q9mask2[k9]; ++k9;
2135                            MD5_REVERSE_STEP(block, Q, 8, 0x698098d8, 7);
2136                            MD5_REVERSE_STEP(block, Q, 9, 0x8b44f7af, 12);
2137                            MD5_REVERSE_STEP(block, Q, 12, 0x6b901122, 7);
2138
2139                            MD5_STEP(GG, ref a, b, c, d, block[9], 0x21e1cde6, 5);
2140                            MD5_STEP(GG, ref d, a, b, c, block[14], 0xc33707d6, 9);
2141                            MD5_STEP(GG, ref c, d, a, b, block[3], 0xf4d50d87, 14);
2142                            MD5_STEP(GG, ref b, c, d, a, block[8], 0x455a14ed, 20);
2143                            MD5_STEP(GG, ref a, b, c, d, block[13], 0xa9e3e905, 5);
2144                            MD5_STEP(GG, ref d, a, b, c, block[2], 0xfcefa3f8, 9);
2145                            MD5_STEP(GG, ref c, d, a, b, block[7], 0x676f02d9, 14);
2146                            MD5_STEP(GG, ref b, c, d, a, block[12], 0x8d2a4c8a, 20);
2147                            MD5_STEP(HH, ref a, b, c, d, block[5], 0xfffa3942, 4);
2148                            MD5_STEP(HH, ref d, a, b, c, block[8], 0x8771f681, 11);
2149
2150                            c += HH(d, a, b) + block[11] + 0x6d9d6122;
2151                            if (0 == (c & (1 << 15)))
2152                                { LogReturn(13); continue; }
2153                            c = (c << 16 | c >> 16) + d;
2154
2155                            MD5_STEP(HH, ref b, c, d, a, block[14], 0xfde5380c, 23);
2156                            MD5_STEP(HH, ref a, b, c, d, block[1], 0xa4beea44, 4);
2157                            MD5_STEP(HH, ref d, a, b, c, block[4], 0x4bdecfa9, 11);
2158                            MD5_STEP(HH, ref c, d, a, b, block[7], 0xf6bb4b60, 16);
2159                            MD5_STEP(HH, ref b, c, d, a, block[10], 0xbebfbc70, 23);
2160                            MD5_STEP(HH, ref a, b, c, d, block[13], 0x289b7ec6, 4);
2161                            MD5_STEP(HH, ref d, a, b, c, block[0], 0xeaa127fa, 11);
2162                            MD5_STEP(HH, ref c, d, a, b, block[3], 0xd4ef3085, 16);
2163                            MD5_STEP(HH, ref b, c, d, a, block[6], 0x04881d05, 23);
2164                            MD5_STEP(HH, ref a, b, c, d, block[9], 0xd9d4d039, 4);
2165                            MD5_STEP(HH, ref d, a, b, c, block[12], 0xe6db99e5, 11);
2166                            MD5_STEP(HH, ref c, d, a, b, block[15], 0x1fa27cf8, 16);
2167                            MD5_STEP(HH, ref b, c, d, a, block[2], 0xc4ac5665, 23);
2168                            if (0 != ((b ^ d) & 0x80000000))
2169                                { LogReturn(14); continue; }
2170
2171                            MD5_STEP(II, ref a, b, c, d, block[0], 0xf4292244, 6);
2172                            if (0 != ((a ^ c) >> 31)) { LogReturn(15); continue; }
2173                            MD5_STEP(II, ref d, a, b, c, block[7], 0x432aff97, 10);
2174                            if (0 == ((b ^ d) >> 31)) { LogReturn(16); continue; }
2175                            MD5_STEP(II, ref c, d, a, b, block[14], 0xab9423a7, 15);
2176                            if (0 != ((a ^ c) >> 31)) { LogReturn(17); continue; }
2177                            MD5_STEP(II, ref b, c, d, a, block[5], 0xfc93a039, 21);
2178                            if (0 != ((b ^ d) >> 31)) { LogReturn(18); continue; }
2179                            MD5_STEP(II, ref a, b, c, d, block[12], 0x655b59c3, 6);
2180                            if (0 != ((a ^ c) >> 31)) { LogReturn(19); continue; }
2181                            MD5_STEP(II, ref d, a, b, c, block[3], 0x8f0ccc92, 10);
2182                            if (0 != ((b ^ d) >> 31)) { LogReturn(20); continue; }
2183                            MD5_STEP(II, ref c, d, a, b, block[10], 0xffeff47d, 15);
2184                            if (0 != ((a ^ c) >> 31)) { LogReturn(21); continue; }
2185                            MD5_STEP(II, ref b, c, d, a, block[1], 0x85845dd1, 21);
2186                            if (0 != ((b ^ d) >> 31)) { LogReturn(22); continue; }
2187                            MD5_STEP(II, ref a, b, c, d, block[8], 0x6fa87e4f, 6);
2188                            if (0 != ((a ^ c) >> 31)) { LogReturn(23); continue; }
2189                            MD5_STEP(II, ref d, a, b, c, block[15], 0xfe2ce6e0, 10);
2190                            if (0 != ((b ^ d) >> 31)) { LogReturn(24); continue; }
2191                            MD5_STEP(II, ref  c, d, a, b, block[6], 0xa3014314, 15);
2192                            if (0 != ((a ^ c) >> 31)) { LogReturn(25); continue; }
2193                            MD5_STEP(II, ref  b, c, d, a, block[13], 0x4e0811a1, 21);
2194                            if (0 == ((b ^ d) >> 31)) { LogReturn(26); continue; }
2195                            MD5_STEP(II, ref a, b, c, d, block[4], 0xf7537e82, 6);
2196                            if (0 != ((a ^ c) >> 31)) { LogReturn(27); continue; }
2197                            MD5_STEP(II, ref d, a, b, c, block[11], 0xbd3af235, 10);
2198                            if (0 != ((b ^ d) >> 31)) { LogReturn(28); continue; }
2199                            MD5_STEP(II, ref c, d, a, b, block[2], 0x2ad7d2bb, 15);
2200                            if (0 != ((a ^ c) >> 31)) { LogReturn(29); continue; }
2201                            MD5_STEP(II, ref b, c, d, a, block[9], 0xeb86d391, 21);
2202
2203                            //std::cout << "." << std::flush;
2204
2205                            UInt32[] block2 = new UInt32[16];
2206                            UInt32[] IV1 = new UInt32[4], IV2 = new UInt32[4];
2207                            for (int t = 0; t < 4; ++t)
2208                            {
2209                                IV1[t] = IV[t];
2210                                IV2[t] = IV[t] + ((UInt32)1 << 31);
2211                            }
2212                            IV2[1] += (1 << 25);
2213                            IV2[2] += (1 << 25);
2214                            IV2[3] += (1 << 25);
2215
2216                            for (int t = 0; t < 16; ++t)
2217                                block2[t] = block[t];
2218                            block2[4] += (UInt32)1 << 31;
2219                            block2[11] -= 1 << 15;
2220                            block2[14] += (UInt32)1 << 31;
2221
2222                            md5_compress(IV1, block);
2223                            md5_compress(IV2, block2);
2224                            if (IV2[0] == IV1[0] && IV2[1] == IV1[1] && IV2[2] == IV1[2] && IV2[3] == IV1[3])
2225                            {
2226                                LogReturn(30);
2227                                return;
2228                            }
2229
2230                            //if (IV2[0] != IV1[0])
2231                            //  std::cout << "!" << std::flush;
2232                        }
2233                    }
2234                }
2235            }
2236        }
2237
2238        private bool IsStopped { get; set; }
2239
2240        protected override void PerformStop()
2241        {
2242            IsStopped = true;
2243        }
2244    }
2245}
Note: See TracBrowser for help on using the repository browser.