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.
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;
}
}
}
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 parameterm
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 them
much more than 28679, since it could not increase or decrease the nBits.my test code is