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); }