private PrimeGeneratorResult GeneratePrimes(PrimeGeneratorParameters param) { BigInteger p, p1, p2, q, q1, q2, xp, xq; // 1, 2, 3, 4 covered by guards // 5 var p1Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[0], param.Seed.ToPositiveBigInteger(), _sha); if (!p1Result.Success) { return(new PrimeGeneratorResult($"Failed to generate p1: {p1Result.ErrorMessage}")); } var p2Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[1], p1Result.PrimeSeed, _sha); if (!p2Result.Success) { return(new PrimeGeneratorResult($"Failed to generate p2: {p2Result.ErrorMessage}")); } p1 = p1Result.Prime; p2 = p2Result.Prime; var pResult = PrimeGeneratorHelper.ProbablePrimeFactor(_primeTest, _entropyProvider, _pBound, param.A, p1, p2, param.Modulus, param.PublicE); if (!pResult.Success) { return(new PrimeGeneratorResult($"Failed to generate p: {pResult.ErrorMessage}")); } p = pResult.Prime; xp = pResult.XPrime; do { // 6 var q1Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[2], p2Result.PrimeSeed, _sha); if (!q1Result.Success) { return(new PrimeGeneratorResult($"Failed to generate q1: {q1Result.ErrorMessage}")); } var q2Result = PrimeGen186_4.ShaweTaylorRandomPrime(param.BitLens[3], q1Result.PrimeSeed, _sha); if (!q2Result.Success) { return(new PrimeGeneratorResult($"Failed to generate q2: {q2Result.ErrorMessage}")); } q1 = q1Result.Prime; q2 = q2Result.Prime; var qResult = PrimeGeneratorHelper.ProbablePrimeFactor(_primeTest, _entropyProvider, _pBound, param.B, q1, q2, param.Modulus, param.PublicE); if (!qResult.Success) { return(new PrimeGeneratorResult($"Failed to generate q: {qResult.ErrorMessage}")); } q = qResult.Prime; xq = qResult.XPrime; // 7 } while (BigInteger.Abs(p - q) <= NumberTheory.Pow2(param.Modulus / 2 - 100) || BigInteger.Abs(xp - xq) <= NumberTheory.Pow2(param.Modulus / 2 - 100)); var auxValues = new AuxiliaryResult { XP = xp, XQ = xq }; var primePair = new PrimePair { P = p, Q = q }; return(new PrimeGeneratorResult(primePair, auxValues)); }
/// <summary> /// A.1.2.1.2 /// </summary> /// <param name="L"></param> /// <param name="N"></param> /// <param name="firstSeed"></param> /// <returns></returns> private PQGenerateResult Generate(int L, int N, BigInteger firstSeed) { // 1 if (!DSAHelper.VerifyLenPair(L, N)) { return(new PQGenerateResult("Bad L, N pair")); } // 2 var qResult = PrimeGen186_4.ShaweTaylorRandomPrime(N, firstSeed, _sha); if (!qResult.Success) { return(new PQGenerateResult("Failed to generate q from ShaweTaylor")); } var q = qResult.Prime; var qSeed = qResult.PrimeSeed; var qCounter = qResult.PrimeGenCounter; // 3 var pLen = L.CeilingDivide(2) + 1; var pResult = PrimeGen186_4.ShaweTaylorRandomPrime(pLen, qSeed, _sha); if (!pResult.Success) { return(new PQGenerateResult("Failed to generate p0 from ShaweTaylor")); } var p0 = pResult.Prime; var pSeed = pResult.PrimeSeed; var pCounter = pResult.PrimeGenCounter; // 4, 5 var outLen = _sha.HashFunction.OutputLen; var iterations = L.CeilingDivide(outLen) - 1; var oldCounter = pCounter; // 6, 7 BigInteger x = 0; for (var i = 0; i <= iterations; i++) { x += _sha.HashNumber(pSeed + i).ToBigInteger() * NumberTheory.Pow2(i * outLen); } // 8 pSeed += iterations + 1; // 9 x = NumberTheory.Pow2(L - 1) + (x % NumberTheory.Pow2(L - 1)); // 10 var t = x.CeilingDivide(2 * q * p0); do { // 11 if (2 * t * q * p0 + 1 > NumberTheory.Pow2(L)) { t = NumberTheory.Pow2(L - 1).CeilingDivide(2 * q * p0); } // 12, 13 var p = 2 * t * q * p0 + 1; pCounter++; // 14, 15 BigInteger a = 0; for (var i = 0; i <= iterations; i++) { a += _sha.HashNumber(pSeed + i).ToBigInteger() * NumberTheory.Pow2(i * outLen); } // 16 pSeed += iterations + 1; // 17 a = 2 + (a % (p - 3)); // 18 var z = BigInteger.ModPow(a, 2 * t * q, p); // 19 if (1 == NumberTheory.GCD(z - 1, p) && 1 == BigInteger.ModPow(z, p0, p)) { return(new PQGenerateResult(p, q, new DomainSeed(firstSeed, pSeed, qSeed), new Counter(pCounter, qCounter))); } // 20 if (pCounter > 4 * L + oldCounter) { return(new PQGenerateResult("Too many iterations")); } // 21 t++; // 22 } while (true); }