Пример #1
0
        public static BigInteger FindSmallPrimes(int bits)
        {
            if (bits > 20)
            {
                throw new ArgumentException("bits > 20");
            }

            Log.MethodEnter("TrialDivision.CheckForSmallComposites", nameof(bits), bits);
            BigInteger result = 0;

            using (executionTimer.StartTimer())
            {
                long n         = 0;
                bool composite = true;
                while (composite)
                {
                    n = 1 << (bits - 1);

                    for (int i = 0; i < bits - 1; i++)
                    {
                        n |= CryptoRandomSingleton.Next(2) << i;
                    }

                    composite = !Eratosthenes.IsPrime(n);
                }
                result = n;
            }

            Log.MethodLeave();
            return(result);
        }
        /// <summary>
        /// Returns a probable prime of size bits and will search n rounds for a composite
        /// </summary>
        /// <param name="bitSize">Size of prime, in bits</param>
        /// <param name="testCount">Number of different bases to use when testing probable prime  for composites as evidence of primality</param>
        /// <returns></returns>
        public BigInteger GetProbablePrime(int bitSize, int testCount)
        {
            BigInteger result = 0;

            //Log.Message(".");
            Log.MethodEnter("ProvablePrime", nameof(bitSize), bitSize);

            if (cancelToken.IsCancellationRequested)
            {
                Log.Message("ProvablePrime.CancellationToken.IsCancellationRequested();");
                Log.MethodLeave();
                return(-1);
            }

            if (bitSize <= 20)
            {
                Log.Message("***MAXIMUM RECURSION DEPT REACHED");
                result = TrialDivision.FindSmallPrimes(bitSize);
                Log.Message("***Hopeful prime: {0}", result);
            }
            else
            {
                //double c = 0.1;
                int    m = 20;
                double r = 0.5;

                if (bitSize > 2 * m)
                {
                    double rnd  = 0;
                    bool   done = false;
                    while (!done)
                    {
                        rnd  = CryptoRandomSingleton.NextDouble();
                        r    = Math.Pow(2, rnd - 1);
                        done = (bitSize - r * bitSize) > m;
                    }
                }

                int newBits = (int)Math.Floor(r * bitSize) + 1;

                BigInteger smallPrime = GetProbablePrime(newBits, testCount);

                if (smallPrime == -1)
                {
                    Log.MethodLeave();
                    return(-1);
                }
                Log.Message("After Recursion: Length = {0}", smallPrime.ToString().Length);

                BigInteger pow = BigInteger.Pow(Two, bitSize - 1);
                BigInteger Q   = Two * smallPrime;
                BigInteger I   = pow / Q;

                bool success = false;
                while (!success)
                {
                    if (cancelToken.IsCancellationRequested)
                    {
                        Log.Message("ProvablePrime.CancellationToken.IsCancellationRequested();");
                        Log.MethodLeave();
                        return(-1);
                    }

                    //LogMethod("Loop[{0}]: TestComposite({1})", _loopCount, result);

                    BigInteger J     = I + 1;
                    BigInteger K     = 2 * I;
                    BigInteger rand1 = CryptoRandomSingleton.RandomRange(J, K);
                    result = 2 * rand1;
                    result = result * smallPrime;
                    result = result + 1;

                    bool isPrime = false;
                    if (Eratosthenes.IsTooLarge(result))
                    {
                        isPrime = true;
                    }
                    else
                    {
                        isPrime = Eratosthenes.IsPrime(result);
                    }

                    if (isPrime)
                    {
                        //LogMethod("ProvablePrime.RandomRange(J: {0}, K: {1}) = {2}", J, K, rand1);
                        if (MillerRabin.IsProbablyPrime(result, testCount))
                        {
                            success = true;
                            string cert = MillerRabin.GetCertificateOfPrimality(result, rand1);

                            if (cert != null)
                            {
                                Log.Message(cert);
                            }
                        }
                    }
                }
            }

            //Log.Message(".");
            Log.MethodLeave();
            return(result);
        }