Integer InvertibleRabinFunction::CalculateInverse(const Integer &in) const { DoQuickSanityCheck(); Integer cp=in%m_p, cq=in%m_q; int jp = Jacobi(cp, m_p); int jq = Jacobi(cq, m_q); if (jq==-1) { cp = cp*EuclideanMultiplicativeInverse(m_r, m_p)%m_p; cq = cq*EuclideanMultiplicativeInverse(m_r, m_q)%m_q; } if (jp==-1) { cp = cp*EuclideanMultiplicativeInverse(m_s, m_p)%m_p; cq = cq*EuclideanMultiplicativeInverse(m_s, m_q)%m_q; } cp = ModularSquareRoot(cp, m_p); cq = ModularSquareRoot(cq, m_q); if (jp==-1) cp = m_p-cp; Integer out = CRT(cq, m_q, cp, m_p, m_u); if ((jq==-1 && out.IsEven()) || (jq==1 && out.IsOdd())) out = m_n-out; return out; }
Integer InvertibleRabinFunction::CalculateInverse(const Integer &in) const { Integer cp=in%p, cq=in%q; int jp = Jacobi(cp, p); int jq = Jacobi(cq, q); if (jq==-1) { cp = cp*EuclideanMultiplicativeInverse(r, p)%p; cq = cq*EuclideanMultiplicativeInverse(r, q)%q; } if (jp==-1) { cp = cp*EuclideanMultiplicativeInverse(s, p)%p; cq = cq*EuclideanMultiplicativeInverse(s, q)%q; } cp = ModularSquareRoot(cp, p); cq = ModularSquareRoot(cq, q); if (jp==-1) cp = p-cp; Integer out = CRT(cq, q, cp, p, u); if ((jq==-1 && out.IsEven()) || (jq==1 && out.IsOdd())) out = n-out; return out; }
// generate a random private key InvertableRSAFunction::InvertableRSAFunction(RandomNumberGenerator &rng, unsigned int keybits, const Integer &eStart) { assert(keybits >= 16); // generate 2 random primes of suitable size if (keybits%2==0) { const Integer minP = Integer(182) << (keybits/2-8); const Integer maxP = Integer::Power2(keybits/2)-1; p.Randomize(rng, minP, maxP, Integer::PRIME); q.Randomize(rng, minP, maxP, Integer::PRIME); } else { const Integer minP = Integer::Power2((keybits-1)/2); const Integer maxP = Integer(181) << ((keybits+1)/2-8); p.Randomize(rng, minP, maxP, Integer::PRIME); q.Randomize(rng, minP, maxP, Integer::PRIME); } // pre-calculate some other data for faster speed const Integer lcm = LCM(p-1, q-1); // make sure e starts odd for (e = eStart+(1-eStart%2); GCD(e, lcm)!=1; ++e, ++e); d = EuclideanMultiplicativeInverse(e, lcm); dp = d % (p-1); dq = d % (q-1); u = EuclideanMultiplicativeInverse(q, p); n = p * q; assert(n.BitCount() == keybits); }
Integer ModularRoot(const Integer &a, const Integer &e, const Integer &p, const Integer &q) { Integer dp = EuclideanMultiplicativeInverse(e, p-1); Integer dq = EuclideanMultiplicativeInverse(e, q-1); Integer u = EuclideanMultiplicativeInverse(p, q); assert(!!dp && !!dq && !!u); return ModularRoot(a, dp, dq, p, q, u); }
void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) { int modulusSize = 2048; alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); ASSERT( modulusSize >= 16 ); m_e = alg.GetValueWithDefault("PublicExponent", Integer(17)); ASSERT( m_e >= 3 ); ASSERT( !m_e.IsEven() ); RSAPrimeSelector selector(m_e); const NameValuePairs &primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) ("PointerToPrimeSelector", selector.GetSelectorPointer()); m_p.GenerateRandom(rng, primeParam); m_q.GenerateRandom(rng, primeParam); m_d = EuclideanMultiplicativeInverse(m_e, LCM(m_p-1, m_q-1)); assert(m_d.IsPositive()); m_dp = m_d % (m_p-1); m_dq = m_d % (m_q-1); m_n = m_p * m_q; m_u = m_q.InverseMod(m_p); }
void ElGamalDecryptor::RawDecrypt(const Integer &a, const Integer &b, Integer &m) const { if (x.BitCount()+20 < p.BitCount()) // if x is short m = b * EuclideanMultiplicativeInverse(a_exp_b_mod_c(a, x, p), p) % p; else // save a multiplicative inverse calculation m = b * a_exp_b_mod_c(a, p-1-x, p) % p; }
BlumGoldwasserPrivateKey::BlumGoldwasserPrivateKey(const Integer &n, const Integer &p, const Integer &q, const Integer &u) : BlumGoldwasserPublicKey(n), p(p), q(q), u(u) { assert(n == p*q); assert(u == EuclideanMultiplicativeInverse(p, q)); }
Integer InvertibleRabinFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &in) const { DoQuickSanityCheck(); ModularArithmetic modn(m_n); Integer r(rng, Integer::One(), m_n - Integer::One()); r = modn.Square(r); Integer r2 = modn.Square(r); Integer c = modn.Multiply(in, r2); // blind Integer cp=c%m_p, cq=c%m_q; int jp = Jacobi(cp, m_p); int jq = Jacobi(cq, m_q); if (jq==-1) { cp = cp*EuclideanMultiplicativeInverse(m_r, m_p)%m_p; cq = cq*EuclideanMultiplicativeInverse(m_r, m_q)%m_q; } if (jp==-1) { cp = cp*EuclideanMultiplicativeInverse(m_s, m_p)%m_p; cq = cq*EuclideanMultiplicativeInverse(m_s, m_q)%m_q; } cp = ModularSquareRoot(cp, m_p); cq = ModularSquareRoot(cq, m_q); if (jp==-1) cp = m_p-cp; Integer out = CRT(cq, m_q, cp, m_p, m_u); out = modn.Divide(out, r); // unblind if ((jq==-1 && out.IsEven()) || (jq==1 && out.IsOdd())) out = m_n-out; return out; }
Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u) { Integer d = (m*m-4); Integer p2, q2; #pragma omp parallel #pragma omp sections { #pragma omp section { p2 = p-Jacobi(d,p); p2 = Lucas(EuclideanMultiplicativeInverse(e,p2), m, p); } #pragma omp section { q2 = q-Jacobi(d,q); q2 = Lucas(EuclideanMultiplicativeInverse(e,q2), m, q); } } return CRT(p2, p, q2, q, u); }
BlumGoldwasserPrivateKey::BlumGoldwasserPrivateKey(BufferedTransformation &bt) { BERSequenceDecoder seq(bt); n.BERDecode(seq); modulusLen = n.ByteCount(); p.BERDecode(seq); q.BERDecode(seq); u.BERDecode(seq); assert(n == p*q); assert(u == EuclideanMultiplicativeInverse(p, q)); }
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); }
// generate a random private key InvertibleRabinFunction::InvertibleRabinFunction(RandomNumberGenerator &rng, unsigned int keybits) { assert(keybits >= 16); // generate 2 random primes of suitable size if (keybits%2==0) { const Integer minP = Integer(182) << (keybits/2-8); const Integer maxP = Integer::Power2(keybits/2)-1; p.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); q.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); } else { const Integer minP = Integer::Power2((keybits-1)/2); const Integer maxP = Integer(181) << ((keybits+1)/2-8); p.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); q.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); } bool rFound=false, sFound=false; Integer t=2; while (!(rFound && sFound)) { int jp = Jacobi(t, p); int jq = Jacobi(t, q); if (!rFound && jp==1 && jq==-1) { r = t; rFound = true; } if (!sFound && jp==-1 && jq==1) { s = t; sFound = true; } ++t; } n = p * q; assert(n.BitCount() == keybits); u = EuclideanMultiplicativeInverse(q, p); assert(u*q%p==1); }
void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) { int modulusSize = 2048; alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); if (modulusSize < 16) throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small"); m_e = alg.GetValueWithDefault("PublicExponent", Integer(17)); if (m_e < 3 || m_e.IsEven()) throw InvalidArgument("InvertibleRSAFunction: invalid public exponent"); RSAPrimeSelector selector(m_e); const NameValuePairs &primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) ("PointerToPrimeSelector", selector.GetSelectorPointer()); m_p.GenerateRandom(rng, primeParam); m_q.GenerateRandom(rng, primeParam); m_d = EuclideanMultiplicativeInverse(m_e, LCM(m_p-1, m_q-1)); assert(m_d.IsPositive()); m_dp = m_d % (m_p-1); m_dq = m_d % (m_q-1); m_n = m_p * m_q; m_u = m_q.InverseMod(m_p); if (FIPS_140_2_ComplianceEnabled()) { RSASS<PKCS1v15, SHA>::Signer signer(*this); RSASS<PKCS1v15, SHA>::Verifier verifier(signer); SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); RSAES<OAEP<SHA> >::Decryptor decryptor(*this); RSAES<OAEP<SHA> >::Encryptor encryptor(decryptor); EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor); } }
// generate a random private key BlumGoldwasserPrivateKey::BlumGoldwasserPrivateKey(RandomNumberGenerator &rng, unsigned int keybits) { assert(keybits >= 16); // generate 2 random primes of suitable size if (keybits%2==0) { const Integer minP = Integer(182) << (keybits/2-8); const Integer maxP = Integer::Power2(keybits/2)-1; p.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); q.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); } else { const Integer minP = Integer::Power2((keybits-1)/2); const Integer maxP = Integer(181) << ((keybits+1)/2-8); p.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); q.Randomize(rng, minP, maxP, Integer::PRIME, 3, 4); } n = p*q; u = EuclideanMultiplicativeInverse(p, q); modulusLen = n.ByteCount(); }
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); }
Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q) { return InverseLucas(e, m, p, q, EuclideanMultiplicativeInverse(p, q)); }
Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q) { return CRT(xp, p, xq, q, EuclideanMultiplicativeInverse(p, q)); }