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

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

+ MD5Collider: Added quick watch presentation

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