/// <summary> /// Creates a pair of two primes which, being multiplied one by another, /// produce a public key of desired length for the RSA algorithm. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <param name="digits">The desired number of digits in the public key.</param> /// <param name="randomGenerator">A random generator for long integer numbers.</param> /// <param name="primalityTest"></param> /// <returns></returns> public static Point <LongInt <B> > GetKey <B>(int digits, IRandomBounded <LongInt <B> > randomGenerator = null, Func <LongInt <B>, bool> primalityTest = null) where B : IBase, new() { Contract.Requires <ArgumentOutOfRangeException>(digits > 1, "The amount of digits in the key should be more than 1."); /* * Contract.Ensures( * (Contract.Result<Point<LongInt<B>>>().X * Contract.Result<Point<LongInt<B>>>().Y) * .Length == digits); */ long bits = (long)Math.Ceiling(Math.Log(LongInt <B> .BASE, 2)); // сколько бит занимает BASE if (randomGenerator == null) { randomGenerator = new RandomLongIntModular <B>(new RandomMersenneTwister()); } if (primalityTest == null) { primalityTest = (x => __isPrimeOptimized(x)); } LongInt <B> firstPrime, secondPrime; int half = digits / 2; // На текущий момент длина ключа может оказаться МЕНЬШЕ // запланированной. Сделать так, чтобы она всегда была одна. // Нижеуказанный генератор тоже снести. IRandomBoundedUnbounded <int> tmp = new RandomCryptographic(); do { firstPrime = new LongInt <B>(half, tmp, false); }while (!primalityTest(firstPrime)); do { secondPrime = new LongInt <B>(digits - half, tmp, false); }while (!primalityTest(secondPrime)); return(new Point <LongInt <B> >(firstPrime, secondPrime)); }
/// <summary> /// Hidden method - tries the first 100 primes to test divisibility. /// If not divisible - proceeds with Miller-Rabin. /// </summary> private static bool __isPrimeOptimized <B>(LongInt <B> number) where B : IBase, new() { RandomMersenneTwister gen = new RandomMersenneTwister(); RandomLongIntModular <B> lgen = new RandomLongIntModular <B>(gen); foreach (int prime in firstPrimes) { if (number % prime == 0) { return(false); } } if (PrimalityTests.IsPrime_MillerRabin(number, lgen, number.LengthInBinaryPlaces) < 1) { return(true); } return(false); }