Beispiel #1
0
void sampleGaussian(ZZX &poly, long n, double stdev)
{
  static double const Pi=4.0*atan(1.0); // Pi=3.1415..
  static long const bignum = 0xfffffff;
  // THREADS: C++11 guarantees these are initialized only once

  if (n<=0) n=deg(poly)+1; if (n<=0) return;
  poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial
  for (long i=0; i<n; i++) SetCoeff(poly, i, ZZ::zero());

  // Uses the Box-Muller method to get two Normal(0,stdev^2) variables
  for (long i=0; i<n; i+=2) {
    double r1 = (1+RandomBnd(bignum))/((double)bignum+1);
    double r2 = (1+RandomBnd(bignum))/((double)bignum+1);
    double theta=2*Pi*r1;
    double rr= sqrt(-2.0*log(r2))*stdev;

    assert(rr < 8*stdev); // sanity-check, no more than 8 standard deviations

    // Generate two Gaussians RV's, rounded to integers
    long x = (long) floor(rr*cos(theta) +0.5);
    SetCoeff(poly, i, x);
    if (i+1 < n) {
      x = (long) floor(rr*sin(theta) +0.5);
      SetCoeff(poly, i+1, x);
    }
  }
  poly.normalize(); // need to call this after we work on the coeffs
}
Beispiel #2
0
int main()
{
   zz_p::init(2);

   long i;

   vec_GF2 v;
   v.SetLength(5);
   v[1] = 1;
   v[0] = v[1];

   if (v[0] != v[1]) Error("BitMatTest not OK!!");

   for (i=0; i < 8; i++) {
      mat_zz_p a, x;
      mat_GF2 A, X, X1;

      long n = RandomBnd(500) + 1;
      long m = RandomBnd(500) + 1;
      cerr << n << " " << m << "\n";

      double t;

      random(a, n, m);

      t = GetTime();
      kernel(x, a);
      t = GetTime() - t;  cerr << t << "\n";

      cvt(A, a);

      t = GetTime();
      kernel(X, A);
      t = GetTime() - t;  cerr << t << "\n";

      cerr << x.NumRows() << "\n";

      cvt(X1, x);

      if (X1 != X) Error("BitMatTest NOT OK!!");

      if (!IsZero(X*A)) Error("BitMatTest NOT OK!!");

      cerr << "\n";
   }

   cerr << "BitMatTest OK\n";

}
Beispiel #3
0
long PrimeTest(const ZZ& n, long t)
{
   if (n <= 1) return 0;

   PrimeSeq s;  
   long p;

   p = s.next();
   while (p && p < 2000) {
      if ((n % p) == 0) return (n == p);
      p = s.next();  
   }

   ZZ x;
   long i;

   for (i = 0; i < t; i++)
   {
      x = RandomBnd(n); 

      if (witness(n, x)) 
         return 0;
   }

   return 1;
}
Beispiel #4
0
Wallet::Wallet(const ZZ &sk, const ZZ &sIn, const ZZ &tIn, int size,
			   int d, const BankParameters* bp, int st, int l, 
			   const hashalg_t &alg, const vector<ZZ> &sig)
	: sk_u(sk), s(sIn), t(tIn), walletSize(size), coinDenom(d), 
	  numCoinsUsed(0), params(bp), stat(st), lx(l), hashAlg(alg), 
	  signature(sig)
{
	// generate a list of the indices that haven't yet been added to
	// the spendOrder vector
	for(int i = 0; i < walletSize; i++) {
		//spendOrder[i] = i;
		spendOrder.push_back(i);
	}

	// fill the spendOrder vector
	// On iteration i, remaining free indices are values
	// remainingIndices[0], ..., remainingIndices[walletSize - i - 1]
	for(int i = 0; i < walletSize; i++) {
		int index = RandomBnd(walletSize);
		int temp = spendOrder[i];
		spendOrder[i] = spendOrder[index];
		spendOrder[index] = temp;
	}
#ifdef DEBUG
	for(int i = 0; i < walletSize; i++) {
		cout << spendOrder[i] << " ";
	}
#endif //DEBUG
}
Beispiel #5
0
// choose random curve
// if IsZero(Z), then X is non-trivial factor of ZZ_p::modulus()
void ECM_random_curve(EC_pCurve& curve, ZZ_p& X, ZZ_p& Z) {
  ZZ sigma;
  RandomBnd(sigma,ZZ_p::modulus()-6);
  sigma+=6;
  ZZ_p u,v;
  u = sqr(to_ZZ_p(sigma))-5;
  v = 4*to_ZZ_p(sigma);
  ZZ_p C,Cd;
  C = (v-u)*sqr(v-u)*(3*u+v);
  Cd = 4*u*sqr(u)*v;
  // make sure Cd is invertible
  ZZ Cinv;
  if (InvModStatus(Cinv,rep(Cd),ZZ_p::modulus())!=0) {
    conv(X,Cinv);
    clear(Z);
    return;
  }
  C*=to_ZZ_p(Cinv);
  C-=2;

  // random curve
  ZZ_pX f;
  SetCoeff(f,3);
  SetCoeff(f,2,C);
  SetCoeff(f,1);
  conv(curve,f);
  curve.SetRepresentation(curve.MONTGOMERY);

  // initial point
  mul(X,u,sqr(u));
  mul(Z,v,sqr(v));
}
Beispiel #6
0
// Генерация ключей
void genkeys ( ZZ &x, ZZ &y, ZZ &p, ZZ &q, ZZ &a)
{
	RandomBnd(x, q-1);			// Секретный ключ 
	PowerMod(y, a%p, x%p, p);	// Открытый ключ

	cout << "\nSecret key x = \n"; show_dec_in_hex (x, N);	cout << endl;
	cout << "\nPublic key y = \n"; show_dec_in_hex (y, L);	cout << endl;
}
Beispiel #7
0
ZZX RandPoly(long n,const ZZ& p)
{ 
  ZZX F; F.SetMaxLength(n);
  ZZ p2;  p2=p>>1;
  for (long i=0; i<n; i++)
    { SetCoeff(F,i,RandomBnd(p)-p2); }
  return F;
}
Beispiel #8
0
void randomizePlaintext(Plaintext &ptxt, unsigned deg, unsigned p) {
	ZZ_pX poly;
	poly.rep.SetLength(deg);
	for(unsigned i = 0; i < deg; i++) {
		poly.rep[i] = RandomBnd(p);
	}

	poly.normalize();
	ptxt.Init(poly);
}
Beispiel #9
0
NTL_CLIENT

int main()
{
   zz_p::init(17);

   zz_pX P;
   BuildIrred(P, 10);

   zz_pE::init(P);

   zz_pEX f, g, h;

   random(f, 20);
   SetCoeff(f, 20);

   random(h, 20);

   g = MinPolyMod(h, f);

   if (deg(g) < 0) Error("bad zz_pEXTest (1)");
   if (CompMod(g, h, f) != 0)
      Error("bad zz_pEXTest (2)");


   
   vec_pair_zz_pEX_long v;

   long i;
   for (i = 0; i < 5; i++) {
      long n = RandomBnd(20)+1;
      cerr << n << " ";

      random(f, n);
      SetCoeff(f, n);

      v = CanZass(f);

      g = mul(v);
      if (f != g) cerr << "oops1\n";

      long i;
      for (i = 0; i < v.length(); i++)
         if (!DetIrredTest(v[i].a))
            Error("bad zz_pEXTest (3)");


   }

   cerr << "\n";

   cerr << "zz_pEXTest OK\n";
}
Beispiel #10
0
void IndexCalc::IndexCalculus(){
	ZZ y;
	long limit = primeNumbers.length();
	
	ZZ x;

	for(long i = 0; i < 4*limit; i++){
		x =  RandomBnd(p) + 1;


	}
	

}
Beispiel #11
0
// Generate a random permutation on [0..n-1]
void randomPerm(Permut& perm, long n)
{
  perm.SetLength(n);
  for (long j = 0; j < n; j++)
     perm[j] = j;
   
  // random shuffle
  for (long m = n; m > 0; m--) {
     long p = RandomBnd(m);
     // swap positions p and m-1 of perm
     long tmp = perm[p];
     perm[p] = perm[m-1];
     perm[m-1] = tmp;
  }
}
Beispiel #12
0
template <typename T> vec_ZZ RandomPoint(LatticeBasis<T>& B,int seed,int dim=0) {
    //Generate uniformly random point in the box \prod[-b*i/2,b*i/2]
    B.updateGSBasis();
    vec_ZZ ret;

    ZZ det = LatticeVolumeZZ(B);
    if (dim==0) dim = B.dim;
    ret.SetLength(dim);
    SetSeed(to_ZZ(seed));
    for (int i=0;i<dim;i++) {
        ret[i] = RandomBnd(det);
    }
    ret = NearestPlane(ret,B);
    
    return ret;
    
}
Beispiel #13
0
//  Генерация ЭЦП
void gensign ( ZZ &r, ZZ &s, ZZ &H, ZZ &x, ZZ &p, ZZ &q, ZZ &a)
{
	ZZ k;
	while ( s == 0 )
	{
		RandomBnd(k, q);			// Случайное число k
		r = PowerMod(a%p, k%p, p) % q;
		if ( r == 0 )
			continue;
		s = (x * r + k * H ) % q;
		if ( s == 0 )
			continue;
	}
	cout << "\nGenerate sign\n";
	cout << "\nSession key k = \n"; show_dec_in_hex (H, N);	cout << endl;
	cout << "\nr = \n"; show_dec_in_hex (r, N);	cout << endl;
	cout << "\ns = \n"; show_dec_in_hex (s, N);	cout << endl;
}
Beispiel #14
0
// same as ProbPrime(), but with no trial division stage
bool ProbPrime_notd(const ZZ& n, long NumTrials=10) {
  // first try W == 2....the exponentiation
  // algorithm runs slightly faster in this case
  ZZ W;
  W = 2;
  if (MillerWitness(n, W))
    return false;

  while (--NumTrials>=0) {
    do {
      RandomBnd(W,n);
    } while (IsZero(W));
    // W == 0 is not a useful candidate for a witness!
    if (MillerWitness(n, W))
      return false;
  }
  return true;
}
Beispiel #15
0
template <typename T> mat_ZZ RandomPoints(LatticeBasis<T>& B,int seed,int numrows,int dim=0) {

    B.updateGSBasis();
    vec_ZZ r;
    ZZ det = LatticeVolumeZZ(B);
    if (dim==0) dim = B.dim;
    r.SetLength(dim);

    mat_ZZ ret;
    ret.SetDims(numrows,dim);
    
    SetSeed(to_ZZ(seed));
    
    for (int k=0;k<numrows;k++) {
        for (int i=0;i<dim;i++) {
            r[i] = RandomBnd(det);
        }
        ret[k] = NearestPlane(r,B);
    }
    return ret;
}
Beispiel #16
0
  RandomMatrix(const EncryptedArray& _ea) : ea(_ea) { 
    long n = ea.size();
    long d = ea.getDegree();

    long bnd = 2*n; // non-zero with probability 1/bnd

    RBak bak; bak.save(); ea.getContext().alMod.restoreContext();

    data.resize(n);
    for (long i = 0; i < n; i++) {
      data[i].resize(n);
      for (long j = 0; j < n; j++) {
        bool zEntry = (RandomBnd(bnd) > 0);

        if (zEntry)
          clear(data[i][j]);
        else
          random(data[i][j], d);
      }
    }
  }
