Example #1
0
// Create a tensor product of c1,c2. It is assumed that *this,c1,c2
// are defined relative to the same set of primes and plaintext space,
// and that *this DOES NOT point to the same object as c1,c2
void Ctxt::tensorProduct(const Ctxt& c1, const Ctxt& c2)
{
  // c1,c2 may be scaled, so multiply by the inverse scalar if needed
  long f = 1;
  if (c1.ptxtSpace>2) 
    f = rem(context.productOfPrimes(c1.primeSet),c1.ptxtSpace);
  if (f!=1) f = InvMod(f,c1.ptxtSpace);

  clear();                // clear *this, before we start adding things to it
  primeSet = c1.primeSet; // set the correct prime-set before we begin

  // The actual tensoring
  CtxtPart tmpPart(context, IndexSet::emptySet()); // a scratch CtxtPart
  for (size_t i=0; i<c1.parts.size(); i++) {
    CtxtPart thisPart = c1.parts[i];
    if (f!=1) thisPart *= f;
    for (size_t j=0; j<c2.parts.size(); j++) {
      tmpPart = c2.parts[j];
      // What secret key will the product point to?
      if (!tmpPart.skHandle.mul(thisPart.skHandle, tmpPart.skHandle))
	Error("Ctxt::tensorProduct: cannot multiply secret-key handles");

      tmpPart *= thisPart; // The element of the tensor product

      // Check if we already have a part relative to this secret-key handle
      long k = getPartIndexByHandle(tmpPart.skHandle);
      if (k >= 0) // found a matching part
	parts[k] += tmpPart;
      else
	parts.push_back(tmpPart);
    }
  }

  /* Compute the noise estimate as c1.noiseVar * c2.noiseVar * factor
   * where the factor depends on the handles of c1,c2. Specifically,
   * if the largest powerOfS in c1,c2 are n1,n2, respectively, then we
   * have factor = ((n1+n2) choose n2).
   */
  long n1=0,  n2=0;
  for (size_t i=0; i<c1.parts.size(); i++) // get largest powerOfS in c1
    if (c1.parts[i].skHandle.getPowerOfS() > n1)
      n1 = c1.parts[i].skHandle.getPowerOfS();
  for (size_t i=0; i<c2.parts.size(); i++) // get largest powerOfS in c2
    if (c2.parts[i].skHandle.getPowerOfS() > n2)
      n2 = c2.parts[i].skHandle.getPowerOfS();

  // compute ((n1+n2) choose n2)
  long factor = 1;
  for (long i=n1+1; i<=n1+n2; i++) factor *= i;
  for (long i=n2  ; i>1     ; i--) factor /= i;

  noiseVar = c1.noiseVar * c2.noiseVar * factor * context.zMStar.get_cM();
  if (f!=1) {
    // WARNING: the following line is written just so to prevent overflow
    noiseVar = (noiseVar*f)*f; // because every product was scaled by f
  }
}
Example #2
0
// Sets the prime defining the field for the curve and stores certain values
void Icart::setPrime(ZZ* p)
{
    //ZZ_p::init(*p);
    // Icart hash function uses 1/3 root, which is equivalent to (2p-1)/3
    exp = MulMod( SubMod( MulMod(ZZ(2), *p, *p), ZZ(1), *p), InvMod(ZZ(3),*p), *p);
    // Store inverse values to be used later
    ts = inv(ZZ_p(27));
    th = inv(ZZ_p(3));
}
Example #3
0
void InitFFTPrimeInfo(FFTPrimeInfo& info, long q, long w, long bigtab)
{
   double qinv = 1/((double) q);

   long mr = CalcMaxRoot(q);

   info.q = q;
   info.qinv = qinv;
   info.zz_p_context = 0;


   info.RootTable.SetLength(mr+1);
   info.RootInvTable.SetLength(mr+1);
   info.TwoInvTable.SetLength(mr+1);
   info.TwoInvPreconTable.SetLength(mr+1);

   long *rt = &info.RootTable[0];
   long *rit = &info.RootInvTable[0];
   long *tit = &info.TwoInvTable[0];
   mulmod_precon_t *tipt = &info.TwoInvPreconTable[0];

   long j;
   long t;

   rt[mr] = w;
   for (j = mr-1; j >= 0; j--)
      rt[j] = MulMod(rt[j+1], rt[j+1], q);

   rit[mr] = InvMod(w, q);
   for (j = mr-1; j >= 0; j--)
      rit[j] = MulMod(rit[j+1], rit[j+1], q);

   t = InvMod(2, q);
   tit[0] = 1;
   for (j = 1; j <= mr; j++)
      tit[j] = MulMod(tit[j-1], t, q);

   for (j = 0; j <= mr; j++)
      tipt[j] = PrepMulModPrecon(tit[j], q, qinv);

   info.bigtab = bigtab;
}
Example #4
0
NTL_CLIENT

#include <algorithm>   // defines count(...), min(...)
#include <iostream>

#include "NumbTh.h"
#include "PAlgebra.h"


