int Jacobi(const Integer &aIn, const Integer &bIn) { assert(bIn.IsOdd()); Integer b = bIn, a = aIn%bIn; int result = 1; while (!!a) { unsigned i=0; while (a.GetBit(i)==0) i++; a>>=i; if (i%2==1 && (b%8==3 || b%8==5)) result = -result; if (a%4==3 && b%4==3) result = -result; std::swap(a, b); a %= b; } return (b==1) ? result : 0; }
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; }
bool ECP::ValidateParameters(RandomNumberGenerator &rng) const { Integer p = FieldSize(); return p.IsOdd() && VerifyPrime(rng, p) && !m_a.IsNegative() && m_a<p && !m_b.IsNegative() && m_b<p && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive(); }
Integer RabinFunction::ApplyFunction(const Integer &in) const { Integer out = in.Squared()%n; if (in.IsOdd()) out = out*r%n; if (Jacobi(in, n)==-1) out = out*s%n; return out; }
Integer RabinFunction::ApplyFunction(const Integer &in) const { DoQuickSanityCheck(); Integer out = in.Squared()%m_n; if (in.IsOdd()) out = out*m_r%m_n; if (Jacobi(in, m_n)==-1) out = out*m_s%m_n; return out; }
bool ECP::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const { Integer p = FieldSize(); bool pass = p.IsOdd(); pass = pass && !m_a.IsNegative() && m_a<p && !m_b.IsNegative() && m_b<p; if (level >= 1) pass = pass && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive(); if (level >= 2) pass = pass && VerifyPrime(rng, p); return pass; }
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; }
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod) { assert(!equiv.IsNegative() && equiv < mod); Integer gcd = GCD(equiv, mod); if (gcd != Integer::One()) { // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) if (p <= gcd && gcd <= max && IsPrime(gcd)) { p = gcd; return true; } else return false; } BuildPrimeTable(); if (p <= primeTable[primeTableSize-1]) { word *pItr; --p; if (p.IsPositive()) pItr = std::upper_bound(primeTable, primeTable+primeTableSize, p.ConvertToLong()); else pItr = primeTable; while (pItr < primeTable+primeTableSize && *pItr%mod != equiv) ++pItr; if (pItr < primeTable+primeTableSize) { p = *pItr; return p <= max; } p = primeTable[primeTableSize-1]+1; } assert(p > primeTable[primeTableSize-1]); if (mod.IsOdd()) return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1); p += (equiv-p)%mod; if (p>max) return false; PrimeSieve sieve(p, max, mod); while (sieve.NextCandidate(p)) { if (FastProbablePrimeTest(p) && IsPrime(p)) return true; } return false; }
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector) { assert(!equiv.IsNegative() && equiv < mod); Integer gcd = GCD(equiv, mod); if (gcd != Integer::One()) { // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd))) { p = gcd; return true; } else return false; } unsigned int primeTableSize; const word16 * primeTable = GetPrimeTable(primeTableSize); if (p <= primeTable[primeTableSize-1]) { const word16 *pItr; --p; if (p.IsPositive()) pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong()); else pItr = primeTable; while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr)))) ++pItr; if (pItr < primeTable+primeTableSize) { p = *pItr; return p <= max; } p = primeTable[primeTableSize-1]+1; } assert(p > primeTable[primeTableSize-1]); if (mod.IsOdd()) return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector); p += (equiv-p)%mod; if (p>max) return false; PrimeSieve sieve(p, max, mod); while (sieve.NextCandidate(p)) { if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p)) return true; } return false; }