Beispiel #17
0
void sampleUniform(ZZX& poly, const ZZ& B, long n)
{
  if (n<=0) n=deg(poly)+1; if (n<=0) return;
  if (B <= 0) {
    clear(poly);
    return;
  }

  poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial

  ZZ UB, tmp;

  UB =  2*B + 1;
  for (long i = 0; i < n; i++) {
    RandomBnd(tmp, UB);
    tmp -= B; 
    poly.rep[i] = tmp;
  }

  poly.normalize();
}
Beispiel #18
0
/************** Each round consists of the following:
1. c1.multiplyBy(c0)
2. c0 += random constant
3. c2 *= random constant
4. tmp = c1
5. ea.rotate(tmp, random amount in [-nSlots/2, nSlots/2])
6. c2 += tmp
7. ea.rotate(c2, random amount in [1-nSlots, nSlots-1])
8. c1.negate()
9. c3.multiplyBy(c2) 
10. c0 -= c3
**************/
void testGeneralOps(const FHEPubKey& publicKey, const FHESecKey& secretKey,
                    const EncryptedArrayCx& ea, double epsilon,
                    long nRounds)
{
  long nslots = ea.size();
  char buffer[32];

  vector<cx_double> p0, p1, p2, p3;
  ea.random(p0);
  ea.random(p1);
  ea.random(p2);
  ea.random(p3);

  Ctxt c0(publicKey), c1(publicKey), c2(publicKey), c3(publicKey);
  ea.encrypt(c0, publicKey, p0, /*size=*/1.0);
  ea.encrypt(c1, publicKey, p1, /*size=*/1.0);
  ea.encrypt(c2, publicKey, p2, /*size=*/1.0);
  ea.encrypt(c3, publicKey, p3, /*size=*/1.0);

  resetAllTimers();
  FHE_NTIMER_START(Circuit);

  for (long i = 0; i < nRounds; i++) {

    if (verbose) std::cout << "*** round " << i << "..."<<endl;

     long shamt = RandomBnd(2*(nslots/2) + 1) - (nslots/2);
                  // random number in [-nslots/2..nslots/2]
     long rotamt = RandomBnd(2*nslots - 1) - (nslots - 1);
                  // random number in [-(nslots-1)..nslots-1]

     // two random constants
     vector<cx_double> const1, const2;
     ea.random(const1);
     ea.random(const2);

     ZZX const1_poly, const2_poly;
     ea.encode(const1_poly, const1, /*size=*/1.0);
     ea.encode(const2_poly, const2, /*size=*/1.0);

     mul(p1, p0);     // c1.multiplyBy(c0)
     c1.multiplyBy(c0);
     if (verbose) {
       CheckCtxt(c1, "c1*=c0");
       debugCompare(ea, secretKey, p1, c1, epsilon);
     }

     add(p0, const1); // c0 += random constant
     c0.addConstant(const1_poly);
     if (verbose) {
       CheckCtxt(c0, "c0+=k1");
       debugCompare(ea, secretKey, p0, c0, epsilon);
     }
     mul(p2, const2); // c2 *= random constant
     c2.multByConstant(const2_poly);
     if (verbose) {
       CheckCtxt(c2, "c2*=k2");
       debugCompare(ea, secretKey, p2, c2, epsilon);
     }
     vector<cx_double> tmp_p(p1); // tmp = c1
     Ctxt tmp(c1);
     sprintf(buffer, "tmp=c1>>=%d", (int)shamt);
     rotate(tmp_p, shamt); // ea.shift(tmp, random amount in [-nSlots/2,nSlots/2])
     ea.rotate(tmp, shamt);
     if (verbose) {
       CheckCtxt(tmp, buffer);
       debugCompare(ea, secretKey, tmp_p, tmp, epsilon);
     }
     add(p2, tmp_p);  // c2 += tmp
     c2 += tmp;
     if (verbose) {
       CheckCtxt(c2, "c2+=tmp");
       debugCompare(ea, secretKey, p2, c2, epsilon);
     }
     sprintf(buffer, "c2>>>=%d", (int)rotamt);
     rotate(p2, rotamt); // ea.rotate(c2, random amount in [1-nSlots, nSlots-1])
     ea.rotate(c2, rotamt);
     if (verbose) {
       CheckCtxt(c2, buffer);
       debugCompare(ea, secretKey, p2, c2, epsilon);
     }
     negateVec(p1); // c1.negate()
     c1.negate();
     if (verbose) {
       CheckCtxt(c1, "c1=-c1");
       debugCompare(ea, secretKey, p1, c1, epsilon);
     }
     mul(p3, p2); // c3.multiplyBy(c2) 
     c3.multiplyBy(c2);
     if (verbose) {
       CheckCtxt(c3, "c3*=c2");
       debugCompare(ea, secretKey, p3, c3, epsilon);
     }
     sub(p0, p3); // c0 -= c3
     c0 -= c3;
     if (verbose) {
       CheckCtxt(c0, "c0=-c3");
       debugCompare(ea, secretKey, p0, c0, epsilon);
     }
  }

  c0.cleanUp();
  c1.cleanUp();
  c2.cleanUp();
  c3.cleanUp();

  FHE_NTIMER_STOP(Circuit);

  vector<cx_double> pp0, pp1, pp2, pp3;
   
  ea.decrypt(c0, secretKey, pp0);
  ea.decrypt(c1, secretKey, pp1);
  ea.decrypt(c2, secretKey, pp2);
  ea.decrypt(c3, secretKey, pp3);

  std::cout << "Test "<<nRounds<<" rounds of mixed operations, ";
  if (cx_equals(pp0, p0,conv<double>(epsilon*c0.getPtxtMag()))
      && cx_equals(pp1, p1,conv<double>(epsilon*c1.getPtxtMag()))
      && cx_equals(pp2, p2,conv<double>(epsilon*c2.getPtxtMag()))
      && cx_equals(pp3, p3,conv<double>(epsilon*c3.getPtxtMag())))
    std::cout << "PASS\n\n";
  else {
    std::cout << "FAIL:\n";
    std::cout << "  max(p0)="<<largestCoeff(p0)
              << ", max(pp0)="<<largestCoeff(pp0)
              << ", maxDiff="<<calcMaxDiff(p0,pp0) << endl;
    std::cout << "  max(p1)="<<largestCoeff(p1)
              << ", max(pp1)="<<largestCoeff(pp1)
              << ", maxDiff="<<calcMaxDiff(p1,pp1) << endl;
    std::cout << "  max(p2)="<<largestCoeff(p2)
              << ", max(pp2)="<<largestCoeff(pp2)
              << ", maxDiff="<<calcMaxDiff(p2,pp2) << endl;
    std::cout << "  max(p3)="<<largestCoeff(p3)
              << ", max(pp3)="<<largestCoeff(pp3)
              << ", maxDiff="<<calcMaxDiff(p3,pp3) << endl<<endl;
  }

  if (verbose) {
    std::cout << endl;
    printAllTimers();
    std::cout << endl;
  }
  resetAllTimers();
   }
