void PollardPMinusOneEntry(long number, long b) { try { long a = 2, p; for (int j = 2; j <= b; j++) { a = CryptographyMath.PowerSearch(a, j, number); } p = CryptographyMath.ExtendedGCD(a - 1, number)[0]; if (p != 1 || p != number) { MessageBox.Show(p.ToString() + " - делитель " + number.ToString()); } else { MessageBox.Show("Увы, попробуй ещё раз"); } } catch (Exception ex) { MessageBox.Show("Ошибка:" + ex.Message); } }
void RabinMillerEntry(long number) { try { long baseNum = (long)rnd.Next(2, (int)number - 2); long s = 0; // степень двойки long t = 0; // нечетное число, n-1 = 2^s*t bool searchRequired = true; long primeSearchCounter = 0; // если число n чётное или НОД(baseNum, n)!=1, то оно составное if (number % 2 == 0 || CryptographyMath.ExtendedGCD(baseNum, number)[0] != 1) { MessageBox.Show("Число " + number.ToString() + " скорее всего составное"); } else { t = (number - 1); //представляем число n - 1 в таком виде: n-1 = 2^s*t, находим s и t while (searchRequired) { if (t % 2 == 0) { s++; t = (number - 1) / (long)Math.Pow(2, s); } else { searchRequired = false; } } //если baseNum^t = 1 (mod n), или baseNum^((2^r)*t) = -1 (mod n) при 0<=r<s , то n псевдопростое по основанию baseNum for (int i = 0; i < s; i++) { long atn = CryptographyMath.PowerSearch(baseNum, t, number); // возводим а в степень t по модулю n if ((Math.Abs(atn) == 1) || (CryptographyMath.PowerSearch(atn, (long)Math.Pow(2, i), number) == number - 1)) // вместо того, чтобы писать Stepen(atn, (long) Math.Pow(2, i), n) == -1 { MessageBox.Show("Число " + number.ToString() + " вероятно простое"); break; } else { primeSearchCounter += 1; } } //если ни при одном r (0<=r<s) не выполняется baseNum^((2^r)*t) = -1 (mod n), то n составное if (primeSearchCounter == s) { MessageBox.Show(" Число " + number.ToString() + " составное"); } } } catch (Exception ex) { MessageBox.Show("Ошибка:" + ex.Message); } }
private void DixonAlgorithm(int N, int numOfInstances, bool calculateOperations) { Log("Начинаем подбор. Факторизуемое число - " + N + " .Кол-во инстансов - " + numOfInstances); var tasks = new List <Task>(); for (int iter = 0; iter < numOfInstances; iter++) { tasks.Add(new Task(() => { try { var calculateOps = calculateOperations; var primesUponN = CryptographyMath.SieveOfEratosthenes(N).ToList(); if (primesUponN.Contains(N)) { Log("Число " + N + " - простое!"); return; } primesUponN.RemoveAt(0);//Remove 1 from list var minN = (int)Math.Sqrt(N); var M = Math.Pow(LofN(N), 0.5); var primes = primesUponN.Where(x => x <= M).ToList(); if (primes.Count == 0) { Log("Слишком маленькое число !!"); return; } var B = new List <long>(primes.ConvertAll(i => (long)i));//build factor base int h = B.Count + 1; var smoothed = new List <SmoothInfo>(); var operationCounter = new List <DixonOperations>(); var answerNotFound = true; while (answerNotFound) { int curFound = 0; smoothed.Clear(); while (curFound < h) { var b = random.Next(minN + 1, N - 1); var a = long.Parse(BigInteger.ModPow(new BigInteger(b), new BigInteger(2), new BigInteger(N)).ToString()); if (calculateOps) { operationCounter.Add(DixonOperations.GenerateB); operationCounter.Add(DixonOperations.GenerateA); } if (a == 0) { continue; } var factors = new List <long>(); if (calculateOps) { operationCounter.Add(DixonOperations.CheckSmooth); } if (CryptographyMath.IsSmooth(a, B, out factors)) { var smooth = new SmoothInfo(); smooth.a = a; smooth.b = b; smooth.aVec = factors; factors.ForEach(x => smooth.epsVec.Add(x % 2)); smoothed.Add(smooth); curFound += 1; } else { continue; } } for (int first = 0; first < smoothed.Count && answerNotFound == true; first++) { for (int second = first; second < smoothed.Count && answerNotFound == true; second++) { if (first != second) { if (calculateOps) { operationCounter.Add(DixonOperations.CheckLinearEquation); } var vecOne = smoothed[first]; var vecTwo = smoothed[second]; var deltaLeft = smoothed.Count - (smoothed.Count - first); var deltaMiddle = second - (first + 1); var currentAnswer = new List <double>(); var matrix = new List <List <double> >(); //create correct matrix here for (int i = 0; i < vecOne.aVec.Count; i++) { var vertex = new List <double>(); vertex.AddRange(Enumerable.Repeat(0.0, deltaLeft)); vertex.Add(vecOne.aVec[i]); vertex.AddRange(Enumerable.Repeat(0.0, deltaMiddle)); vertex.Add(vecTwo.aVec[i]); vertex.Add(0); matrix.Add(vertex); } CryptographyMath.TheTruePowerfullGauss(matrix, currentAnswer); if (currentAnswer.Any(x => x != 0)) { var probableX = (vecOne.b * vecTwo.b) % N; var probableY = 1.0; for (int i = 0; i < B.Count; i++) { var value = B[i]; var step = (vecOne.aVec[i] + vecTwo.aVec[i]) / 2.0; probableY *= Math.Pow(value, step); } probableY = probableY % N; if (calculateOps) { operationCounter.Add(DixonOperations.CheckXY); } if ((probableX == probableY) || (probableX == -probableY)) { continue; } else { //n = u * v //u = gcd(x+y,n) //v = gcd(x-y,n) var u = CryptographyMath.ExtendedGCD((int)(probableX + probableY), N)[0]; var v = CryptographyMath.ExtendedGCD((int)(probableX - probableY), N)[0]; if (calculateOps) { operationCounter.Add(DixonOperations.CalculateGcd); operationCounter.Add(DixonOperations.CalculateGcd); } if (((u * v) == N) && (u != 1) && (v != 1)) { Log("Разложение найдено - (" + u + ") * (" + v + ") = " + N); answerNotFound = false; } } } else { continue; } } } } } if (calculateOps) { var finalResult = "\r\nОбщее кол-во выполненых операций:" + operationCounter.Count + "\r\n"; var countResults = operationCounter.GroupBy(x => x).ToDictionary(x => x.Key, y => y.Count()); foreach (var info in countResults) { finalResult += info.Key + " - " + info.Value + "\r\n"; } Log(finalResult); } } catch (Exception e) { if (e.Message.Contains("OutOfMemoryException")) { Log("Недостаточно памяти для вычисления значения"); } else { Log("Возникла ошибка:" + e.Message); } return; } })); } tasks.ForEach(x => x.Start()); }