private void FindCollision() { try { //заведем константы: const int cMinTextLength = 1, //минимальная длина случайной строки cMaxTextLength = 512, //максимальная - чтобы не улететь в переполнение cNextAttemptCount = 300; //через каждое такое количество попыток - производим изменение длины строки //зафиксируем копии: string mainText = String.Copy(_MainText); Sha1Hash mainHash = _MainHash.Clone(); //возьмем копию //заведем необходимые переменные: Sha1Alg sha1Add = new Sha1Alg(); //заведем отдельный класс, чтобы не заморачиваться с локами sha1Add.HashBitCount = _Sha1Main.HashBitCount; //устанавливаем количество значимых бит Sha1Hash addHash = new Sha1Hash(); //тут будет хеш случайных строк string randomText = String.Empty; //тут будет случайная строка Stopwatch hashSW = new Stopwatch(); //время поиска int attemptCount = 0; //количество попыток bool isFinded = false; //нашли\не нашли bool upWay = true; //идея в том, чтобы до определенного значения увеличивать длину строки, по достижении его - уменьшать. и потом по-новой int oldNextAttemptValue = 0; int textLength = cMinTextLength; //установим начальную длину случайной строки hashSW.Start(); //запускаем замер времени поиска //поиск: while (!_NeedStopSearch && !isFinded) { randomText = GetRandomString(textLength); //получаем случайную строку addHash = sha1Add.GetHash(randomText); //если усеченные хеши совпали и при этом не совпали строки, от которых они взяты if (sha1Add.Compare(mainHash, addHash) && mainText.IndexOf(randomText) < 0) { isFinded = true; //коллизия найдена } if (attemptCount++ / cNextAttemptCount > oldNextAttemptValue) //если пересекли очередной рубеж для изменения длины строки { oldNextAttemptValue = attemptCount / cNextAttemptCount; if (upWay) //если сейчас режим увеличения случайной строки { if (++textLength >= cMaxTextLength) { upWay = !upWay; //меняем направление } } else { if (--textLength <= cMinTextLength) { upWay = !upWay; //меняем направление } } //для подобия обратной связи - обновляем показатели времени поиска и количества попыток //надо конечно делать через таймер, но и это лучше чем ничего: Invoke(new Action(delegate() { lCollisionTime.Text = hashSW.Elapsed.ToString(); lAttemptCount.Text = attemptCount.ToString(); })); } } hashSW.Stop(); //выходим в основной поток, переводим в состояние завершения поиска Invoke(new Action(delegate() { bFindCollision.Tag = true; bFindCollision.Text = Str.cFindCollisionText; if (isFinded) //если нас не прервали и коллизия найдена { tbCollisionText.Text = randomText; lCollisionHash.Text = "0x" + addHash.Text; lCollisionTime.Text = hashSW.Elapsed.ToString(); lTruncCollisionHash.Text = "0x" + _Sha1Main.GetTruncateHash(addHash.Value).Text; lAttemptCount.Text = attemptCount.ToString(); ShowStatusMessage(Str.cCollisionFinded); } })); } catch { //в releise-версии тут нечего ловить, т.к. при завершении потока постоянно будут сообщения } }