Beispiel #19
0
long IsFFTPrime(long n, long& w)
{
   long  m, x, y, z;
   long j, k;


   if (n <= 1 || n >= NTL_SP_BOUND) return 0;

   if (n % 2 == 0) return 0;

   if (n % 3 == 0) return 0;

   if (n % 5 == 0) return 0;

   if (n % 7 == 0) return 0;
   
   m = n - 1;
   k = 0;
   while ((m & 1) == 0) {
      m = m >> 1;
      k++;
   }

   for (;;) {
      x = RandomBnd(n);

      if (x == 0) continue;
      z = PowerMod(x, m, n);
      if (z == 1) continue;

      x = z;
      j = 0;
      do {
         y = z;
         z = MulMod(y, y, n);
         j++;
      } while (j != k && z != 1);

      if (z != 1 || y !=  n-1) return 0;

      if (j == k) 
         break;
   }

   /* x^{2^k} = 1 mod n, x^{2^{k-1}} = -1 mod n */

   long TrialBound;

   TrialBound = m >> k;
   if (TrialBound > 0) {
      if (!ProbPrime(n, 5)) return 0;
   
      /* we have to do trial division by special numbers */
   
      TrialBound = SqrRoot(TrialBound);
   
      long a, b;
   
      for (a = 1; a <= TrialBound; a++) {
         b = (a << k) + 1;
         if (n % b == 0) return 0; 
      }
   }

   /* n is an FFT prime */

   for (j = NTL_FFTMaxRoot; j < k; j++)
      x = MulMod(x, x, n);

   w = x;
   return 1;
}
Beispiel #20
0
int main()
{

#ifdef NTL_LONG_LONG


   if (sizeof(NTL_LL_TYPE) < 2*sizeof(long)) {
      printf("999999999999999 ");
      print_flag();
      return 0;
   }

#endif

   SetSeed(ZZ(0));

   long i, k;

   
   k = 10*NTL_ZZ_NBITS;

   for (i = 0; i < 10000; i++) {
      ZZ a, b, c, d;
      long da = RandomBnd(k);
      long db = RandomBnd(k);
      long dc = RandomBnd(k);
      long dd = RandomBnd(k);
      RandomLen(a, da);  RandomLen(b, db);  RandomLen(c, dc);  RandomLen(d, dd);

      if ((a + b)*(c + d) != c*a + d*a + c*b + d*b) {
	 printf("999999999999999 ");
	 print_flag();
	 return 0;
      }
   }

   

   for (i = 0; i < 10000; i++) {
      ZZ a, b, c;
      
      long da = RandomBnd(k);
      long db = RandomBnd(k);
      long dc = RandomBnd(k) + 2;
      
      RandomLen(a, da);  RandomLen(b, db);  RandomLen(c, dc); 

      if ( ( a * b ) % c != ((a % c) * (b % c)) % c ) {
	 printf("999999999999999 ");
	 print_flag();
	 return 0;
      }
   }

   k = 1024;

   ZZ x1, x2, x3;
   double t;
   long j;

   RandomLen(x1, k);
   RandomLen(x2, k);
   

   long iter;

   mul(x3, x1, x2);

   iter = 1;

   do {
     t = GetTime();
     for (i = 0; i < iter; i++) {
        for (j = 0; j < 500; j++) mul(x3, x1, x2);
      }
     t = GetTime() - t;
     iter = 2*iter;
   } while(t < 1);


   iter = iter/2;
   iter = long((3/t)*iter) + 1;

   double tvec[5];
   long w;

   for (w = 0; w < 5; w++) {
     t = GetTime();
     for (i = 0; i < iter; i++) {
        for (j = 0; j < 500; j++) mul(x3, x1, x2);
      }
     t = GetTime() - t;
     tvec[w] = t;
   }

   t = clean_data(tvec);

   t = floor((t/iter)*1e14);

   if (t < 0 || t >= 1e15)
      printf("999999999999999 ");
   else
      printf("%015.0f ", t);

   printf(" [%ld] ", iter);

   print_flag();

   return 0;
}
Beispiel #21
0
int main()
{


   cerr << "This is NTL version " << NTL_VERSION << "\n"; 

   cerr << "Basic Configuration Options:\n";


#ifdef NTL_STD_CXX
   cerr << "NTL_STD_CXX\n";
#endif

#ifdef NTL_PSTD_NNS
   cerr << "NTL_PSTD_NNS\n";
#endif

#ifdef NTL_PSTD_NHF
   cerr << "NTL_PSTD_NHF\n";
#endif

#ifdef NTL_PSTD_NTN
   cerr << "NTL_PSTD_NTN\n";
#endif

#ifdef NTL_GMP_LIP
   cerr << "NTL_GMP_LIP\n";
#endif

#ifdef NTL_GMP_HACK
   cerr << "NTL_GMP_HACK\n";
#endif

#ifdef NTL_GF2X_LIB
   cerr << "NTL_GF2X_LIB\n";
#endif


#ifdef NTL_LONG_LONG_TYPE
   cerr << "NTL_LONG_LONG_TYPE: ";
   cerr << make_string(NTL_LONG_LONG_TYPE) << "\n";
#endif

#ifdef NTL_UNSIGNED_LONG_LONG_TYPE
   cerr << "NTL_UNSIGNED_LONG_LONG_TYPE: ";
   cerr << make_string(NTL_UNSIGNED_LONG_LONG_TYPE) << "\n";
#endif

#ifdef NTL_CXX_ONLY
   cerr << "NTL_CXX_ONLY\n";
#endif


#ifdef NTL_X86_FIX
   cerr << "NTL_X86_FIX\n";
#endif

#ifdef NTL_NO_X86_FIX
   cerr << "NTL_NO_X86_FIX\n";
#endif

#ifdef NTL_NO_INIT_TRANS
   cerr << "NTL_NO_INIT_TRANS\n";
#endif

#ifdef NTL_CLEAN_INT
   cerr << "NTL_CLEAN_INT\n";
#endif

#ifdef NTL_CLEAN_PTR
   cerr << "NTL_CLEAN_PTR\n";
#endif

#ifdef NTL_RANGE_CHECK
   cerr << "NTL_RANGE_CHECK\n";
#endif


cerr << "\n";
cerr << "Resolution of double-word types:\n";
cerr << make_string(NTL_LL_TYPE) << "\n";
cerr << make_string(NTL_ULL_TYPE) << "\n";


cerr << "\n";
cerr << "Performance Options:\n";

#ifdef NTL_LONG_LONG
   cerr << "NTL_LONG_LONG\n";
#endif

#ifdef NTL_AVOID_FLOAT
   cerr << "NTL_AVOID_FLOAT\n";
#endif

#ifdef NTL_SPMM_UL
   cerr << "NTL_SPMM_UL\n";
#endif


#ifdef NTL_SPMM_ULL
   cerr << "NTL_SPMM_ULL\n";
#endif


#ifdef NTL_SPMM_ASM
   cerr << "NTL_SPMM_ASM\n";
#endif




#ifdef NTL_AVOID_BRANCHING
   cerr << "NTL_AVOID_BRANCHING\n";
#endif



#ifdef NTL_TBL_REM
   cerr << "NTL_TBL_REM\n";
#endif


#ifdef NTL_GF2X_ALTCODE
   cerr << "NTL_GF2X_ALTCODE\n";
#endif

#ifdef NTL_GF2X_ALTCODE1
   cerr << "NTL_GF2X_ALTCODE1\n";
#endif


#ifdef NTL_GF2X_NOINLINE
   cerr << "NTL_GF2X_NOINLINE\n";
#endif

   cerr << "\n\n";

   if (_ntl_gmp_hack)
      cerr << "using GMP hack\n\n";

   cerr << "running tests...";

   long n, k;

   n = 200;
   k = 10*NTL_ZZ_NBITS;

   ZZ p;

   GenPrime(p, k);


   ZZ_p::init(p);         // initialization

   ZZ_pX f, g, h, r1, r2, r3;

   random(g, n);    // g = random polynomial of degree < n
   random(h, n);    // h =             "   "
   random(f, n);    // f =             "   "

   // SetCoeff(f, n);  // Sets coefficient of X^n to 1
   
   ZZ_p lc;

   do {
      random(lc);
   } while (IsZero(lc));

   SetCoeff(f, n, lc);


   // For doing arithmetic mod f quickly, one must pre-compute
   // some information.

   ZZ_pXModulus F;
   build(F, f);

   PlainMul(r1, g, h);  // this uses classical arithmetic
   PlainRem(r1, r1, f);

   MulMod(r2, g, h, F);  // this uses the FFT

   MulMod(r3, g, h, f);  // uses FFT, but slower

   // compare the results...

   if (r1 != r2) {
      cerr << "r1 != r2!!\n";
      return 1;
   }
   else if (r1 != r3) {
      cerr << "r1 != r3!!\n";
      return 1;
   }


   // small prime tests...I've made some changes in v5.3
   // that should be checked on various platforms, so 
   // we might as well check them here.

   if (SmallModulusTest(17, 1000)) {
      cerr << "first SmallModulusTest failed!!\n";
      return 1;
   }

   if (SmallModulusTest((1L << (NTL_SP_NBITS))-1, 1000)) {
      cerr << "second SmallModulusTest failed!!\n";
      return 1;
   }

   // Test gf2x code....

   if (GF2X_test()) {
      cerr << "GF2X test failed!\n";
      return 1;
   }
   

   cerr << "OK\n";

   ZZ x1, x2, x3, x4;
   double t;
   long i;

   RandomLen(x1, 1024);
   RandomBnd(x2, x1);
   RandomBnd(x3, x1);

   mul(x4, x2, x3);

   t = GetTime();
   for (i = 0; i < 100000; i++)
      mul(x4, x2, x3);
   t = GetTime()-t;

   cerr << "time for 1024-bit mul: " << t*10 << "us";

   if (_ntl_gmp_hack) {
      _ntl_gmp_hack = 0;
      mul(x4, x2, x3);

      t = GetTime();
      for (i = 0; i < 100000; i++)
         mul(x4, x2, x3);
      t = GetTime()-t;

      cerr << " (" << (t*10) << "us without GMP)"; 

      _ntl_gmp_hack = 1;
   }

   cerr << "\n";

   rem(x2, x4, x1);

   t = GetTime();
   for (i = 0; i < 100000; i++)
      rem(x2, x4, x1);
   t = GetTime()-t;

   cerr << "time for 2048/1024-bit rem: " << t*10 << "us";

   if (_ntl_gmp_hack) {
      _ntl_gmp_hack = 0;
      rem(x2, x4, x1);
   
      t = GetTime();
      for (i = 0; i < 100000; i++)
         rem(x2, x4, x1);
      t = GetTime()-t;
      cerr << " (" << (t*10) << "us without GMP)"; 

      _ntl_gmp_hack = 1;
   }

   cerr << "\n";
   

   GenPrime(p, 1024);
   RandomBnd(x1, p);
   if (IsZero(x1)) set(x1);

   InvMod(x2, x1, p);

   t = GetTime();
   for (i = 0; i < 1000; i++)
      InvMod(x2, x1, p);
   t = GetTime()-t;

   cerr << "time for 1024-bit modular inverse: " << t*1000 << "us";

   if (_ntl_gmp_hack) {
      _ntl_gmp_hack = 0;
      InvMod(x2, x1, p);
   
      t = GetTime();
      for (i = 0; i < 1000; i++)
         InvMod(x2, x1, p);
      t = GetTime()-t;
         cerr << " (" << (t*1000) << "us without GMP)"; 

      _ntl_gmp_hack = 1;
   }

   cerr << "\n";



   // test modulus switching
   
   n = 1024;
   k = 1024;
   RandomLen(p, k);

   ZZ_p::init(p);
   ZZ_pInfo->check();

   ZZ_pX j1, j2, j3;

   random(j1, n);
   random(j2, n);

   t = GetTime();
   for (i = 0; i < 20; i++) mul(j3, j1, j2);
   t = GetTime()-t;

   cerr << "time to multiply degree 1023 polynomials\n   modulo a 1024-bit number: ";
   cerr << (t/20) << "s";

   if (_ntl_gmp_hack) {
      _ntl_gmp_hack = 0;

      ZZ_p::init(p);
      ZZ_pInfo->check();

      t = GetTime();
      for (i = 0; i < 20; i++) mul(j3, j1, j2);
      t = GetTime()-t;

      cerr << " (" << (t/20) << "s without GMP)";
      _ntl_gmp_hack = 1;
   }

   cerr << "\n";

   GF2X_time();

   return 0;
}
Beispiel #22
0
int main()
{

#ifdef NTL_SPMM_ULL

   if (sizeof(NTL_ULL_TYPE) < 2*sizeof(long)) {
      printf("999999999999999 ");
      print_flag();
      return 0;
   }

#endif


   long n, k;

   n = 200;
   k = 10*NTL_ZZ_NBITS;

   ZZ p;

   RandomLen(p, k);


   ZZ_p::init(p);         // initialization

   ZZ_pX f, g, h, r1, r2, r3;

   random(g, n);    // g = random polynomial of degree < n
   random(h, n);    // h =             "   "
   random(f, n);    // f =             "   "

   SetCoeff(f, n);  // Sets coefficient of X^n to 1
   

   // For doing arithmetic mod f quickly, one must pre-compute
   // some information.

   ZZ_pXModulus F;
   build(F, f);

   PlainMul(r1, g, h);  // this uses classical arithmetic
   PlainRem(r1, r1, f);

   MulMod(r2, g, h, F);  // this uses the FFT

   MulMod(r3, g, h, f);  // uses FFT, but slower

   // compare the results...

   if (r1 != r2) {
      printf("999999999999999 ");
      print_flag();
      return 0;
   }
   else if (r1 != r3) {
      printf("999999999999999 ");
      print_flag();
      return 0;
   }

   double t;
   long i, j;
   long iter;

   const int nprimes = 30;
   const long L = 12; 
   const long N = 1L << L;
   long r;
   

   for (r = 0; r < nprimes; r++) UseFFTPrime(r);

   vec_long aa[nprimes], AA[nprimes];

   for (r = 0; r < nprimes; r++) {
      aa[r].SetLength(N);
      AA[r].SetLength(N);

      for (i = 0; i < N; i++)
         aa[r][i] = RandomBnd(GetFFTPrime(r));


      FFTFwd(AA[r].elts(), aa[r].elts(), L, r);
      FFTRev1(AA[r].elts(), AA[r].elts(), L, r);
   }

   iter = 1;

   do {
     t = GetTime();
     for (j = 0; j < iter; j++) {
        for (r = 0; r < nprimes; r++) {
           long *AAp = AA[r].elts();
           long *aap = aa[r].elts();
           long q = GetFFTPrime(r);
           mulmod_t qinv = GetFFTPrimeInv(r);

           FFTFwd(AAp, aap, L, r);
           FFTRev1(AAp, aap, L, r);
           for (i = 0; i < N; i++) AAp[i] = NormalizedMulMod(AAp[i], aap[i], q, qinv);
        }
     }
     t = GetTime() - t;
     iter = 2*iter;
   } while(t < 1);

   iter = iter/2;

   iter = long((1.5/t)*iter) + 1;


   double tvec[5];
   long w;

   for (w = 0; w < 5; w++) {
     t = GetTime();
     for (j = 0; j < iter; j++) {
        for (r = 0; r < nprimes; r++) {
           long *AAp = AA[r].elts();
           long *aap = aa[r].elts();
           long q = GetFFTPrime(r);
           mulmod_t qinv = GetFFTPrimeInv(r);

           FFTFwd(AAp, aap, L, r);
           FFTRev1(AAp, aap, L, r);
           for (i = 0; i < N; i++) AAp[i] = NormalizedMulMod(AAp[i], aap[i], q, qinv);
        }
     }
     t = GetTime() - t;
     tvec[w] = t;
   }

   t = clean_data(tvec);

   t = floor((t/iter)*1e13);

   if (t < 0 || t >= 1e15)
      printf("999999999999999 ");
   else
      printf("%015.0f ", t);

   printf(" [%ld] ", iter);

   print_flag();

   return 0;
}
Beispiel #23
0
int main(int argc, char *argv[]) 
{
  if (argc<2) {
    cout << "\nUsage: " << argv[0] << " L [c=2 w=64 k=80 d=1]" << endl;
    cout << "  L is the number of levels\n";
    cout << "  optional c is number of columns in the key-switching matrices (default=2)\n";
    cout << "  optional w is Hamming weight of the secret key (default=64)\n";
    cout << "  optional k is the security parameter (default=80)\n";
    cout << "  optional d specifies GF(2^d) arithmetic (default=1, must be <=16)\n";
    //    cout << "  k is the security parameter\n";
    //    cout << "  m determines the ring mod Phi_m(X)" << endl;
    cout << endl;
    exit(0);
  }
  cout.unsetf(ios::floatfield);
  cout.precision(4);

  long L = atoi(argv[1]);
  long c = 2;
  long w = 64;
  long k = 80;
  long d = 1;
  if (argc>2) c = atoi(argv[2]);
  if (argc>3) w = atoi(argv[3]);
  if (argc>4) k = atoi(argv[4]);
  if (argc>5) d = atoi(argv[5]);

  if (d>16) Error("d cannot be larger than 16\n");

  cout << "\nTesting FHE with parameters L="<<L
       << ", c="<<c<<", w="<<w<<", k="<<k<<", d="<<d<< endl;

  // get a lower-bound on the parameter N=phi(m):
  // 1. Empirically, we use ~20-bit small primes in the modulus chain (the main
  //    constraints is that 2m must divide p-1 for every prime p). The first
  //    prime is larger, a 40-bit prime. (If this is a 32-bit machine then we
  //    use two 20-bit primes instead.)
  // 2. With L levels, the largest modulus for "fresh ciphertexts" has size
  //          q0 ~ p0 * p^{L} ~ 2^{40+20L}
  // 3. We break each ciphertext into upto c digits, do each digit is as large
  //    as    D=2^{(40+20L)/c}
  // 4. The added noise variance term from the key-switching operation is
  //    c*N*sigma^2*D^2, and this must be mod-switched down to w*N (so it is
  //    on part with the added noise from modulus-switching). Hence the ratio
  //    P that we use for mod-switching must satisfy c*N*sigma^2*D^2/P^2<w*N,
  //    or    P > sqrt(c/w) * sigma * 2^{(40+20L)/c}
  // 5. With this extra P factor, the key-switching matrices are defined
  //    relative to a modulus of size
  //          Q0 = q0*P ~ sqrt{c/w} sigma 2^{(40+20L)(1+1/c)}
  // 6. To get k-bit security we need N>log(Q0/sigma)(k+110)/7.2, i.e. roughly
  //          N > (40+20L)(1+1/c)(k+110) / 7.2

  long ptxtSpace = 2;
  double cc = 1.0+(1.0/(double)c);
  long N = (long) ceil((pSize*L+p0Size)*cc*(k+110)/7.2);
  cout << "  bounding phi(m) > " << N << endl;

#if 0  // A small m for debugging purposes
  long m = 15;
#else
  // pre-computed values of [phi(m),m,d]
  long ms[][4] = {
    //phi(m)  m  ord(2) c_m*1000
    { 1176,  1247, 28,  3736},
    { 1936,  2047, 11,  3870},
    { 2880,  3133, 24,  3254},
    { 4096,  4369, 16,  3422},
    { 5292,  5461, 14,  4160},
    { 5760,  8435, 24,  8935},
    { 8190,  8191, 13,  1273},
    {10584, 16383, 14,  8358},
    {10752, 11441, 48,  3607},
    {12000, 13981, 20,  2467},
    {11520, 15665, 24, 14916},
    {14112, 18415, 28, 11278},
    {15004, 15709, 22,  3867},
    {15360, 20485, 24, 12767},
 // {16384, 21845, 16, 12798},
    {17208 ,21931, 24, 18387},
    {18000, 18631, 25,  4208},
    {18816, 24295, 28, 16360},
    {19200, 21607, 40, 35633},
    {21168, 27305, 28, 15407},
    {23040, 23377, 48,  5292},
    {24576, 24929, 48,  5612},
    {27000, 32767, 15, 20021},
    {31104, 31609, 71,  5149},
    {42336, 42799, 21,  5952},
    {46080, 53261, 24, 33409},
    {49140, 57337, 39,  2608},
    {51840, 59527, 72, 21128},
    {61680, 61681, 40,  1273},
    {65536, 65537, 32,  1273},
    {75264, 82603, 56, 36484},
    {84672, 92837, 56, 38520}
  };

#if 0

  for (long i = 0; i < 25; i++) {
    long m = ms[i][1];
    PAlgebra alg(m);
    alg.printout();
    cout << "\n";
    // compute phi(m) directly
    long phim = 0;
    for (long j = 0; j < m; j++)
      if (GCD(j, m) == 1) phim++;

    if (phim != alg.phiM()) cout << "ERROR\n";
  }

  exit(0);


#endif



  // find the first m satisfying phi(m)>=N and d | ord(2) in Z_m^*
  long m = 0;
  for (unsigned i=0; i<sizeof(ms)/sizeof(long[3]); i++) 
    if (ms[i][0]>=N && (ms[i][2] % d) == 0) {
      m = ms[i][1];
      c_m = 0.001 * (double) ms[i][3];
      break;
    }
  if (m==0) Error("Cannot support this L,d combination");
#endif
  //  m = 257;
  FHEcontext context(m);
#if 0
  context.stdev = to_xdouble(0.5); // very low error
#endif
  activeContext = &context; // Mark this as the "current" context

  context.zMstar.printout();
  cout << endl;


  // Set the modulus chain

#if 1
  // The first 1-2 primes of total p0size bits
  #if (NTL_SP_NBITS > p0Size)
    AddPrimesByNumber(context, 1, 1UL<<p0Size); // add a single prime
  #else
    AddPrimesByNumber(context, 2, 1UL<<(p0Size/2)); // add two primes
  #endif
#endif

  // The next L primes, as small as possible
  AddPrimesByNumber(context, L);

  ZZ productOfCtxtPrimes = context.productOfPrimes(context.ctxtPrimes);
  double productSize = context.logOfProduct(context.ctxtPrimes);

  // might as well test that the answer is roughly correct
  cout << "  context.logOfProduct(...)-log(context.productOfPrimes(...)) = "
       << productSize-log(productOfCtxtPrimes) << endl;

  // calculate the size of the digits

  context.digits.resize(c);
  IndexSet s1;
#if 0
  for (long i=0; i<c-1; i++) context.digits[i] = IndexSet(i,i);
  context.digits[c-1] = context.ctxtPrimes / IndexSet(0,c-2);
  AddPrimesByNumber(context, 2, 1, true);
#else
  double sizeSoFar = 0.0;
  double maxDigitSize = 0.0;
  if (c>1) {   // break ciphetext into a few digits
    double dsize = productSize/c;  // initial estimate
    double target = dsize-(pSize/3.0);
    long idx = context.ctxtPrimes.first();
    for (long i=0; i<c-1; i++) { // compute next digit
      IndexSet s;
      while (idx <= context.ctxtPrimes.last() && sizeSoFar < target) {
        s.insert(idx);
	sizeSoFar += log((double)context.ithPrime(idx));
	idx = context.ctxtPrimes.next(idx);
      }
      context.digits[i] = s;
      s1.insert(s);
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
      cout << "  digit #"<<i+1<< " " <<s << ": size " << thisDigitSize << endl;
      target += dsize;
    }
    IndexSet s = context.ctxtPrimes / s1; // all the remaining primes
    context.digits[c-1] = s;
    double thisDigitSize = context.logOfProduct(s);
    if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
    cout << "  digit #"<<c<< " " <<s << ": size " << thisDigitSize << endl;
  }
  else { 
    maxDigitSize = context.logOfProduct(context.ctxtPrimes);
    context.digits[0] = context.ctxtPrimes;
  }

  // Add primes to the chain for the P factor of key-switching
  double sizeOfSpecialPrimes 
    = maxDigitSize + log(c/(double)w)/2 + log(context.stdev *2);

  AddPrimesBySize(context, sizeOfSpecialPrimes, true);
#endif

  cout << "* ctxtPrimes: " << context.ctxtPrimes 
       << ", log(q0)=" << context.logOfProduct(context.ctxtPrimes) << endl;
  cout << "* specialPrimes: " << context.specialPrimes
       << ", log(P)=" << context.logOfProduct(context.specialPrimes) << endl;

  for (long i=0; i<context.numPrimes(); i++) {
    cout << "  modulus #" << i << " " << context.ithPrime(i) << endl;
  }
  cout << endl;

  setTimersOn();
  const ZZX& PhimX = context.zMstar.PhimX(); // The polynomial Phi_m(X)
  long phim = context.zMstar.phiM();         // The integer phi(m)
  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;

#if 0 // Debug mode: use sk=1,2
  DoubleCRT newSk(to_ZZX(2), context);
  long id1 = secretKey.ImportSecKey(newSk, 64, ptxtSpace);
  newSk -= 1;
  long id2 = secretKey.ImportSecKey(newSk, 64, ptxtSpace);
#else
  long id1 = secretKey.GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key
  long id2 = secretKey.GenSecKey(w,ptxtSpace); // A second Hamming-weight-w secret key
#endif

  ZZX zero = to_ZZX(0);
//  Ctxt zeroCtxt(publicKey);

  /******************************************************************/
  /**                      TESTS BEGIN HERE                       ***/
  /******************************************************************/


  cout << "ptxtSpace = " << ptxtSpace << endl;

  GF2X G;          // G is the AES polynomial, G(X)= X^8 +X^4 +X^3 +X +1
  SetCoeff(G,8); SetCoeff(G,4); SetCoeff(G,3); SetCoeff(G,1); SetCoeff(G,0);
  GF2X X;
  SetX(X);
  
#if 1
  // code for rotations...

  {
    GF2X::HexOutput = 1;
    
    const PAlgebra& al = context.zMstar;
    const PAlgebraModTwo& al2 = context.modTwo;

    long ngens = al.numOfGens();
    long nslots = al.NSlots();
    DoubleCRT tmp(context);

    vector< vector< DoubleCRT > > maskTable;

    maskTable.resize(ngens);
    for (long i = 0; i < ngens; i++) {
      if (i==0 && al.SameOrd(i)) continue;
      long ord = al.OrderOf(i);
      maskTable[i].resize(ord+1, tmp);
      for (long j = 0; j <= ord; j++) {
        // initialize the mask that is 1 whenever
        // the ith coordinate is at least j

        vector<GF2X> maps, alphas, betas;

        al2.mapToSlots(maps, G); // Change G to X to get bits in the slots
        alphas.resize(nslots);

        for (long k = 0; k < nslots; k++) 
          if (coordinate(al, i, k) >= j)
               alphas[k] = 1;
          else alphas[k] = 0;

       GF2X ptxt;
       al2.embedInSlots(ptxt, alphas, maps);

       // Sanity-check, make sure that encode/decode works as expected
       al2.decodePlaintext(betas, ptxt, G, maps);
       for (long k = 0; k < nslots; k++) {
	 if (alphas[k] != betas[k]) {
	   cout << " Mask computation failed, i="<<i<<", j="<<j<<"\n";
	   return 0;
	 }
       }
       maskTable[i][j] = to_ZZX(ptxt);
      }
    }

  vector<GF2X> maps;
  al2.mapToSlots(maps, G);

  vector<GF2X> alphas(nslots);
  for (long i=0; i < nslots; i++) 
    random(alphas[i], 8); // random degree-7 polynomial mod 2

  for (long amt = 0; amt < 20; amt++) {

    cout << ".";

     GF2X ptxt;
     al2.embedInSlots(ptxt, alphas, maps);

     DoubleCRT pp(context);
     pp = to_ZZX(ptxt);

     rotate(pp, amt, maskTable);

     GF2X ptxt1 = to_GF2X(to_ZZX(pp));

     vector<GF2X> betas;
     al2.decodePlaintext(betas, ptxt1, G, maps);

     for (long i = 0; i < nslots; i++) {
       if (alphas[i] != betas[(i+amt)%nslots]) {
	 cout << " amt="<<amt<<" oops\n";
          return 0;
       }
     }
   }

   cout << "\n";

#if 0
  long ord0 = al.OrderOf(0);

  for (long i = 0; i < nslots; i++) {
    cout << alphas[i] << " ";
    if ((i+1) % (nslots/ord0) == 0) cout << "\n";
  }
 
  cout << "\n\n";
  cout << betas.size() << "\n";

  for (long i = 0; i < nslots; i++) {
    cout << betas[i] << " ";
    if ((i+1) % (nslots/ord0) == 0) cout << "\n";
  }
#endif


  return 0;
  

  }


#endif

  // an initial sanity check on noise estimates,
  // comparing the estimated variance to the actual average
  cout << "pk:"; checkCiphertext(publicKey.pubEncrKey, zero, secretKey);

  ZZX ptxt[6]; // first four are plaintext, last two are constants
  std::vector<Ctxt> ctxt(4, Ctxt(publicKey));

  // Initialize the plaintext and constants to random 0-1 polynomials
  for (size_t j=0; j<6; j++) {
    ptxt[j].rep.SetLength(phim);
    for (long i = 0; i < phim; i++)
      ptxt[j].rep[i] = RandomBnd(ptxtSpace);
    ptxt[j].normalize();

    if (j<4) { 
      publicKey.Encrypt(ctxt[j], ptxt[j], ptxtSpace);
      cout << "c"<<j<<":"; checkCiphertext(ctxt[j], ptxt[j], secretKey);
    }
  }

  // perform upto 2L levels of computation, each level computing:
  //    1. c0 += c1
  //    2. c1 *= c2            // L1' = max(L1,L2)+1
  //    3. c1.reLinearlize
  //    4. c2 *= p4
  //    5. c2.automorph(k)     // k is the first generator of Zm^* /(2)
  //    6. c2.reLinearlize
  //    7. c3 += p5
  //    8. c3 *= c0            // L3' = max(L3,L0,L1)+1
  //    9. c2 *= c3            // L2' = max(L2,L0+1,L1+1,L3+1)+1
  //   10. c0 *= c0            // L0' = max(L0,L1)+1
  //   11. c0.reLinearlize
  //   12. c2.reLinearlize
  //   13. c3.reLinearlize
  //
  // The levels of the four ciphertexts behave as follows:
  // 0, 0, 0, 0  =>  1, 1, 2, 1  =>  2, 3, 3, 2
  //             =>  4, 4, 5, 4  =>  5, 6, 6, 5
  //             =>  7, 7, 8, 7  =>  8,,9, 9, 10  => [...]
  //
  // We perform the same operations on the plaintext, and after each operation
  // we check that decryption still works, and print the curretn modulus and
  // noise estimate. We stop when we get the first decryption error, or when
  // we reach 2L levels (which really should not happen).

  zz_pContext zzpc;
  zz_p::init(ptxtSpace);
  zzpc.save();
  const zz_pXModulus F = to_zz_pX(PhimX);
  long g = context.zMstar.ZmStarGen(0); // the first generator in Zm*
  zz_pX x2g(g, 1);
  zz_pX p2;

  // generate a key-switching matrix from s(X^g) to s(X)
  secretKey.GenKeySWmatrix(/*powerOfS= */  1,
			   /*powerOfX= */  g,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  // generate a key-switching matrix from s^2 to s
  secretKey.GenKeySWmatrix(/*powerOfS= */  2,
			   /*powerOfX= */  1,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  // generate a key-switching matrix from s^3 to s
  secretKey.GenKeySWmatrix(/*powerOfS= */  3,
			   /*powerOfX= */  1,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  for (long lvl=0; lvl<2*L; lvl++) {
    cout << "=======================================================\n";
    ctxt[0] += ctxt[1];
    ptxt[0] += ptxt[1];
    PolyRed(ptxt[0], ptxtSpace, true);
    cout << "c0+=c1:  "; checkCiphertext(ctxt[0], ptxt[0], secretKey);

    ctxt[1].multiplyBy(ctxt[2]);
    ptxt[1] = (ptxt[1] * ptxt[2]) % PhimX;
    PolyRed(ptxt[1], ptxtSpace, true);
    cout << "c1*=c2:  "; checkCiphertext(ctxt[1], ptxt[1], secretKey);

    ctxt[2].multByConstant(ptxt[4]);
    ptxt[2] = (ptxt[2] * ptxt[4]) % PhimX;
    PolyRed(ptxt[2], ptxtSpace, true);
    cout <<  "c2*=p4:  "; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[2] >>= g;
    zzpc.restore();
    p2 = to_zz_pX(ptxt[2]);
    CompMod(p2, p2, x2g, F);
    ptxt[2] = to_ZZX(p2);
    cout << "c2>>="<<g<<":"; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[2].reLinearize();
    cout << "c2.relin:"; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[3].addConstant(ptxt[5]);
    ptxt[3] += ptxt[5];
    PolyRed(ptxt[3], ptxtSpace, true);
    cout << "c3+=p5:  "; checkCiphertext(ctxt[3], ptxt[3], secretKey);

    ctxt[3].multiplyBy(ctxt[0]);
    ptxt[3] = (ptxt[3] * ptxt[0]) % PhimX;
    PolyRed(ptxt[3], ptxtSpace, true);
    cout << "c3*=c0:  ";    checkCiphertext(ctxt[3], ptxt[3], secretKey);

    ctxt[0].square();
    ptxt[0] = (ptxt[0] * ptxt[0]) % PhimX;
    PolyRed(ptxt[0], ptxtSpace, true);
    cout << "c0*=c0:  ";    checkCiphertext(ctxt[0], ptxt[0], secretKey);

    ctxt[2].multiplyBy(ctxt[3]);
    ptxt[2] = (ptxt[2] * ptxt[3]) % PhimX;
    PolyRed(ptxt[2], ptxtSpace, true);
    cout << "c2*=c3:  ";    checkCiphertext(ctxt[2], ptxt[2], secretKey);
  }
  /******************************************************************/
  /**                       TESTS END HERE                        ***/
  /******************************************************************/
  cout << endl;
  return 0;
}
Beispiel #24
0
int main()
{
   long n, i, j, iter, s, k;
   double t;


   for (i = 0; i < 10000; i++) {
      GF2X a, b, c, d;
      long da = RandomBnd(5*NTL_BITS_PER_LONG);
      long db = RandomBnd(5*NTL_BITS_PER_LONG);
      long dc = RandomBnd(5*NTL_BITS_PER_LONG);
      long dd = RandomBnd(5*NTL_BITS_PER_LONG);
      random(a, da);  random(b, db);  random(c, dc);  random(d, dd);

      if ((a + b)*(c + d) != c*a + d*a + c*b + d*b) {
	 printf("999999999999999 ");
	 print_flag();
	 return 0;
      }
   }
   

   n = 16;
   s = 56;

   GF2X *a = new GF2X[s];
   GF2X *b = new GF2X[s];

   GF2X c;

   for (k = 0; k < s; k++) {
      random(a[k], (n + (k % 7))*NTL_BITS_PER_LONG);
      random(b[k], (n + (k % 8))*NTL_BITS_PER_LONG);
   }

   for (k = 0; k < s; k++) mul(c, a[k], b[k]);


   iter = 1;

   do {
     t = GetTime();
     for (i = 0; i < iter; i++) {
        for (j = 0; j < 1; j++) for (k = 0; k < s; k++) mul(c, a[k], b[k]);
     }
     t = GetTime() - t;
     iter = 2*iter;
   } while(t < 1);

   iter = iter/2;

   iter = long((2/t)*iter) + 1;

   double tvec[5];
   long w;

   for (w = 0; w < 5; w++) {
     t = GetTime();
     for (i = 0; i < iter; i++) {
        for (j = 0; j < 1; j++) for (k = 0; k < s; k++) mul(c, a[k], b[k]);
     }
     t = GetTime() - t;
     tvec[w] = t;
   }


   t = clean_data(tvec);

   t = floor((t/iter)*1e14);

   if (t < 0 || t >= 1e15)
      printf("999999999999999 ");
   else
      printf("%015.0f ", t);

   printf(" [%ld] ", iter);

   print_flag();

   return 0;
}
/**************************
//Goldwasser-Micali HE system
//len: length of params p,q
**************************/
void GM(int len=512){
  ZZ N, p, q, x;

  long m1, m2;
  ZZ BSm, HEm; //baseline and HE result
  ZZ c, c1, c2, cm1, cm2, r;

  //key gen
  start = std::clock();

  GenPrime(p, len);
  GenPrime(q, len);
  mul(N, p, q);
  
  do{
  RandomBnd(x, N);
  } while( (Jacobi(x,p)==1) || (Jacobi(x,q)==1));

  cout<<"Jac:"<<Jacobi(x,p)<<Jacobi(x,q)<<endl;
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"GM Setup:"<< duration <<'\n';

  //Enc
  RandomBnd(m1,2);
  RandomBnd(m2,2);

  start = std::clock();
  RandomBnd(r, N);
  MulMod(cm1,r,r,N);

  if(m1==1)
   MulMod(cm1,cm1,x,N);
  
  RandomBnd(r, N);
  MulMod(cm2,r,r,N);

  if(m2==1)
   MulMod(cm2,cm2,x,N);

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"GM Enc:"<< duration <<'\n';

  //Evaluation
  start = std::clock();
  MulMod(c,cm1,cm2,N);
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"GM Eval:"<< duration <<'\n';

  //Dec  
  start = std::clock();
  HEm=Jacobi(c,p);
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"GM Dec:"<< duration <<'\n';

  if(HEm==1)
    HEm=0;
  else
    HEm=1;

  //baseline
  BSm=m1^m2;  //xor

  //cout<<"plaintext:"<<m1<<m2<<BSm<<endl;
  assert(BSm==HEm);
}
/**************************
//Paillier HE system
//len: length of params p,q
**************************/
void Paillier(int len=512){
  ZZ n, n2, p, q, g, lamda;
  ZZ p1, q1, p1q1;
  ZZ miu;
  
  ZZ m1, m2;
  ZZ BSm, HEm; //baseline and HE result
  ZZ c, c1, c2, cm1, cm2, r;

  //key gen
  start = std::clock();

  GenPrime(p, len);
  GenPrime(q, len);
  mul(n, p, q);
  mul(n2, n, n);

  sub(p1,p,1);
  sub(q1,q,1);
  GCD(lamda,p1,q1);
  mul(p1q1,p1,q1);
  div(lamda, p1q1, lamda);

  RandomBnd(g, n2);

  PowerMod(miu,g,lamda,n2);
  sub(miu, miu, 1);
  div(miu,miu,n); //should add 1?
  InvMod(miu, miu, n);
  
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Setup:"<< duration <<'\n';

  //Enc
  start = std::clock();
  RandomBnd(m1,n);
  RandomBnd(m2,n);

  RandomBnd(r,n); //enc m1
  PowerMod(c1, g,m1,n2);
  PowerMod(c2, r,n,n2);
  MulMod(cm1, c1,c2, n2);

  RandomBnd(r,n); //enc m2
  PowerMod(c1, g,m2,n2);
  PowerMod(c2, r,n,n2);
  MulMod(cm2, c1,c2, n2);

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Enc:"<< duration/2 <<'\n';

  //Evaluation
  start = std::clock();
  c=cm1;
  for(int i=0; i<TIMES; i++)
  	MulMod(c,c,cm2,n2);
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Eval:"<< duration <<'\n';

  //c=cm2;
  //Dec  
  start = std::clock();
  PowerMod(c,c,lamda,n2);
  sub(c,c,1);
  div(c,c,n); //should add 1?
  MulMod(HEm, c, miu, n);  

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Dec:"<< duration <<'\n';

  //baseline
  BSm=m1;
  for(int i=0; i<TIMES; i++)
  	AddMod(BSm,BSm,m2,n);

  assert(BSm==HEm);
}
//Comparison protocol based on ""
bool COM(bool disp, long long seed, unsigned p, FHEcontext &context) {
  ZZ seedZZ;
  seedZZ = seed;

  srand48(seed);
  SetSeed(seedZZ);

  FHESISecKey secretKey(context);
  const FHESIPubKey &publicKey(secretKey);
  
  long phim = context.zMstar.phiM();
  
  ZZ_pX ptxt1Poly, ptxt2Poly, sum, sumMult, prod, prod2, sumQuad;
  Plaintext resSum, resSumMult, resProd, resProdSwitch, resProd2, resSumQuad;

  //gen plaintext
  ptxt1Poly.rep.SetLength(phim);
  ptxt2Poly.rep.SetLength(phim);
  for (long i=0; i < phim; i++) {
    ptxt1Poly.rep[i] = RandomBnd(p);
    ptxt2Poly.rep[i] = RandomBnd(p);
  }

  //printpoly(ptxt1Poly, phim);

  ptxt1Poly.normalize();
  ptxt2Poly.normalize();
  
  #ifdef DEBUG
  cout<<"phim:"<<phim<<endl;
  cout<<"p1:"<<endl;
  printpoly(ptxt1Poly, phim);
  cout<<"p2:"<<endl;
  printpoly(ptxt2Poly, phim);
  #endif

  //plaintext operation
  sum = ptxt1Poly + ptxt2Poly;
  sumMult = ptxt2Poly * 7;
  prod = ptxt1Poly * ptxt2Poly;
  prod2 = prod * prod;
  sumQuad = prod2 * prod2 * 9; //\sum_((xy)^4)

  #ifdef DEBUG  
  cout<<"sum:"<<endl;
  printpoly(sum, phim);
  cout<<"prod2:"<<endl;
  printpoly(prod2, phim);
  #endif

  rem(prod, prod, to_ZZ_pX(context.zMstar.PhimX()));
  rem(prod2, prod2, to_ZZ_pX(context.zMstar.PhimX()));
  rem(sumQuad, sumQuad, to_ZZ_pX(context.zMstar.PhimX()));
  
  //encryption
  start = std::clock();
  Plaintext ptxt1(context, ptxt1Poly), ptxt2(context, ptxt2Poly);
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  duration = duration/2;
  cout<<"Encryption:"<< duration <<'\n';

  Ciphertext ctxt1(publicKey), ctxt2(publicKey);
  publicKey.Encrypt(ctxt1, ptxt1);
  publicKey.Encrypt(ctxt2, ptxt2);

  Ciphertext cSum = ctxt1;
  cSum += ctxt2;

  Ciphertext cSumMult = ctxt2;
  start = std::clock();
  for (int i = 1; i < 7; i++) {
    cSumMult += ctxt2;
  }
  duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC);
  duration = duration/6;
  cout<<"Addition:"<< duration <<'\n';

  Ciphertext cProd = ctxt1;
  cProd *= ctxt2;
 
  secretKey.Decrypt(resSum, cSum);
  secretKey.Decrypt(resSumMult, cSumMult);
  
  KeySwitchSI keySwitch(secretKey);
  keySwitch.ApplyKeySwitch(cProd);
  secretKey.Decrypt(resProd, cProd);

  cProd *= cProd;
  Ciphertext tmp = cProd;
  Ciphertext cSumQuad = cProd;
  
  keySwitch.ApplyKeySwitch(cProd);
  secretKey.Decrypt(resProd2, cProd);

  for (int i = 0; i < 8; i++) {
    cSumQuad += tmp;
  }
  keySwitch.ApplyKeySwitch(cSumQuad);  //apply key switch after summing all prod

  start = std::clock();
  cSumQuad *= cProd;
  duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC);
  cout<<"HMult without key switch:"<< duration <<'\n';

  keySwitch.ApplyKeySwitch(cSumQuad);

  duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC);
  cout<<"HMult with key switch:"<< duration <<'\n';

  start = std::clock();
  secretKey.Decrypt(resSumQuad, cSumQuad);
  duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC);
  cout<<"Decryption:"<< duration <<'\n';
  
  //comparison
  bool success = ((resSum.message == sum) && (resSumMult.message == sumMult) &&
                  (resProd.message == prod) && (resProd2.message == prod2) &&
                  (resSumQuad == sumQuad));
  
  if (disp || !success) {
    cout << "Seed: " << seed << endl << endl;
    
    if (resSum.message != sum) {
      cout << "Add failed." << endl;
    }
    if (resSumMult.message != sumMult) {
      cout << "Adding multiple times failed." << endl;
    }
    if (resProd.message != prod) {
      cout << "Multiply failed." << endl;
    }
    if (resProd2.message != prod2) {
      cout << "Squaring failed." << endl;
    }
    if (resSumQuad.message != sumQuad) {
      cout << "Sum and quad failed." << endl;
    }
  }
  
  if (disp || !success) {
    cout << "Test " << (success ? "SUCCEEDED" : "FAILED") << endl;
  }

  return success;
}
Beispiel #28
0
int main()
{
   SetSeed(ZZ(0));


   cerr << "This is NTL version " << NTL_VERSION << "\n"; 

   cerr << "Hardware charactersitics:\n";
   cerr << "NTL_BITS_PER_LONG = " << NTL_BITS_PER_LONG << "\n";
   cerr << "NTL_ZZ_NBITS = " << NTL_ZZ_NBITS << "\n";
   cerr << "NTL_SP_NBITS = " << NTL_SP_NBITS << "\n";

#ifdef NTL_HAVE_LL_TYPE
   cerr << "NTL_HAVE_LL_TYPE\n";
#endif

#ifdef NTL_LONGDOUBLE_SP_MULMOD
   cerr << "NTL_LONGDOUBLE_SP_MULMOD\n";
#endif

#ifdef NTL_LONGLONG_SP_MULMOD
   cerr << "NTL_LONGLONG_SP_MULMOD\n";
#endif

   cerr << "\n";

   


   cerr << "Basic Configuration Options:\n";



#ifdef NTL_LEGACY_NO_NAMESPACE
   cerr << "NTL_LEGACY_NO_NAMESPACE\n";
#endif


#ifdef NTL_LEGACY_INPUT_ERROR
   cerr << "NTL_LEGACY_INPUT_ERROR\n";
#endif


#ifdef NTL_THREADS
   cerr << "NTL_THREADS\n";
#endif


#ifdef NTL_EXCEPTIONS
   cerr << "NTL_EXCEPTIONS\n";
#endif

#ifdef NTL_THREAD_BOOST
   cerr << "NTL_THREAD_BOOST\n";
#endif


#ifdef NTL_LEGACY_SP_MULMOD
   cout << "NTL_LEGACY_SP_MULMOD\n";
#endif


#ifdef NTL_DISABLE_LONGDOUBLE
   cout << "NTL_DISABLE_LONGDOUBLE\n";
#endif


#ifdef NTL_DISABLE_LONGLONG
   cout << "NTL_DISABLE_LONGLONG\n";
#endif

#ifdef NTL_MAXIMIZE_SP_NBITS
   cout << "NTL_MAXIMIZE_SP_NBITS\n";
#endif




#ifdef NTL_GMP_LIP
   cerr << "NTL_GMP_LIP\n";
#endif


#ifdef NTL_GF2X_LIB
   cerr << "NTL_GF2X_LIB\n";
#endif


#ifdef NTL_PCLMUL
   cerr << "NTL_PCLMUL\n";
#endif


#ifdef NTL_LONG_LONG_TYPE
   cerr << "NTL_LONG_LONG_TYPE: ";
   cerr << make_string(NTL_LONG_LONG_TYPE) << "\n";
#endif

#ifdef NTL_UNSIGNED_LONG_LONG_TYPE
   cerr << "NTL_UNSIGNED_LONG_LONG_TYPE: ";
   cerr << make_string(NTL_UNSIGNED_LONG_LONG_TYPE) << "\n";
#endif


#ifdef NTL_X86_FIX
   cerr << "NTL_X86_FIX\n";
#endif

#ifdef NTL_NO_X86_FIX
   cerr << "NTL_NO_X86_FIX\n";
#endif

#ifdef NTL_NO_INIT_TRANS
   cerr << "NTL_NO_INIT_TRANS\n";
#endif

#ifdef NTL_CLEAN_INT
   cerr << "NTL_CLEAN_INT\n";
#endif

#ifdef NTL_CLEAN_PTR
   cerr << "NTL_CLEAN_PTR\n";
#endif

#ifdef NTL_RANGE_CHECK
   cerr << "NTL_RANGE_CHECK\n";
#endif


cerr << "\n";
cerr << "Resolution of double-word types:\n";
cerr << make_string(NTL_LL_TYPE) << "\n";
cerr << make_string(NTL_ULL_TYPE) << "\n";


cerr << "\n";
cerr << "Performance Options:\n";

#ifdef NTL_LONG_LONG
   cerr << "NTL_LONG_LONG\n";
#endif

#ifdef NTL_AVOID_FLOAT
   cerr << "NTL_AVOID_FLOAT\n";
#endif


#ifdef NTL_SPMM_ULL
   cerr << "NTL_SPMM_ULL\n";
#endif


#ifdef NTL_SPMM_ASM
   cerr << "NTL_SPMM_ASM\n";
#endif




#ifdef NTL_AVOID_BRANCHING
   cerr << "NTL_AVOID_BRANCHING\n";
#endif


#ifdef NTL_FFT_BIGTAB
   cout << "NTL_FFT_BIGTAB\n";
#endif

#ifdef NTL_FFT_LAZYMUL
   cout << "NTL_FFT_LAZYMUL\n";
#endif





#ifdef NTL_TBL_REM
   cerr << "NTL_TBL_REM\n";
#endif


#ifdef NTL_TBL_REM_LL
   cerr << "NTL_TBL_REM_LL\n";
#endif

#ifdef NTL_CRT_ALTCODE
   cerr << "NTL_CRT_ALTCODE\n";
#endif

#ifdef NTL_CRT_ALTCODE_SMALL
   cerr << "NTL_CRT_ALTCODE_SMALL\n";
#endif

#ifdef NTL_GF2X_ALTCODE
   cerr << "NTL_GF2X_ALTCODE\n";
#endif

#ifdef NTL_GF2X_ALTCODE1
   cerr << "NTL_GF2X_ALTCODE1\n";
#endif


#ifdef NTL_GF2X_NOINLINE
   cerr << "NTL_GF2X_NOINLINE\n";
#endif

   cerr << "\n\n";

   cerr << "running tests";

   long n, k, i;

   n = 250;
   k = 16000;

   ZZ p;


   for (i = 0; i < 15; i++) {
      // cerr << n << "/" << k; 
      cerr << ".";
      RandomLen(p, k);
      ZZ_p::init(p);  
    

      ZZ_pX a, b, c, c1;


      random(a, n);
      random(b, n);

      FFTMul(c, a, b);
      //cerr << ZZ_pInfo->FFTInfo->NumPrimes;

      c1 = conv<ZZ_pX>( KarMul( conv<ZZX>(a), conv<ZZX>(b) ) );

      if (c1 != c) {
         cerr << "ZZ_pX mul failed!\n";
         return 1;
      }

      n = long(n * 1.35);
      k = long(k / 1.414);
   }


   // small prime tests...I've made some changes in v5.3
   // that should be checked on various platforms, so 
   // we might as well check them here.

   if (SmallModulusTest(17, 1000)) {
      cerr << "first SmallModulusTest failed!!\n";
      return 1;
   }

   if (SmallModulusTest((1L << (NTL_SP_NBITS))-1, 1000)) {
      cerr << "second SmallModulusTest failed!!\n";
      return 1;
   }

   // Test gf2x code....

   if (GF2X_test()) {
      cerr << "GF2X test failed!\n";
      return 1;
   }
   

   cerr << "OK\n";

   ZZ x1, x2, x3, x4;
   double t;

   RandomLen(x1, 1024);
   RandomBnd(x2, x1);
   RandomBnd(x3, x1);

   mul(x4, x2, x3);

   t = GetTime();
   for (i = 0; i < 100000; i++)
      mul(x4, x2, x3);
   t = GetTime()-t;

   cerr << "time for 1024-bit mul: " << t*10 << "us";
   cerr << "\n";

   rem(x2, x4, x1);

   t = GetTime();
   for (i = 0; i < 100000; i++)
      rem(x2, x4, x1);
   t = GetTime()-t;

   cerr << "time for 2048/1024-bit rem: " << t*10 << "us";
   cerr << "\n";
   

   GenPrime(p, 1024);
   RandomBnd(x1, p);
   if (IsZero(x1)) set(x1);

   InvMod(x2, x1, p);

   t = GetTime();
   for (i = 0; i < 1000; i++)
      InvMod(x2, x1, p);
   t = GetTime()-t;

   cerr << "time for 1024-bit modular inverse: " << t*1000 << "us";
   cerr << "\n";



   // test modulus switching
   
   n = 1024;
   k = 1024;
   RandomLen(p, k);

   ZZ_p::init(p);
   if (!IsOdd(p)) p++;

   ZZ_pX j1, j2, j3;

   random(j1, n);
   random(j2, n);

   mul(j3, j1, j2);

   t = GetTime();
   for (i = 0; i < 200; i++) mul(j3, j1, j2);
   t = GetTime()-t;

   cerr << "time to multiply degree 1023 polynomials\n   modulo a 1024-bit number: ";
   cerr << (t/200) << "s";
   cerr << "\n";

   GF2X_time();

   return 0;
}
Beispiel #29
0
int main()
{
   RR::SetPrecision(150);
   long n, b, size;

   cerr << "n: ";
   cin >> n;

   cerr << "b: ";
   cin >> b;

   cerr << "size: ";
   cin >> size;

   cerr << "prune: ";
   long prune;
   cin >> prune;

   ZZ seed;
   cerr << "seed: ";
   cin >> seed;

   if (seed != 0)
      SetSeed(seed);

   char alg;
   cerr << "alg [fqQxr]: ";
   cin >> alg;

   double TotalTime = 0;
   long TotalSucc = 0;

   long iter;

   for (iter = 1; iter <= 20; iter++) {
      vec_ZZ a;
      a.SetLength(n);
   
      ZZ bound;
   
      LeftShift(bound, to_ZZ(1), b);
   
      long i;
      for (i = 1; i <= n; i++) {
         RandomBnd(a(i), bound);
         a(i) += 1;
      }
   
      ZZ S;
   
      do {
         RandomLen(S, n+1);
      } while (weight(S) != n/2+1);
   
      ZZ s;
      clear(s);
      for (i = 1; i <= n; i++)
         if (bit(S, i-1))
            s += a(i);
   
      mat_ZZ B(INIT_SIZE, n+1, n+3);
   
      for (i = 1; i <= n; i++) {
         B(i, i) = 2;
         B(i, n+1) = a(i) * n;
         B(i, n+3) = n;
      }
   
      for (i = 1; i <= n; i++)
         B(n+1, i) = 1;
   
      B(n+1, n+1) = s * n;
      B(n+1, n+2) = 1;
      B(n+1, n+3) = n;
      B(n+1, n+3) *= n/2;
   
      swap(B(1), B(n+1)); 
   
      for (i = 2; i <= n; i++) {
         long j = RandomBnd(n-i+2) + i;
         swap(B(i), B(j));
      }
   
      double t;

      LLLStatusInterval = 10;
   
      t = GetTime();
      switch (alg) {
      case 'f':
         BKZ_FP(B, 0.99, size, prune, SubsetSumSolution);
         break;
      case 'q':
         BKZ_QP(B, 0.99, size, prune, SubsetSumSolution);
         break;
      case 'Q':
         BKZ_QP1(B, 0.99, size, prune, SubsetSumSolution);
         break;
      case 'x':
         BKZ_XD(B, 0.99, size, prune, SubsetSumSolution);
         break;
      case 'r':
         BKZ_RR(B, 0.99, size, prune, SubsetSumSolution);
         break;
      default:
         Error("invalid algorithm");
      }


      t = GetTime()-t;
   
      long succ = 0;
      for (i = 1; i <= n+1; i++)
         if (SubsetSumSolution(B(i)))
            succ = 1;

      TotalTime += t;
      TotalSucc += succ;

      if (succ)
         cerr << "+";
      else
         cerr << "-";
   }

   cerr << "\n";

   cerr << "number of success: " << TotalSucc << "\n";
   cerr << "average time: " << TotalTime/20 << "\n";

   return 0;
}
/**************************
//ElGamal HE system
//len: length of params p,q
**************************/
void ElGamal(int len=512){
  ZZ n, n2, p, q, g, x, lamda;
  ZZ p1, q1, p1q1;
  ZZ bA;
  
  ZZ m1, m2, k1, k2;
  ZZ BSm, HEm; //baseline and HE result
  ZZ c, r1, r2, t1, t2, cm1, cm2;
  ZZ r, t;

  //key gen
  start = std::clock();

  GenPrime(q, len);
  RandomBnd(g, q);
  RandomBnd(x, q);
  PowerMod(bA,g,x, q);

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"ElGamal Setup:"<< duration <<'\n';

  //Enc
  RandomBnd(m1, q);
  RandomBnd(m2, q);

  start = std::clock();

  RandomBnd(k1, q); //B
  PowerMod(r1,g,k1, q);
  PowerMod(t1,bA,k1, q);
  MulMod(t1, t1, m1, q);

  RandomBnd(k2, q); //B
  PowerMod(r2,g,k2, q);
  PowerMod(t2,bA,k2, q);
  MulMod(t2, t2, m2, q);

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"ElGamal Enc:"<< duration/2 <<'\n';

  //Evaluation
  start = std::clock();

  MulMod(r,r1,r2,q);
  MulMod(t,t1,t2,q);

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"ElGamal Eval:"<< duration/2 <<'\n';

  //Dec  
  start = std::clock();

  PowerMod(HEm,r,x,q);
  InvMod(HEm, HEm, q);
  MulMod(HEm,HEm,t,q);
  
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"ElGamal Dec:"<< duration/2 <<'\n';

  //baseline
  MulMod(BSm,m1,m2,q);

  assert(BSm==HEm);
}