homenc / HElib

HElib is an open-source software library that implements homomorphic encryption. It supports the BGV scheme with bootstrapping and the Approximate Number CKKS scheme. HElib also includes optimizations for efficient homomorphic evaluation, focusing on effective use of ciphertext packing techniques and on the Gentry-Halevi-Smart optimizations.
https://homenc.github.io/HElib
Other
3.11k stars 760 forks source link

Bootstrap capacity and security level #389

Open xueyumusic opened 3 years ago

xueyumusic commented 3 years ago

I used the parameter m=28679 p=2 r=1 for bootstrap recryption, and tests different nBits(level) values, it looks that if the nBits is less, the recryption maybe failed or after recryption the left capacity is very low so could not run more levels, but if increase nBits the security level decreased. so if I need to keep some security level does that mean the parameter m should have lower bound and be greater than some value, for example, if I want to keep the security >98, do I need to make the m much more than 28679, since it could not increase or decrease the nBits.

nBits capacity after recrypt security level
500 -19 127.701
550 29 98.2779
600 85 71.8524

my test code is

int main(int argc, char* argv[])
{
  auto start = std::chrono::system_clock::now();
  std::time_t start_time = std::chrono::system_clock::to_time_t(start);
  std::cout << "##begin rotate:" << std::ctime(&start_time) << std::endl;

  long mValues[][14] = {
//{ p, phi(m),  m,   d, m1, m2, m3,   g1,    g2,   g3,ord1,ord2,ord3, c_m}
  { 2, 23040, 28679, 24, 17, 7, 241, 15184, 4098,28204, 16,  6,-10,1500}, // m=7*17*(241) m/phim(m)=1.24    C=63  D=4 E=3
  };

  int cid = 0;
  unsigned long p = mValues[cid][0];
  unsigned long m = mValues[cid][2];
  unsigned long r = 1;
  unsigned long bits = 550;
  unsigned long c = 3;

  std::vector<long> gens;
  std::vector<long> ords;
  NTL::Vec<long> mvec;
  gens.push_back(mValues[cid][7]);
  if (mValues[cid][8]>1)   gens.push_back(mValues[cid][8]);
  if (mValues[cid][9]>1) gens.push_back(mValues[cid][9]);

  ords.push_back(mValues[cid][10]);
  if (abs(mValues[cid][11])>1) ords.push_back(mValues[cid][11]);
  if (abs(mValues[cid][12])>1) ords.push_back(mValues[cid][12]);

  mvec.append(mValues[cid][4]);
  if (mValues[cid][5]>1) mvec.append(mValues[cid][5]);
  if (mValues[cid][6]>1) mvec.append(mValues[cid][6]);

  helib::Context context(m, p, r, gens, ords);
  context.zMStar.set_cM(mValues[cid][13]/100.0);
  buildModChain(context, bits, c, true, 64);
  context.makeBootstrappable(mvec, 64);

  std::cout << "security=" << context.securityLevel() << std::endl;
  std::cout << "# small primes = " << context.smallPrimes.card() << "\n";
  std::cout << "# ctxt primes = " << context.ctxtPrimes.card() << "\n";
  std::cout << "# bits in ctxt primes = "
            << long(context.logOfProduct(context.ctxtPrimes) / log(2.0) + 0.5)
            << "\n";
  std::cout << "# special primes = " << context.specialPrimes.card() << "\n";
  std::cout << "# bits in special primes = "
            << long(context.logOfProduct(context.specialPrimes) / log(2.0) +
                    0.5)
            << "\n";
  std::cout << "scale=" << context.scale << std::endl;
  std::cout << std::endl;

  helib::SecKey secret_key(context);
  secret_key.GenSecKey();

  helib::addFrbMatrices(secret_key);      // Also add Frobenius key-switching
  helib::addSome1DMatrices(secret_key);
  secret_key.genRecryptData();

  const helib::PubKey& public_key = secret_key;

  const uint8_t polybytes[] = { 0xf5, 0x1 }; // X^8+X^7+X^6+X^5+X^4+X^2+1
  const NTL::GF2X poly = NTL::GF2XFromBytes(polybytes, 2);
  helib::EncryptedArrayDerived<helib::PA_GF2> ea2(context, poly, context.alMod);

  long nslots = ea2.size();
  int groupnum = nslots/16;

  std::vector<NTL::GF2X> slots(ea2.size(), NTL::GF2X::zero());
  unsigned char b = 0x01;
  for (int i = 0; i < slots.size(); i++) {
    NTL::GF2XFromBytes(slots[i], &b, 1);
  }
  NTL::ZZX encData;
  ea2.encode(encData, slots);
  helib::Ctxt ctxt(public_key);
  public_key.Encrypt(ctxt, encData);

  int i = 0;
  helib::Ctxt tmpctxt(ctxt);
  while(i<100000) {
    ctxt.multiplyBy(tmpctxt);
    ctxt.cleanUp();
    std::cout << "##i:" << i << ":" << ctxt.bitCapacity() << std::endl;
    i+=1;
    if (ctxt.bitCapacity() < 30) {
      std::cout << "##begin recrypt:" << ctxt.bitCapacity() << std::endl;
      public_key.reCrypt(ctxt);
      std::cout << "##end recrypt:" << ctxt.bitCapacity() << std::endl;
    }
  }

}