/// <summary> /// Generate a prime number using with a given approximate length and byte length margin /// </summary> /// <param name="threads">How many threads to use to generate primes</param> /// <param name="approximateByteCount">The byte array length around which the prime generator will select lengths</param> /// <param name="byteMargin">Allowed deviation of byte length from approximateByteCount</param> /// <param name="certainty">How many iterations of the fermat test should be run to test primailty for each generated number</param> /// <param name="provider">Random provider that will be used to generate random primes</param> /// <returns>A prime number that is aproximately approximateByteCount long</returns> public static BigInteger GeneratePrime(int threads, int approximateByteCount, int byteMargin, int certainty, RandomProvider provider) { var found = false; BigInteger result = BigInteger.Zero; for (int i = 0; i < threads; ++i) { Task.Factory.StartNew(() => { char left = '\0'; byte rand = 0; BigInteger b = BigInteger.Zero; while (!found) { if (left == 0) { rand = provider.GetBytes(1)[0]; left = (char)8; } byte[] b1 = provider.GetBytes(approximateByteCount + (provider.GetBytes(1)[0] % byteMargin) * (rand % 2 == 1 ? 1 : -1)); b1[0] |= 1; // Always odd b1[b1.Length - 1] &= 127; // Always positive b = new BigInteger(b1); rand >>= 1; --left; if (IsProbablePrime(b, provider, certainty)) { found = true; result = b; } } }); } while (!found) { System.Threading.Thread.Sleep(125); } return(result); }