// Generate the representation of Z[X]/(Phi_m(X),2) for the odd integer m
void PAlgebraModTwo::init(unsigned m)
{
  if (m == zmStar.M()) return; // nothign to do

  ((PAlgebra&)zmStar).init(m); // initialize the structure of (Z/mZ)*, if needed
  if (zmStar.M()==0 || zmStar.NSlots()==0) return; // error in zmStar
  unsigned nSlots = zmStar.NSlots();

  // Next compute the factors Ft of Phi_m(X) mod 2, for all t \in T

  //  GF2X PhimXmod = to_GF2X(zmStar.PhimX()); // Phi_m(X) mod 2
  PhimXmod = to_GF2X(zmStar.PhimX()); // Phi_m(X) mod 2

  EDF(factors, PhimXmod, zmStar.OrdTwo()); // equal-degree factorization

  // It is left to order the factors according to their representatives

  GF2XModulus F1(factors[0]); // We arbitrarily choose factors[0] as F1
  for (unsigned i=1; i<nSlots; i++) {
    unsigned t = zmStar.ith_rep(i); // Ft is minimal polynomial of x^{1/t} mod F1
    unsigned tInv = rep(inv(to_zz_p(t))); // tInv = t^{-1} mod m
    GF2X X2tInv = PowerXMod(tInv,F1);     // X2tInv = X^{1/t} mod F1
    IrredPolyMod(factors[i], X2tInv, F1);
  }
  /* Debugging sanity-check #1: we should have Ft= GCD(F1(X^t),Phi_m(X))
  GF2XModulus Pm2(PhimXmod);
  for (i=1; i<nSlots; i++) {
    unsigned t = T[i];
    GF2X X2t = PowerXMod(t,PhimXmod);  // X2t = X^t mod Phi_m(X)
    GF2X Ft = GCD(CompMod(F1,X2t,Pm2),Pm2);
    if (Ft != factors[i]) {
      cout << "Ft != F1(X^t) mod Phi_m(X), t=" << t << endl;
      exit(0);
    }
  }*******************************************************************/

  // Compute the CRT coefficients for the Ft's
  crtCoeffs.SetLength(nSlots);
  for (unsigned i=0; i<nSlots; i++) {
    GF2X te = PhimXmod / factors[i]; // \prod_{j\ne i} Fj
    te %= factors[i];              // \prod_{j\ne i} Fj mod Fi
    InvMod(crtCoeffs[i], te, factors[i]);// \prod_{j\ne i} Fj^{-1} mod Fi
  }
}
Example #5
0
// divVec[d] = m/p_d^{e_d}, powVec[d] = p^{e_d}
// computes invVec[d] = divVec[d]^{-1} mod powVec[d]
void computeInvVec(Vec<long>& invVec,
                   const Vec<long>& divVec, const Vec<long>& powVec)
{
  long k = divVec.length();
  invVec.SetLength(k);

  for (long d = 0; d < k; d++) {
    long t1 = divVec[d] % powVec[d];
    long t2 = InvMod(t1, powVec[d]);
    invVec[d] = t2;
  }
}
Example #6
0
ZZ ASTDiv::eval(Environment &env) { 			
	pair<VarInfo,VarInfo> p = getTypes(env);
	VarInfo leftInfo = p.first;
	VarInfo rightInfo = p.second;
	// XXX: this will cause a problem if we ever try to use
	// it during constant propagation/substitution
	const Group* lGroup = env.groups.at(leftInfo.group);
	const Group* rGroup = env.groups.at(rightInfo.group);
	const Group* retGroup = (lGroup != 0 ? lGroup : rGroup);
	// integers can just be divided
	if ((lGroup == 0 && rGroup == 0) 
		|| (leftInfo.type == VarInfo::MODULUS 
			|| rightInfo.type == VarInfo::MODULUS)) {
		return lhs->eval(env) / rhs->eval(env);
	} else if (leftInfo.type == VarInfo::EXPONENT || 
			   rightInfo.type == VarInfo::EXPONENT) {
		// want to get LHS * inv(RHS)
		// this only works if we are in a group with known order
		if (retGroup->getType() == Group::TYPE_PRIME) {
			ZZ ord = retGroup->getOrder();
			ZZ right = InvMod(rhs->eval(env), ord);
			return lhs->eval(env) * right;
			// in an RSA group, only permit computing 1/x if the caller
			// knows the order of the group
		} else if(retGroup->getType() == Group::TYPE_RSA && 
				  (retGroup->getOrder() != 0)) {
			ZZ ord = retGroup->getOrder();
			ZZ right = InvMod(rhs->eval(env), ord);
			return lhs->eval(env) * right;
		} else {
			throw CashException(CashException::CE_PARSE_ERROR,
								"That operation is not permitted in an RSA group");
		}
	} else {
		assert(retGroup);
		ZZ mod = retGroup->getModulus();
		return MulMod(lhs->eval(env), InvMod(rhs->eval(env), mod), mod);
	}
}	
Example #7
0
ZZ BankTool::identifyDoubleSpender(const Coin& coin1, const ZZ &tPrime2, 
								   const ZZ& rValue2) const {
	// Should probably check that the R values are different
	ZZ mod = coin1.getCashGroup()->getModulus();
	ZZ order = coin1.getCashGroup()->getOrder();
	ZZ t1 = coin1.getTPrime();
    ZZ t2 = tPrime2;
	ZZ r1 = coin1.getR();
    ZZ r2 = rValue2;

    if (r2 > r1) {
		NTL::swap(r2, r1);
		NTL::swap(t2, t1);
    }

	ZZ exp = InvMod(r1 - r2, order);
	ZZ num = PowerMod(t2, r1, mod);
	ZZ denom = InvMod(PowerMod(t1, r2, mod), mod);
	ZZ base = MulMod(num, denom, mod);
	ZZ publicKeyUser = PowerMod(base, exp, mod);
	
	return publicKeyUser;
}
Example #8
0
    long solve(int *S, int *R) { // start = S, each = R
        for (int i = 0; i < m; ++i) {
            visited[i] = false;
            inv[S[i]] = i;
        }

        long ret = 0, MOD = 1;
        for (int i = 0; i < m; ++i) {
            if (visited[i]) continue;
            // print("--- loop ---\n");
            int loop = 0;
            for (int j = i; !visited[j]; j = R[j]) {
                // print("{} ", j);
                visited[j] = true;
                vs[loop] = S[j] % 2;
                vr[loop] = j % 2;
                ++loop;
            }
            // print("\n");
            TIME += loop;

            int mod, rem;
            tie(mod, rem) = match(loop);
            // for (int i = 0; i < loop; ++i) {
            //     print("{} {}\n", vs[i], vr[i]);
            // }
            // print("mod = {}, rem = {}\n", mod, rem);

            if (mod == 0) {
                return 1e18;
            }
            long g = GCD(MOD, mod);
            if (ret % g != rem % g) {
                return 1e18;
            }
            // print("mod = {}, rem = {}\n", mod, rem);
            MOD /= g, mod /= g;
            long t = InvMod(MOD, mod) * ((rem - ret) / g % mod + mod) % mod;
            // print("t = {}\n", t);
            assert((t * MOD * g + ret) % (mod * g) == rem);
            ret = t * MOD * g + ret;
            MOD = MOD * mod * g;
            // print("MOD = {}, REM = {}\n", MOD, ret);

            // print("loop: {}\n", n);
        }
        return ret;
    }
