예제 #1
0
        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-версии тут нечего ловить, т.к. при завершении потока постоянно будут сообщения
            }
        }