/// <summary> /// Первичная инициализация /// </summary> private void Init() { try { _Sha1Main = new Sha1Alg(); //класс, через который будем работать с хешами в осн.потоке tbHashBitCount.Text = HashBitCount.ToString(); HashBitCount = HashBitCount; bFindCollision.Tag = true; //устанавливаем начальное состояние кнопки в "Найти коллизию" bFindCollision.Text = Str.cFindCollisionText; //Начальный текст на кнопке CollisionViewReset(); _DefaultStatusStripHeight = statusStrip1.Height; txtTip.Multiline = true; txtTip.WordWrap = true; txtTip.Font = statusLabel.Font; //такой же шрифт как и у лейблы statusStrip1.BackColor = this.BackColor; } catch (Exception ex) { ShowStatusMessage(Str.cExceptionHappened + ex.Message, true); } }
void OnBCalcSha1Click(object sender, EventArgs e) { try { ShowStatusMessage(Str.cHashCalculating); if (_Sha1Main == null) { _Sha1Main = new Sha1Alg(); } //получаем количество значимых бит от пользователя и если оно корректно устанавливаем его, //иначе - работаем с количеством бит по умолчанию int userHashBitCount; if (int.TryParse(tbHashBitCount.Text, out userHashBitCount) && userHashBitCount >= cMinHashBitCount && userHashBitCount <= cMaxHashBitCount) { HashBitCount = userHashBitCount; } else { tbHashBitCount.Text = HashBitCount.ToString(); } Stopwatch hashSW = new Stopwatch(); hashSW.Start(); //запускаем замер времени выполнения _MainHash = _Sha1Main.GetHash(tbInputText.Text); //вычисляем хеш от содержимого текстбокса hashSW.Stop(); //останавливаем, независимо от результата if (_MainHash != null && !String.IsNullOrEmpty(_MainHash.Text)) { lSha1Hash.Text = "0x" + _MainHash.Text; lTruncSha1Hash.Text = "0x" + _Sha1Main.GetTruncateHash(_MainHash.Value).Text; lSha1Time.Text = hashSW.Elapsed.ToString(); _MainText = tbInputText.Text; _Sha1Calculated = true; //указываем что в _Sha1Main посчитанный хеш и можно искать коллизии ShowStatusMessage(Str.cHashCalcEnd); } else { ShowStatusMessage(Str.cCantCalcHash, true); } } catch (Exception ex) { ShowStatusMessage(Str.cExceptionHappened + ex.Message, true); } }
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-версии тут нечего ловить, т.к. при завершении потока постоянно будут сообщения } }