예제 #1
0
        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);
            }
        }
예제 #2
0
        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());
        }