void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer &q, GFP2Element &g, unsigned int pbits, unsigned int qbits) { CRYPTOPP_ASSERT(qbits > 9); // no primes exist for pbits = 10, qbits = 9 CRYPTOPP_ASSERT(pbits > qbits); const Integer minQ = Integer::Power2(qbits - 1); const Integer maxQ = Integer::Power2(qbits) - 1; const Integer minP = Integer::Power2(pbits - 1); const Integer maxP = Integer::Power2(pbits) - 1; top: Integer r1, r2; do { (void)q.Randomize(rng, minQ, maxQ, Integer::PRIME, 7, 12); // Solution always exists because q === 7 mod 12. (void)SolveModularQuadraticEquation(r1, r2, 1, -1, 1, q); // I believe k_i, r1 and r2 are being used slightly different than the // paper's algorithm. I believe it is leading to the failed asserts. // Just make the assert part of the condition. if(!p.Randomize(rng, minP, maxP, Integer::PRIME, CRT(rng.GenerateBit() ? r1 : r2, q, 2, 3, EuclideanMultiplicativeInverse(p, 3)), 3 * q)) { continue; } } while (((p % 3U) != 2) || (((p.Squared() - p + 1) % q).NotZero())); // CRYPTOPP_ASSERT((p % 3U) == 2); // CRYPTOPP_ASSERT(((p.Squared() - p + 1) % q).IsZero()); GFP2_ONB<ModularArithmetic> gfp2(p); GFP2Element three = gfp2.ConvertIn(3), t; while (true) { g.c1.Randomize(rng, Integer::Zero(), p-1); g.c2.Randomize(rng, Integer::Zero(), p-1); t = XTR_Exponentiate(g, p+1, p); if (t.c1 == t.c2) continue; g = XTR_Exponentiate(g, (p.Squared()-p+1)/q, p); if (g != three) break; } if (XTR_Exponentiate(g, q, p) != three) goto top; // CRYPTOPP_ASSERT(XTR_Exponentiate(g, q, p) == three); }
void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) { Integer p, q, g; if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) { q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); } else { int modulusSize = 1024; alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); if (!DSA::IsValidPrimeLength(modulusSize)) throw InvalidArgument("DSA: not a valid prime length"); SecByteBlock seed(SHA::DIGESTSIZE); Integer h; int c; do { rng.GenerateBlock(seed, SHA::DIGESTSIZE); } while (!DSA::GeneratePrimes(seed, SHA::DIGESTSIZE*8, c, p, modulusSize, q)); do { h.Randomize(rng, 2, p-2); g = a_exp_b_mod_c(h, (p-1)/q, p); } while (g <= 1); } Initialize(p, q, g); }
Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits) { const unsigned smallPrimeBound = 29, c_opt=10; Integer p; unsigned int primeTableSize; const word16 * primeTable = GetPrimeTable(primeTableSize); if (bits < smallPrimeBound) { do p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ANY, 1, 2); while (TrialDivision(p, 1 << ((bits+1)/2))); } else { const unsigned margin = bits > 50 ? 20 : (bits-10)/2; double relativeSize; do relativeSize = pow(2.0, double(rng.GenerateWord32())/0xffffffff - 1); while (bits * relativeSize >= bits - margin); Integer a,b; Integer q = MaurerProvablePrime(rng, unsigned(bits*relativeSize)); Integer I = Integer::Power2(bits-2)/q; Integer I2 = I << 1; unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt); bool success = false; while (!success) { p.Randomize(rng, I, I2, Integer::ANY); p *= q; p <<= 1; ++p; if (!TrialDivision(p, trialDivisorBound)) { a.Randomize(rng, 2, p-1, Integer::ANY); b = a_exp_b_mod_c(a, (p-1)/q, p); success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1); } } } return p; }
Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits) { Integer p; Integer minP = Integer::Power2(pbits-1); Integer maxP = Integer::Power2(pbits) - 1; if (maxP <= Integer(s_lastSmallPrime).Squared()) { // Randomize() will generate a prime provable by trial division p.Randomize(rng, minP, maxP, Integer::PRIME); return p; } unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36); Integer q = MihailescuProvablePrime(rng, qbits); Integer q2 = q<<1; while (true) { // this initializes the sieve to search in the arithmetic // progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q, // with q the recursively generated prime above. We will be able // to use Lucas tets for proving primality. A trick of Quisquater // allows taking q > cubic_root(p) rather then square_root: this // decreases the recursion. p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2); PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2); while (sieve.NextCandidate(p)) { if (FastProbablePrimeTest(p) && ProvePrime(p, q)) return p; } } // not reached return p; }
void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer &q, GFP2Element &g, unsigned int pbits, unsigned int qbits) { assert(qbits > 9); // no primes exist for pbits = 10, qbits = 9 assert(pbits > qbits); const Integer minQ = Integer::Power2(qbits - 1); const Integer maxQ = Integer::Power2(qbits) - 1; const Integer minP = Integer::Power2(pbits - 1); const Integer maxP = Integer::Power2(pbits) - 1; Integer r1, r2; do { bool qFound = q.Randomize(rng, minQ, maxQ, Integer::PRIME, 7, 12); CRYPTOPP_UNUSED(qFound); assert(qFound); bool solutionsExist = SolveModularQuadraticEquation(r1, r2, 1, -1, 1, q); CRYPTOPP_UNUSED(solutionsExist); assert(solutionsExist); } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, CRT(rng.GenerateBit()?r1:r2, q, 2, 3, EuclideanMultiplicativeInverse(p, 3)), 3*q)); assert(((p.Squared() - p + 1) % q).IsZero()); GFP2_ONB<ModularArithmetic> gfp2(p); GFP2Element three = gfp2.ConvertIn(3), t; while (true) { g.c1.Randomize(rng, Integer::Zero(), p-1); g.c2.Randomize(rng, Integer::Zero(), p-1); t = XTR_Exponentiate(g, p+1, p); if (t.c1 == t.c2) continue; g = XTR_Exponentiate(g, (p.Squared()-p+1)/q, p); if (g != three) break; } assert(XTR_Exponentiate(g, q, p) == three); }
bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &n, unsigned int rounds) { if (n <= 3) return n==2 || n==3; assert(n>3); Integer b; for (unsigned int i=0; i<rounds; i++) { b.Randomize(rng, 2, n-2); if (!IsStrongProbablePrime(n, b)) return false; } return true; }