Example #9
0
// Division by constant
// FIXME: this is not alias friendly
SingleCRT& SingleCRT::operator/=(const ZZ &num)
{
  const IndexSet& s = map.getIndexSet();
  ZZ pi, n;

  for (long i = s.first(); i <= s.last(); i = s.next(i)) {
    pi = to_ZZ(context.ithPrime(i));
    rem(n,num,pi);
    InvMod(n,n,pi);   // n = num^{-1} mod pi

    vec_ZZ& vp = map[i].rep;
    for (long j=0; j<vp.length(); j++) MulMod(vp[j], vp[j], n, pi);
    map[i].normalize();
  }
  return *this;
}
Example #10
0
// Процедура проверки подписи
void verifysign (ZZ &R, ZZ &r, ZZ &s, ZZ &e, Qxy &Q, Qxy &P, ZZ &q  )
{
    ZZ v, z1, z2;
    Qxy C;
    ZZ e1;
    if (InvModStatus( v, e, q ))
    {
        cout << "\nError in signature\n";
        goto end;
    }
    v = InvMod(e,q);
    z1 = (s*v)%q;
    z2 = (-r*v)%q;
    C = P*z1 + Q*z2;
    R = (conv<ZZ>(C.putx()))%q;

    cout << "\nv (dec) = \n" << v << endl;
    cout << "\nv (hex) = \n";
    show_dec_in_hex (v, L);
    cout << endl;

    cout << "\nz1 (dec) = \n" << z1 << endl;
    cout << "\nz1 (hex) = \n";
    show_dec_in_hex (z1, L);
    cout << endl;

    cout << "\nz2 (dec) = \n" << z2 << endl;
    cout << "\nz2 (hex) = \n";
    show_dec_in_hex (z2, L);
    cout << endl;

    cout << "\nPoint C:\n";
    C.putQxy();

    cout << "\nR (dec) = \n" << R << endl;
    cout << "\nR (hex) = \n";
    show_dec_in_hex (R, L);
    cout << endl;

end:
    if ( r == R )
        cout << "\nr = R\nSignature is OK";
    else
        cout << "\nSignature is FAILD";
    cout << endl;
}
Example #11
0
// mod-switch down to primeSet \intersect s, after this call we have
// primeSet<=s. s must contain either all special primes or none of them.
void Ctxt::modDownToSet(const IndexSet &s)
{
  IndexSet intersection = primeSet & s;
  //  assert(!empty(intersection));       // some primes must be left
  if (empty(intersection)) {
    cerr << "modDownToSet called from "<<primeSet<<" to "<<s<<endl;
    exit(1);
  }
  if (intersection==primeSet) return; // nothing to do, removing no primes
  FHE_TIMER_START;

  IndexSet setDiff = primeSet / intersection; // set-minus

  // Scale down all the parts: use either a simple "drop down" (just removing
  // primes, i.e., reducing the ctxt modulo the samaller modulus), or a "real
  // modulus switching" with rounding, basically whichever yeilds smaller
  // noise. Recall that we keep the invariant that a ciphertext mod Q is
  // decrypted to Q*m (mod p), so if we just "drop down" we still need to
  // multiply by (Q^{-1} mod p).

  // Get an estimate for the added noise term for modulus switching
  xdouble addedNoiseVar = modSwitchAddedNoiseVar();
  if (noiseVar*ptxtSpace*ptxtSpace < addedNoiseVar) {     // just "drop down"
    long prodInv = InvMod(rem(context.productOfPrimes(setDiff),ptxtSpace), ptxtSpace);
    for (size_t i=0; i<parts.size(); i++) {
      parts[i].removePrimes(setDiff);         // remove the primes not in s
      parts[i] *= prodInv;
      // WARNING: the following line is written just so to prevent overflow
      noiseVar = noiseVar*prodInv*prodInv;
    }
    //    cerr << "DEGENERATE DROP\n";
  } 
  else {                                      // do real mod switching
    for (size_t i=0; i<parts.size(); i++) 
      parts[i].scaleDownToSet(intersection, ptxtSpace);

    // update the noise estimate
    double f = context.logOfProduct(setDiff);
    noiseVar /= xexp(2*f);
    noiseVar += addedNoiseVar;
  }
  primeSet.remove(setDiff); // remove the primes not in s
  assert(verifyPrimeSet()); // sanity-check: ensure primeSet is still valid
  FHE_TIMER_STOP;
}
Example #12
0
// Divide a cipehrtext by p, for plaintext space p^r, r>1. It is assumed
// that the ciphertext encrypts a polynomial which is zero mod p. If this
// is not the case then the result will not be a valid ciphertext anymore.
// As a side-effect, the plaintext space is reduced from p^r to p^{r-1}.
void Ctxt::divideByP()
{
  // Special case: if *this is empty then do nothing
  if (this->isEmpty()) return;

  long p = getContext().zMStar.getP();
  assert (ptxtSpace>p);

  // multiply all the parts by p^{-1} mod Q (Q=productOfPrimes)
  ZZ pInverse, Q;
  getContext().productOfPrimes(Q, getPrimeSet());
  InvMod(pInverse, conv<ZZ>(p), Q);
  for (size_t i=0; i<parts.size(); i++)
    parts[i] *= pInverse;

  noiseVar /= (p * (double)p);  // noise is reduced by a p factor
  ptxtSpace /= p;               // and so is the plaintext space
}
Example #13
0
// generate all matrices of the form s(X^{g^i})->s(X) for generators g of
// Zm* /<2> and i<ord(g). If g has different orders in Zm* and Zm* /<2>
// then generate also matrices of the form s(X^{g^{-i}})->s(X)
void add1DMatrices(FHESecKey& sKey, long keyID)
{
  const FHEcontext &context = sKey.getContext();
  long m = context.zMStar.getM();

  // key-switching matrices for the automorphisms
  for (long i = 0; i < (long)context.zMStar.numOfGens(); i++) {
    for (long j = 1; j < (long)context.zMStar.OrderOf(i); j++) {
      long val = PowerMod(context.zMStar.ZmStarGen(i), j, m); // val = g^j
      // From s(X^val) to s(X)
      sKey.GenKeySWmatrix(1, val, keyID, keyID);
      if (!context.zMStar.SameOrd(i))
	// also from s(X^{1/val}) to s(X)
	sKey.GenKeySWmatrix(1, InvMod(val,m), keyID, keyID);
    }
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Example #14
0
// Apply F(X)->F(X^k) followed by re-liearization. The automorphism is possibly
// evaluated via a sequence of steps, to ensure that we can re-linearize the
// result of every step.
void Ctxt::smartAutomorph(long k) 
{
  FHE_TIMER_START;

  // A hack: record this automorphism rather than actually performing it
  if (isSetAutomorphVals()) { // defined in NumbTh.h
    recordAutomorphVal(k);
    return;
  }
  // Special case: if *this is empty then do nothing
  if (this->isEmpty()) return;

  // Sanity check: verify that k \in Zm*
  long m = context.zMStar.getM();
  k = mcMod(k, m);
  assert (context.zMStar.inZmStar(k));

  long keyID=getKeyID();
  if (!pubKey.isReachable(k,keyID)) {// must have key-switching matrices for it
    throw std::logic_error("no key-switching matrices for k="+std::to_string(k)
                           + ", keyID="+std::to_string(keyID));
  }

  if (!inCanonicalForm(keyID)) {     // Re-linearize the input, if needed
    reLinearize(keyID);
    assert (inCanonicalForm(keyID)); // ensure that re-linearization succeeded
  }

  while (k != 1) {
    const KeySwitch& matrix = pubKey.getNextKSWmatrix(k,keyID);
    long amt = matrix.fromKey.getPowerOfX();

    // A hack: record this automorphism rather than actually performing it
    if (isSetAutomorphVals2()) { // defined in NumbTh.h
      recordAutomorphVal2(amt);
      return;
    }
    //cerr << "********* automorph " << amt << "\n";
    automorph(amt);
    reLinearize(keyID);
    k = MulMod(k, InvMod(amt,m), m);
  }
  FHE_TIMER_STOP;
}
Example #15
0
// Assumes current zz_p modulus is p^r
// computes S = F^{-1} mod G via Hensel lifting
void InvModpr(zz_pX& S, const zz_pX& F, const zz_pX& G, long p, long r)
{
  ZZX ff, gg, ss, tt;

  ff = to_ZZX(F); 
  gg = to_ZZX(G);

  zz_pBak bak;
  bak.save();
  zz_p::init(p);

  zz_pX f, g, s, t;
  f = to_zz_pX(ff);
  g = to_zz_pX(gg);
  s = InvMod(f, g);
  t = (1-s*f)/g;
  assert(s*f + t*g == 1);
  ss = to_ZZX(s);
  tt = to_ZZX(t);

  ZZ pk = to_ZZ(1);

  for (long k = 1; k < r; k++) {
    // lift from p^k to p^{k+1}
    pk = pk * p;

    assert(divide(ss*ff + tt*gg - 1, pk));

    zz_pX d = to_zz_pX( (1 - (ss*ff + tt*gg))/pk );
    zz_pX s1, t1;
    s1 = (s * d) % g;
    t1 = (d-s1*f)/g;
    ss = ss + pk*to_ZZX(s1);
    tt = tt + pk*to_ZZX(t1);
  }

  bak.restore();

  S = to_zz_pX(ss);

  assert((S*F) % G == 1);
}
Example #16
0
ZZ PaillierParty::decrypt(const std::map<uint32_t,ZZ> &partialCiphers,
                          const std::vector<ZZ> &pubKeys) {
    ZZ sum(0);
    for (auto &pubKey : pubKeys) {
        sum = AddMod(sum,pubKey,m_n);
    }

    ZZ phi = MulMod(m_a,sum,m_n);

    ZZ prod(1);
    for (auto &partialCipher: partialCiphers) {
        uint32_t partyId = partialCipher.first;
        prod = MulMod(prod,PowerMod(partialCipher.second, 2*m_lagrangeBasis[partyId],m_field),m_field);
    }

    ZZ LResult = L_function(prod);

    ZZ combinedShare = InvMod(MulMod(4*m_delta*m_delta,phi,m_n),m_n);
    return MulMod(LResult, combinedShare, m_n);
}
Example #17
0
static void
init_representatives(Vec<long>& representatives, long dim, 
                     const Vec<long>& mvec, const PAlgebra& zMStar)
{
  assert(dim >= 0 && dim < mvec.length());

  // special case
  if (dim >= LONG(zMStar.numOfGens())) {
    representatives.SetLength(1);
    representatives[0] = 1;
    return;
  }
  
  long m = mvec[dim];
  long D = zMStar.OrderOf(dim);
  long g = InvMod(zMStar.ZmStarGen(dim) % m, m);

  representatives.SetLength(D);
  for (long i = 0; i < D; i++)
    representatives[i] = PowerMod(g, i, m);
}
Example #18
0
static void
init_representatives(Vec<long>& representatives, long dim, 
                     const Vec<long>& mvec, const PAlgebra& zMStar)
{
  //OLD: assert(dim >= 0 && dim < mvec.length());
  helib::assertInRange(dim, 0l, mvec.length(), "Invalid argument: dim must be between 0 and mvec.length()");

  // special case
  if (dim >= LONG(zMStar.numOfGens())) {
    representatives.SetLength(1);
    representatives[0] = 1;
    return;
  }
  
  long m = mvec[dim];
  long D = zMStar.OrderOf(dim);
  long g = InvMod(zMStar.ZmStarGen(dim) % m, m);

  representatives.SetLength(D);
  for (long i = 0; i < D; i++)
    representatives[i] = PowerMod(g, i, m);
}
Example #19
0
ZZ get_PowerMod(const ZZ& numar, const ZZ& exponent, const ZZ& baza)
{
	if (exponent == 0) 
		return to_ZZ(1);

	long k = NumBits(exponent);

	ZZ res;
	res = 1;

	for (long i = k-1; i >= 0; i--)
	{
		res = (res*res) % baza;
		if (bit(exponent, i) == 1)
			res = (res*numar) % n;
	}

	if (exponent < 0)
		return InvMod(res, baza);
	else
		return res;
}
Example #20
0
static
void compute_a_vals(Vec<ZZ>& a, long p, long e)
// computes a[m] = a(m)/m! for m = p..(e-1)(p-1)+1,
// as defined by Chen and Han.
// a.length() is set to (e-1)(p-1)+2

{
   ZZ p_to_e = power_ZZ(p, e);
   ZZ p_to_2e = power_ZZ(p, 2*e);

   long len = (e-1)*(p-1)+2;

   ZZ_pPush push(p_to_2e);

   ZZ_pX x_plus_1_to_p = power(ZZ_pX(INIT_MONO, 1) + 1, p);
   ZZ_pX denom = InvTrunc(x_plus_1_to_p - ZZ_pX(INIT_MONO, p), len);
   ZZ_pX poly = MulTrunc(x_plus_1_to_p, denom, len);
   poly *= p;

   a.SetLength(len);

   ZZ m_fac(1);
   for (long m = 2; m < p; m++) {
      m_fac = MulMod(m_fac, m, p_to_2e);
   }

   for (long m = p; m < len; m++) {
      m_fac = MulMod(m_fac, m, p_to_2e);
      ZZ c = rep(coeff(poly, m));
      ZZ d = GCD(m_fac, p_to_2e);
      if (d == 0 || d > p_to_e || c % d != 0) Error("cannot divide");
      ZZ m_fac_deflated = (m_fac / d) % p_to_e;
      ZZ c_deflated = (c / d) % p_to_e;
      a[m] = MulMod(c_deflated, InvMod(m_fac_deflated, p_to_e), p_to_e);
   }

}
Example #21
0
void
make_rsa_key(rsa_pub &pub, rsa_priv &priv, long bits, ZZ& e)
{
  pub.e = e;

  do
    {
      GenPrime(priv.p, bits/2);
    }
  while (!IsOne(GCD(priv.p-1, pub.e)));

  do
    {
      GenPrime(priv.q, bits/2);
    }
  while (!IsOne(GCD(priv.q-1, pub.e)));

  pub.N = priv.p * priv.q;

  priv.d = InvMod(pub.e, (priv.p-1)*(priv.q-1));

  rem(priv.dp1, priv.d, priv.p-1);
  rem(priv.dq1, priv.d, priv.q-1);
}
Example #22
0
long gauss(mat_zz_pE& M_in, long w)
{
   long k, l;
   long i, j;
   long pos;
   zz_pX t1, t2, t3;
   zz_pX *x, *y;

   long n = M_in.NumRows();
   long m = M_in.NumCols();

   if (w < 0 || w > m)
      Error("gauss: bad args");

   const zz_pXModulus& p = zz_pE::modulus();


   vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n];

   for (i = 0; i < n; i++) {
      M[i].SetLength(m);
      for (j = 0; j < m; j++) {
         M[i][j].rep.SetMaxLength(2*deg(p)-1);
         M[i][j] = rep(M_in[i][j]);
      }
   }

   l = 0;
   for (k = 0; k < w && l < n; k++) {

      pos = -1;
      for (i = l; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1)) {
            pos = i;
         }
      }

      if (pos != -1) {
         swap(M[pos], M[l]);

         InvMod(t3, M[l][k], p);
         negate(t3, t3);

         for (j = k+1; j < m; j++) {
            rem(M[l][j], M[l][j], p);
         }

         for (i = l+1; i < n; i++) {
            // M[i] = M[i] + M[l]*M[i,k]*t3

            MulMod(t1, M[i][k], t3, p);

            clear(M[i][k]);

            x = M[i].elts() + (k+1);
            y = M[l].elts() + (k+1);

            for (j = k+1; j < m; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(t2, t2, *x);
               *x = t2;
            }
         }

         l++;
      }
   }
   
   for (i = 0; i < n; i++)
      for (j = 0; j < m; j++)
         conv(M_in[i][j], M[i][j]);

   delete [] M;

   return l;
}
Example #23
0
void* worker(void* arg)
{
   State& state = *((State*) arg);
   long k = state.k;

#ifdef USE_THREADS
   pthread_mutex_lock(&state.lock);
#endif

   while (1)
   {
      if (state.next * BLOCK_SIZE < state.bound)
      {
         // need to generate more modular data
         
         long next = state.next++;
#ifdef USE_THREADS
         pthread_mutex_unlock(&state.lock);
#endif

         Item* item = new Item;

         mpz_set_ui(item->modulus, 1);
         mpz_set_ui(item->residue, 0);
         
         for (long p = max(5, state.table->next_prime(next * BLOCK_SIZE));
              p < state.bound && p < (next+1) * BLOCK_SIZE;
              p = state.table->next_prime(p))
         {
            if (k % (p-1) == 0)
               continue;

            // compute B_k mod p
            long b = bern_modp(p, k);
            
            // CRT into running total
            long x = MulMod(SubMod(b, mpz_fdiv_ui(item->residue, p), p),
                            InvMod(mpz_fdiv_ui(item->modulus, p), p), p);
            mpz_addmul_ui(item->residue, item->modulus, x);
            mpz_mul_ui(item->modulus, item->modulus, p);
         }
         
#ifdef USE_THREADS
         pthread_mutex_lock(&state.lock);
#endif
         state.items.insert(item);
      }
      else
      {
         // all modular data has been generated

         if (state.items.size() <= 1)
         {
            // no more CRTs for this thread to perform
#ifdef USE_THREADS
            pthread_mutex_unlock(&state.lock);
#endif
            return NULL;
         }
         
         // CRT two smallest items together
         Item* item1 = *(state.items.begin());
         state.items.erase(state.items.begin());
         Item* item2 = *(state.items.begin());
         state.items.erase(state.items.begin());
#ifdef USE_THREADS
         pthread_mutex_unlock(&state.lock);
#endif
         
         Item* item3 = CRT(item1, item2);
         delete item1;
         delete item2;

#ifdef USE_THREADS
         pthread_mutex_lock(&state.lock);
#endif
         state.items.insert(item3);
      }
   }
}
Example #24
0
newNTL_START_IMPL

