Esempio n. 1
0
static void add1Dmats4dim(FHESecKey& sKey, long i, long keyID)
{
  const FHEcontext &context = sKey.getContext();
  long m = context.zMStar.getM();
  computeParams(context,m,i); // defines vars: native, ord, gi, g2md, giminv, g2mdminv

  /* MAUTO vector<long> vals; */
  for (long j=1,val=gi; j < ord; j++) {
    // From s(X^val) to s(X)
    sKey.GenKeySWmatrix(1, val, keyID, keyID);
    if (!native) { // also from s(X^{g^{i-ord}}) to s(X)
      long val2 = MulModPrecon(val,g2md,m,g2mdminv);
      sKey.GenKeySWmatrix(1, val2, keyID, keyID);
      /* MAUTO vals.push_back(val2); */
    }
    /* MAUTO vals.push_back(val); */
    val = MulModPrecon(val, gi, m, giminv); // val *= g mod m (= g^{j+1})
  }

  if (!native) {
    sKey.GenKeySWmatrix(1, context.zMStar.genToPow(i, -ord), keyID, keyID);
  }


/* MAUTO
  sKey.resetTree(i,keyID); // remove existing tree, if any
  sKey.add2tree(i, 1, vals, keyID);
*/
}
Esempio n. 2
0
static void addMinimal1Dmats4dim(FHESecKey& sKey, long i, long keyID)
{
  const PAlgebra& zMStar = sKey.getContext().zMStar;
  long ord;
  bool native;

  if (i != -1) {
    ord = zMStar.OrderOf(i);
    native = zMStar.SameOrd(i);\
  }
  else {
    // Frobenius
    ord = zMStar.getOrdP();
    native = true;
  }

  sKey.GenKeySWmatrix(1, zMStar.genToPow(i, 1), keyID, keyID);

  if (!native)
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, -ord), keyID, keyID);

  if (ord > FHE_KEYSWITCH_MIN_THRESH) {
    long g = KSGiantStepSize(ord);
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, g), keyID, keyID);
  }

  sKey.setKSStrategy(i, FHE_KSS_MIN);

}
Esempio n. 3
0
void addTheseMatrices(FHESecKey& sKey,
		      const std::set<long>& automVals, long keyID)
{
  std::set<long>::iterator it;
  for (it=automVals.begin(); it!=automVals.end(); ++it) {
    long k = *it;
    sKey.GenKeySWmatrix(1, k, keyID, keyID);
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 4
0
// Generate all Frobenius matrices of the form s(X^{p^i})->s(X)
void addSomeFrbMatrices(FHESecKey& sKey, long bound, long keyID)
{
  const FHEcontext &context = sKey.getContext();
  if (bound >= LONG(context.zMStar.getOrdP()))
    add1Dmats4dim(sKey, -1, keyID);
  else  // For generators of large order, add only some of the powers
    addSome1Dmats4dim(sKey, -1, bound, keyID);

  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 5
0
void addMinimal1DMatrices(FHESecKey& sKey, long keyID)
{
  const FHEcontext &context = sKey.getContext();

  // key-switching matrices for the automorphisms
  for (long i: range(context.zMStar.numOfGens())) {
    addMinimal1Dmats4dim(sKey, i, keyID);
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 6
0
// Generate all Frobenius matrices of the form s(X^{2^i})->s(X)
void addFrbMatrices(FHESecKey& sKey, long keyID)
{
  const FHEcontext &context = sKey.getContext();
  long m = context.zMStar.getM();

  for (long j = 1; j < (long)context.zMStar.getOrdP(); j++) {
    long val = PowerMod(context.zMStar.getP(), j, m); // val = p^j mod m
    sKey.GenKeySWmatrix(1, val, keyID, keyID);
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 7
0
// A maximalistic approach: generate matrices s(X^e)->s(X) for all e \in Zm*
void addAllMatrices(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 < m; i++) {
    if (!context.zMStar.inZmStar(i)) continue;
    sKey.GenKeySWmatrix(1, i, keyID, keyID);
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 8
0
// generate only matrices of the form s(X^{g^i})->s(X), but not all of them.
// For a generator g whose order is larger than bound, generate only enough
// matrices for the giant-step/baby-step procedures (2*sqrt(ord(g))of them).
void addSome1DMatrices(FHESecKey& sKey, long bound, long keyID)
{
  const FHEcontext &context = sKey.getContext();

  // key-switching matrices for the automorphisms
  for (long i: range(context.zMStar.numOfGens())) {
          // For generators of small order, add all the powers
    if (bound >= context.zMStar.OrderOf(i))
      add1Dmats4dim(sKey, i, keyID);
    else  // For generators of large order, add only some of the powers
      addSome1Dmats4dim(sKey, i, bound, keyID);
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 9
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
}
Esempio n. 10
0
// Generate all key-switching matrices for a given permutation network
void addMatrices4Network(FHESecKey& sKey, const PermNetwork& net, long keyID)
{
  const FHEcontext &context = sKey.getContext();
  long m = context.zMStar.getM();

  for (long i=0; i<net.depth(); i++) {
    long e = net.getLayer(i).getE();
    long gIdx = net.getLayer(i).getGenIdx();
    long g = context.zMStar.ZmStarGen(gIdx);
    long g2e = PowerMod(g, e, m); // g^e mod m
    const Vec<long>&shamts = net.getLayer(i).getShifts();
    for (long j=0; j<shamts.length(); j++) {
      if (shamts[j]==0) continue;
      long val = PowerMod(g2e, shamts[j], m);
      sKey.GenKeySWmatrix(1, val, keyID, keyID);
    }
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 11
0
// generate only matrices of the form s(X^{g^i})->s(X), but not all of them.
// For a generator g whose order is larger than bound, generate only enough
// matrices for the giant-step/baby-step procedures (2*sqrt(ord(g))of them).
void addSome1DMatrices(FHESecKey& sKey, long bound, 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 generators of small order, add all the powers
    if (bound >= (long)context.zMStar.OrderOf(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);
      }
    else { // For generators of large order, add only some of the powers
      long num = SqrRoot(context.zMStar.OrderOf(i)); // floor(ord^{1/2})
      if (num*num < (long) context.zMStar.OrderOf(i)) num++; // ceil(ord^{1/2})

      // VJS: the above two lines replaces the following inexact calculation
      // with an exact calculation
      // long num = ceil(sqrt((double)context.zMStar.OrderOf(i)));

      for (long j=1; j <= num; j++) { // Add matrices for g^j and g^{j*num}
	long val1 = PowerMod(context.zMStar.ZmStarGen(i), j, m);  // g^j
	long val2 = PowerMod(context.zMStar.ZmStarGen(i),num*j,m);// g^{j*num}
	if (j < num) {
	  sKey.GenKeySWmatrix(1, val1, keyID, keyID);
	  sKey.GenKeySWmatrix(1, val2, keyID, keyID);
	}
	if (!context.zMStar.SameOrd(i)) {
	  //	  sKey.GenKeySWmatrix(1, InvMod(val1,m), keyID, keyID);
	  sKey.GenKeySWmatrix(1, InvMod(val2,m), keyID, keyID);
	}
      }

      // VJS: experimantal feature...because the replication code
      // uses rotations by -1, -2, -4, -8, we add a few
      // of these as well...only the small ones are important,
      // and we only need them if SameOrd(i)...
      // Note: we do indeed get a nontrivial speed-up

      if (context.zMStar.SameOrd(i)) {
        for (long k = 1; k <= num; k = 2*k) {
          long j = context.zMStar.OrderOf(i) - k;
          long val = PowerMod(context.zMStar.ZmStarGen(i), j, m); // val = g^j
          sKey.GenKeySWmatrix(1, val, keyID, keyID);
        }
      }
    }
  }
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}
Esempio n. 12
0
// same as above, but uses BS/GS strategy
static void addSome1Dmats4dim(FHESecKey& sKey, long i, long bound, long keyID)
{
  const PAlgebra& zMStar = sKey.getContext().zMStar;
  long ord;
  bool native;

  if (i != -1) {
    ord = zMStar.OrderOf(i);
    native = zMStar.SameOrd(i);\
  }
  else {
    // Frobenius
    ord = zMStar.getOrdP();
    native = true;
  }

  long g = KSGiantStepSize(ord);

  // baby steps
  for (long j = 1; j < g; j++)
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, j), keyID, keyID);

  // giant steps
  for (long j = g; j < ord; j += g)
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, j), keyID, keyID);

  if (!native)
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, -ord), keyID, keyID);

  sKey.setKSStrategy(i, FHE_KSS_BSGS);

  // NOTE: the old code also added matrices for ord-2^k for small k,
  // in the case of (native && i<context.zMStar.numOfGens()).
  // This supposedly speeds up the replication code, but for now
  // we are leaving this out, for simplicity.   Also, it is a waste
  // of space for applications that don't use replication.

}
Esempio n. 13
0
// adds all matrices for dim i.
// i == -1 => Frobenius (NOTE: in matmul1D, i ==#gens means something else,
//   so it is best to avoid that).
static void add1Dmats4dim(FHESecKey& sKey, long i, long keyID)
{
  const PAlgebra& zMStar = sKey.getContext().zMStar;
  long ord;
  bool native;

  if (i != -1) {
    ord = zMStar.OrderOf(i);
    native = zMStar.SameOrd(i);\
  }
  else {
    // Frobenius
    ord = zMStar.getOrdP();
    native = true;
  }

  for (long j = 1; j < ord; j++) 
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, j), keyID, keyID);

  if (!native)
    sKey.GenKeySWmatrix(1, zMStar.genToPow(i, -ord), keyID, keyID);

  sKey.setKSStrategy(i, FHE_KSS_FULL);
}
Esempio n. 14
0
void decryptAndPrint(ostream& s, const Ctxt& ctxt, const FHESecKey& sk,
		     const EncryptedArray& ea, long flags)
{
  const FHEcontext& context = ctxt.getContext();
  xdouble noiseEst = sqrt(ctxt.getNoiseVar());
  xdouble modulus = xexp(context.logOfProduct(ctxt.getPrimeSet()));
  vector<ZZX> ptxt;
  ZZX p, pp;
  sk.Decrypt(p, ctxt, pp);

  s << "plaintext space mod "<<ctxt.getPtxtSpace()
       << ", level="<<ctxt.findBaseLevel()
       << ", \n           |noise|=q*" << (coeffsL2Norm(pp)/modulus)
       << ", |noiseEst|=q*" << (noiseEst/modulus)
       <<endl;

  if (flags & FLAG_PRINT_ZZX) {
    s << "   before mod-p reduction=";
    printZZX(s,pp) <<endl;
  }
  if (flags & FLAG_PRINT_POLY) {
    s << "   after mod-p reduction=";
    printZZX(s,p) <<endl;
  }
  if (flags & FLAG_PRINT_VEC) {
    ea.decode(ptxt, p);
    if (ea.getAlMod().getTag() == PA_zz_p_tag
	&& ctxt.getPtxtSpace() != ea.getAlMod().getPPowR()) {
      long g = GCD(ctxt.getPtxtSpace(), ea.getAlMod().getPPowR());
      for (long i=0; i<ea.size(); i++)
	PolyRed(ptxt[i], g, true);
    }
    s << "   decoded to ";
    if (deg(p) < 40) // just pring the whole thing
      s << ptxt << endl;
    else if (ptxt.size()==1) // a single slot
      printZZX(s, ptxt[0]) <<endl;
    else { // print first and last slots
      printZZX(s, ptxt[0],20) << "--";
      printZZX(s, ptxt[ptxt.size()-1], 20) <<endl;      
    }
  }
}
Esempio n. 15
0
void checkCiphertext(const Ctxt& ctxt, const ZZX& ptxt, const FHESecKey& sk)
{
  const FHEcontext& context = ctxt.getContext();
  /*
  IndexSet base = baseSetOf(ctxt);
  double addedNoise = log(ctxt.modSwitchAddedNoiseVar());
  Ctxt tmp = ctxt;
  tmp.modDownToSet(base);
  double totalNoise = log(tmp.getNoiseVar());
  cout << "   @@@ log(added-noise)="<<addedNoise
       << ", log(total-noise)="<<totalNoise<<endl;
  */
  cout << " ln(q)="<< context.logOfProduct(ctxt.getPrimeSet())
       << ", ln(nVar)/2="<< log(ctxt.getNoiseVar())/2;
  //       << ", ln(nMag)="<< log(ctxt.getNoiseMag());

  ZZX res;
  //  sk.Decrypt(res, ctxt);
  ZZX f;
  sk.Decrypt(res, ctxt, f);
  cout << ", ln(mxPtxtCoef)=" << log(largestCoeff(f));

  // ensure we reduce the same way on both
  PolyRed((ZZX&)res,res,ctxt.getPtxtSpace(),true);
  PolyRed((ZZX&)ptxt,ptxt,ctxt.getPtxtSpace(),true);
  if (res != ptxt) {
    cout << ", failed\n";
    for (long i=0; i<=deg(ptxt); i++) if (coeff(res,i)!=coeff(ptxt,i)) {
	cout << "first mismatch in coeff "<<i<<": "
	     << coeff(res,i)<<"!="<<coeff(ptxt,i)<<"\n";
	break;
      }

    cout << "Timing information:\n";
    printAllTimers();
    cout << "\n";
    exit(0);
  }
  else cout << ", succeeded\n";
}
Esempio n. 16
0
static void addSome1Dmats4dim(FHESecKey& sKey, long i, long bound, long keyID)
{
  const FHEcontext &context = sKey.getContext();
  long m = context.zMStar.getM();
  computeParams(context,m,i); // defines vars: native, ord, gi, g2md, giminv, g2mdminv

  long baby, giant;
  std::tie(baby,giant) = computeSteps(ord, bound, native);

  for (long j=1,val=gi; j<=baby; j++) { // Add matrices for baby steps
    sKey.GenKeySWmatrix(1, val, keyID, keyID);
    if (!native) {
      long val2 = MulModPrecon(val,g2md,m,g2mdminv);
      sKey.GenKeySWmatrix(1, val2, keyID, keyID);
    }
    val = MulModPrecon(val, gi, m, giminv); // val *= g mod m (= g^{j+1})
   }

  long gb = PowerMod(gi,baby,m); // g^baby
  NTL::mulmod_precon_t gbminv = PrepMulModPrecon(gb, m);  
  for (long j=2,val=gb; j < giant; j++) { // Add matrices for giant steps
    val = MulModPrecon(val, gb, m, gbminv); // val = g^{(j+1)*baby}
    sKey.GenKeySWmatrix(1, val, keyID, keyID);
  }

  if (!native) {
    sKey.GenKeySWmatrix(1, context.zMStar.genToPow(i, -ord), keyID, keyID);
  }

  // VJS: experimantal feature...because the replication code
  // uses rotations by -1, -2, -4, -8, we add a few
  // of these as well...only the small ones are important,
  // and we only need them if SameOrd(i)...
  // Note: we do indeed get a nontrivial speed-up

  if (native && i<context.zMStar.numOfGens()) {
    for (long k = 1; k < giant; k = 2*k) {
      long j = ord - k;
      long val = PowerMod(gi, j, m); // val = g^j
      sKey.GenKeySWmatrix(1, val, keyID, keyID);
    }
  }

#if 0 
MAUTO

  // build the tree for this dimension, the internal nodes are 1 and
  // (subset of) gi^{giant}, gi^{2*giant}, ..., gi^{baby*giant}. We

  MAUTO sKey.resetTree(i,keyID); // remove existing tree, if any 

  // keep a list of all the elements that are covered by the tree so far,
  // initialized to only the root (=1).
  std::unordered_set<long> covered({1});

  // Make a list of the automorphisms for this dimension
  std::vector<long> autos;
  for (long j=1,val=gi; j<ord; j++) {
    // Do we have matrices for val and/or val/gi^{di}?
    if (!native) {
      long val2 = MulModPrecon(val, g2md, m, g2mdminv);
      if (sKey.haveKeySWmatrix(1,val2,keyID,keyID)) {
        autos.push_back(val2);
      }
    }
    if (sKey.haveKeySWmatrix(1,val,keyID,keyID)) {
      autos.push_back(val);
    }
    val = MulModPrecon(val, gi, m, giminv); // g^{j+1}
  }

  // Insert internal nodes and their children to tree
  for (long j=0,fromVal=1; j<giant; j++) {
    NTL::mulmod_precon_t fromminv = PrepMulModPrecon(fromVal, m);      
    vector<long> children;
    for (long k: autos) {
      long toVal = MulModPrecon(k, fromVal, m, fromminv);
      if (covered.count(toVal)==0) { // toVal not covered yet
        covered.insert(toVal);
        children.push_back(toVal);
      }
    }
    if (!children.empty()) { // insert fromVal with its children
      sKey.add2tree(i, fromVal, children, keyID);
    }
    fromVal = MulModPrecon(fromVal, gb, m, gbminv); // g^{(j+1)*baby}
  }

  // Sanity-check, did we cover everything?
  long toCover = native? ord: (2*ord-1);
  if (covered.size()<toCover)
    cerr << "**Warning: order-"<<ord<<" dimension, covered "<<covered.size()
         << " of "<<toCover<<endl;
#endif
}
Esempio n. 17
0
// Generate all Frobenius matrices of the form s(X^{p^i})->s(X)
void addMinimalFrbMatrices(FHESecKey& sKey, long keyID)
{
  addMinimal1Dmats4dim(sKey, -1, keyID);
  sKey.setKeySwitchMap(); // re-compute the key-switching map
}