zz_pInfoT::zz_pInfoT(long NewP, long maxroot)
{
   ref_count = 1;

   if (maxroot < 0) Error("zz_pContext: maxroot may not be negative");

   if (NewP <= 1) Error("zz_pContext: p must be > 1");
   if (NumBits(NewP) > newNTL_SP_NBITS) Error("zz_pContext: modulus too big");

   ZZ P, B, M, M1, MinusM;
   long n, i;
   long q, t;

   p = NewP;

   pinv = 1/double(p);

   index = -1;

   conv(P, p);

   sqr(B, P);
   LeftShift(B, B, maxroot+newNTL_FFTFudge);

   set(M);
   n = 0;
   while (M <= B) {
      UseFFTPrime(n);
      q = FFTPrime[n];
      n++;
      mul(M, M, q);
   }

   if (n > 4) Error("zz_pInit: too many primes");

   NumPrimes = n;
   PrimeCnt = n;
   MaxRoot = CalcMaxRoot(q);

   if (maxroot < MaxRoot)
      MaxRoot = maxroot;

   negate(MinusM, M);
   MinusMModP = rem(MinusM, p);

   if (!(CoeffModP = (long *) newNTL_MALLOC(n, sizeof(long), 0)))
      Error("out of space");

   if (!(x = (double *) newNTL_MALLOC(n, sizeof(double), 0)))
      Error("out of space");

   if (!(u = (long *) newNTL_MALLOC(n, sizeof(long), 0)))
      Error("out of space");

   for (i = 0; i < n; i++) {
      q = FFTPrime[i];

      div(M1, M, q);
      t = rem(M1, q);
      t = InvMod(t, q);
      mul(M1, M1, t);
      CoeffModP[i] = rem(M1, p);
      x[i] = ((double) t)/((double) q);
      u[i] = t;
   }
}
Example #25
0
YASHE::YASHE(long pModulus_,
             long log2CModulus,
             long cyclotomicDegree,
             long stdDev_,
             long log2Radix) {
  // Check if already written
  {
    std::string name = getFileName(pModulus_, log2CModulus, cyclotomicDegree, stdDev_, log2Radix);
    std::ifstream f(name.c_str());
    if (f.good()) {
      *this = readFromFile(name);
      return;
    }
  }

  pModulus = pModulus_;
  cModulus = NTL::GenPrime_ZZ(log2CModulus);
  bigPModulus = NTL::ZZ(pModulus);

  NTL::ZZ_p::init(cModulus);
  modulusRatio = NTL::conv<NTL::ZZ_p>(cModulus/pModulus);
  bigModulus = (cModulus * cModulus)/pModulus;

  if (NumberTheory::eulerToitient(cyclotomicDegree) < cModulus) {
    maxDegree = NumberTheory::eulerToitient(cyclotomicDegree) - 1;
    cycloModX = NumberTheory::cyclotomicPoly(cyclotomicDegree);
  } else {
    long smallCModulus = rem(cModulus, LONG_MAX);
    maxDegree = smallCModulus - 1;
    cycloModX = NTL::ZZX(NTL::INIT_MONO, smallCModulus) - 1;
  }

  cycloMod = NTL::ZZ_pXModulus(NTL::conv<NTL::ZZ_pX>(cycloModX));

  {
    NTL::ZZ_pPush push(bigPModulus); // switch to plain text modulus
    // Factor the cyclotomic polynomial modulo t
    // for batch encryption
    NTL::ZZ_pXModulus pModulusX;
    NTL::build(pModulusX, NTL::conv<NTL::ZZ_pX>(cycloModX));
    NTL::vec_ZZ_pX factors_;
    NTL::SFCanZass(factors_, pModulusX);
    factors.resize(factors_.length());
    for (long i = 0; i < factors_.length(); i++) {
      factors[i] = factors_[i];
    }

    crtElements.resize(factors.size());
    NTL::ZZ_pX fInv, fInvInv;
    for (long i = 0; i < factors.size(); i++) {
      div(fInv, NTL::conv<NTL::ZZ_pX>(cycloModX), factors[i]);
      rem(fInvInv, fInv, factors[i]);
      InvMod(fInvInv, fInvInv, factors[i]);
      crtElements[i] = MulMod(fInv, fInvInv, pModulusX);
    }
  }

  {
    NTL::ZZ_pPush push(bigModulus); // switch to multiplication modulus
    // make another modulus for fast multiplication
    bigCycloMod = NTL::ZZ_pXModulus(NTL::conv<NTL::ZZ_pX>(cycloModX));
  }

  stdDev = stdDev_;
  radix = NTL::power2_ZZ(log2Radix);
  decompSize = log(cModulus)/log(radix) + 1; // log_w(q) + 1

  randGen = std::mt19937(time(0));

  writeToFile(getFileName(pModulus, log2CModulus, cyclotomicDegree, stdDev, log2Radix));
}
Example #26
0
void ZZ_p::DoInstall()
{
   SmartPtr<ZZ_pTmpSpaceT> tmps = 0;

   do { // NOTE: thread safe lazy init 
      Lazy<ZZ_pFFTInfoT>::Builder builder(ZZ_pInfo->FFTInfo);
      if (!builder()) break;

      UniquePtr<ZZ_pFFTInfoT> FFTInfo;
      FFTInfo.make();

      ZZ B, M, M1, M2, M3;
      long n, i;
      long q, t;
      mulmod_t qinv;

      sqr(B, ZZ_pInfo->p);

      LeftShift(B, B, NTL_FFTMaxRoot+NTL_FFTFudge);

      // FIXME: the following is quadratic time...would
      // be nice to get a faster solution...
      // One could estimate the # of primes by summing logs,
      // then multiply using a tree-based multiply, then 
      // adjust up or down...

      // Assuming IEEE floating point, the worst case estimate
      // for error guarantees a correct answer +/- 1 for
      // numprimes up to 2^25...for sure we won't be
      // using that many primes...we can certainly put in 
      // a sanity check, though. 

      // If I want a more accuaruate summation (with using Kahan,
      // which has some portability issues), I could represent 
      // numbers as x = a + f, where a is integer and f is the fractional
      // part.  Summing in this representation introduces an *absolute*
      // error of 2 epsilon n, which is just as good as Kahan 
      // for this application.

      // same strategy could also be used in the ZZX HomMul routine,
      // if we ever want to make that subquadratic

      set(M);
      n = 0;
      while (M <= B) {
         UseFFTPrime(n);
         q = GetFFTPrime(n);
         n++;
         mul(M, M, q);
      }

      FFTInfo->NumPrimes = n;
      FFTInfo->MaxRoot = CalcMaxRoot(q);


      double fn = double(n);

      if (8.0*fn*(fn+48) > NTL_FDOUBLE_PRECISION)
         ResourceError("modulus too big");


      if (8.0*fn*(fn+48) <= NTL_FDOUBLE_PRECISION/double(NTL_SP_BOUND))
         FFTInfo->QuickCRT = true;
      else
         FFTInfo->QuickCRT = false;
      
      // FIXME: some of this stuff does not need to be initialized
      // at all if FFTInfo->crt_struct.special()

      FFTInfo->x.SetLength(n);
      FFTInfo->u.SetLength(n);
      FFTInfo->uqinv.SetLength(n);

      FFTInfo->rem_struct.init(n, ZZ_pInfo->p, GetFFTPrime);

      FFTInfo->crt_struct.init(n, ZZ_pInfo->p, GetFFTPrime);

      if (!FFTInfo->crt_struct.special()) {
         ZZ qq, rr;

         DivRem(qq, rr, M, ZZ_pInfo->p);

         NegateMod(FFTInfo->MinusMModP, rr, ZZ_pInfo->p);

         for (i = 0; i < n; i++) {
            q = GetFFTPrime(i);
            qinv = GetFFTPrimeInv(i);

            long tt = rem(qq, q);

            mul(M2, ZZ_pInfo->p, tt);
            add(M2, M2, rr); 
            div(M2, M2, q);  // = (M/q) rem p
            

            div(M1, M, q);
            t = rem(M1, q);
            t = InvMod(t, q);

            mul(M3, M2, t);
            rem(M3, M3, ZZ_pInfo->p);

            FFTInfo->crt_struct.insert(i, M3);


            FFTInfo->x[i] = ((double) t)/((double) q);
            FFTInfo->u[i] = t;
            FFTInfo->uqinv[i] = PrepMulModPrecon(FFTInfo->u[i], q, qinv);
         }
      }

      tmps = MakeSmart<ZZ_pTmpSpaceT>();
      tmps->crt_tmp_vec.fetch(FFTInfo->crt_struct);
      tmps->rem_tmp_vec.fetch(FFTInfo->rem_struct);

      builder.move(FFTInfo);
   } while (0);

   if (!tmps) {
      const ZZ_pFFTInfoT *FFTInfo = ZZ_pInfo->FFTInfo.get();
      tmps = MakeSmart<ZZ_pTmpSpaceT>();
      tmps->crt_tmp_vec.fetch(FFTInfo->crt_struct);
      tmps->rem_tmp_vec.fetch(FFTInfo->rem_struct);
   }

   ZZ_pTmpSpace = tmps;
}
Example #27
0
// Constructor: it is assumed that zms is already set with m>1
// If q == 0, then the current context is used
Cmodulus::Cmodulus(const PAlgebra &zms, long qq, long rt)
{
  assert(zms.getM()>1);
  bool explicitModulus = true;

  if (qq == 0) {
    q = zz_p::modulus();
    explicitModulus = false;
  }
  else
    q = qq;

  zMStar = &zms;
  root = rt;

  long mm;
  mm = zms.getM();
  m_inv = InvMod(mm, q);

  zz_pBak bak; 

  if (zms.getPow2()) {
    // special case when m is a power of 2

    assert( explicitModulus );
    bak.save();

    RandomState state;  SetSeed(conv<ZZ>("84547180875373941534287406458029"));
    // DIRT: this ensures the roots are deterministically generated
    //    inside the zz_pContext constructor
    context = zz_pContext(INIT_USER_FFT, q);
    state.restore();

    context.restore();

    powers.set_ptr(new zz_pX);
    ipowers.set_ptr(new zz_pX);


    long k = zms.getPow2();
    long phim = 1L << (k-1); 

    assert(k <= zz_pInfo->MaxRoot); 
    // rootTables get initialized 0..zz_pInfo->Maxroot

#ifdef FHE_OPENCL
    altFFTInfo = MakeSmart<AltFFTPrimeInfo>();
    InitAltFFTPrimeInfo(*altFFTInfo, *zz_pInfo->p_info, k-1);
#endif

    long w0 = zz_pInfo->p_info->RootTable[0][k];
    long w1 = zz_pInfo->p_info->RootTable[1][k];

    powers->rep.SetLength(phim);
    powers_aux.SetLength(phim);
    for (long i = 0, w = 1; i < phim; i++) {
      powers->rep[i] = w;
      powers_aux[i] = PrepMulModPrecon(w, q);
      w = MulMod(w, w0, q);
    }

    ipowers->rep.SetLength(phim);
    ipowers_aux.SetLength(phim);
    for (long i = 0, w = 1; i < phim; i++) {
      ipowers->rep[i] = w;
      ipowers_aux[i] = PrepMulModPrecon(w, q);
      w = MulMod(w, w1, q);
    }

  
    return;
  }

  if (explicitModulus) {
    bak.save(); // backup the current modulus
    context = BuildContext(q, NextPowerOfTwo(zms.getM()) + 1);
    context.restore();       // set NTL's current modulus to q
  }
  else
    context.save();

  if (root==0) { // Find a 2m-th root of unity modulo q, if not given
    zz_p rtp;
    long e = 2*zms.getM();
    FindPrimitiveRoot(rtp,e); // NTL routine, relative to current modulus
    if (rtp==0) // sanity check
      Error("Cmod::compRoots(): no 2m'th roots of unity mod q");
    root = rep(rtp);
  }
  rInv = InvMod(root,q); // set rInv = root^{-1} mod q

  // Allocate memory (relative to current modulus that was defined above).
  // These objects will be initialized when anyone calls FFT/iFFT.

  zz_pX phimx_poly;
  conv(phimx_poly, zms.getPhimX());

  powers.set_ptr(new zz_pX);
  Rb.set_ptr(new fftRep);
  ipowers.set_ptr(new zz_pX);
  iRb.set_ptr(new fftRep);
  phimx.set_ptr(new zz_pXModulus1(zms.getM(), phimx_poly));

  BluesteinInit(mm, conv<zz_p>(root), *powers, powers_aux, *Rb);
  BluesteinInit(mm, conv<zz_p>(rInv), *ipowers, ipowers_aux, *iRb);
}
Example #28
0
long CRT(mat_ZZ& gg, ZZ& a, const mat_zz_p& G)
{
    long n = gg.NumRows();
    long m = gg.NumCols();

    if (G.NumRows() != n || G.NumCols() != m)
        Error("CRT: dimension mismatch");

    long p = zz_p::modulus();

    ZZ new_a;
    mul(new_a, a, p);

    long a_inv;
    a_inv = rem(a, p);
    a_inv = InvMod(a_inv, p);

    long p1;
    p1 = p >> 1;

    ZZ a1;
    RightShift(a1, a, 1);

    long p_odd = (p & 1);

    long modified = 0;

    long h;

    ZZ g;
    long i, j;

    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
            if (!CRTInRange(gg[i][j], a)) {
                modified = 1;
                rem(g, gg[i][j], a);
                if (g > a1) sub(g, g, a);
            }
            else
                g = gg[i][j];

            h = rem(g, p);
            h = SubMod(rep(G[i][j]), h, p);
            h = MulMod(h, a_inv, p);
            if (h > p1)
                h = h - p;

            if (h != 0) {
                modified = 1;

                if (!p_odd && g > 0 && (h == p1))
                    MulSubFrom(g, a, h);
                else
                    MulAddTo(g, a, h);

            }

            gg[i][j] = g;
        }
    }

    a = new_a;

    return modified;

}
Example #29
0
void determinant(zz_pE& d, const mat_zz_pE& M_in)
{
   long k, n;
   long i, j;
   long pos;
   zz_pX t1, t2;
   zz_pX *x, *y;

   const zz_pXModulus& p = zz_pE::modulus();

   n = M_in.NumRows();

   if (M_in.NumCols() != n)
      Error("determinant: nonsquare matrix");

   if (n == 0) {
      set(d);
      return;
   }

   vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n];

   for (i = 0; i < n; i++) {
      M[i].SetLength(n);
      for (j = 0; j < n; j++) {
         M[i][j].rep.SetMaxLength(2*deg(p)-1);
         M[i][j] = rep(M_in[i][j]);
      }
   }

   zz_pX det;
   set(det);

   for (k = 0; k < n; k++) {
      pos = -1;
      for (i = k; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1))
            pos = i;
      }

      if (pos != -1) {
         if (k != pos) {
            swap(M[pos], M[k]);
            negate(det, det);
         }

         MulMod(det, det, M[k][k], p);

         // make M[k, k] == -1 mod p, and make row k reduced

         InvMod(t1, M[k][k], p);
         negate(t1, t1);
         for (j = k+1; j < n; j++) {
            rem(t2, M[k][j], p);
            MulMod(M[k][j], t2, t1, p);
         }

         for (i = k+1; i < n; i++) {
            // M[i] = M[i] + M[k]*M[i,k]

            t1 = M[i][k];   // this is already reduced

            x = M[i].elts() + (k+1);
            y = M[k].elts() + (k+1);

            for (j = k+1; j < n; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(*x, *x, t2);
            }
         }
      }
      else {
         clear(d);
         goto done;
      }
   }

   conv(d, det);

done:
   delete[] M;
}
Example #30
0
void inv(zz_pE& d, mat_zz_pE& X, const mat_zz_pE& A)
{
   long n = A.NumRows();
   if (A.NumCols() != n)
      Error("inv: nonsquare matrix");

   if (n == 0) {
      set(d);
      X.SetDims(0, 0);
      return;
   }

   long i, j, k, pos;
   zz_pX t1, t2;
   zz_pX *x, *y;

   const zz_pXModulus& p = zz_pE::modulus();


   vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n];

   for (i = 0; i < n; i++) {
      M[i].SetLength(2*n);
      for (j = 0; j < n; j++) {
         M[i][j].rep.SetMaxLength(2*deg(p)-1);
         M[i][j] = rep(A[i][j]);
         M[i][n+j].rep.SetMaxLength(2*deg(p)-1);
         clear(M[i][n+j]);
      }
      set(M[i][n+i]);
   }

   zz_pX det;
   set(det);

   for (k = 0; k < n; k++) {
      pos = -1;
      for (i = k; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1)) {
            pos = i;
         }
      }

      if (pos != -1) {
         if (k != pos) {
            swap(M[pos], M[k]);
            negate(det, det);
         }

         MulMod(det, det, M[k][k], p);

         // make M[k, k] == -1 mod p, and make row k reduced

         InvMod(t1, M[k][k], p);
         negate(t1, t1);
         for (j = k+1; j < 2*n; j++) {
            rem(t2, M[k][j], p);
            MulMod(M[k][j], t2, t1, p);
         }

         for (i = k+1; i < n; i++) {
            // M[i] = M[i] + M[k]*M[i,k]

            t1 = M[i][k];   // this is already reduced

            x = M[i].elts() + (k+1);
            y = M[k].elts() + (k+1);

            for (j = k+1; j < 2*n; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(*x, *x, t2);
            }
         }
      }
      else {
         clear(d);
         goto done;
      }
   }

   X.SetDims(n, n);
   for (k = 0; k < n; k++) {
      for (i = n-1; i >= 0; i--) {
         clear(t1);
         for (j = i+1; j < n; j++) {
            mul(t2, rep(X[j][k]), M[i][j]);
            add(t1, t1, t2);
         }
         sub(t1, t1, M[i][n+k]);
         conv(X[i][k], t1);
      }
   }

   conv(d, det);

done:
   delete[] M;
}