I'm using the homomorphic encryption library, HElib, to do experiments.
I tried to use bootstrapping with parameters that are not in the table provided with HElib.
But I have no idea how to choose the parameters (i.e, gen, ords and mvec) for bootstrapping.
Below is an example in HElib (examples/BGV_binary_arithmetic.cpp
)
// Plaintext prime modulus.
long p = 2;
// Cyclotomic polynomial - defines phi(m).
long m = 4095;
// Hensel lifting (default = 1).
long r = 1;
// Number of bits of the modulus chain.
long bits = 500;
// Number of columns of Key-Switching matrix (typically 2 or 3).
long c = 2;
// Factorisation of m required for bootstrapping.
std::vector<long> mvec = {7, 5, 9, 13};
// Generating set of Zm* group.
std::vector<long> gens = {2341, 3277, 911};
// Orders of the previous generators.
std::vector<long> ords = {6, 4, 6};
My question: In my experiment, I need the ciphertext with the exact number of slots (such as slots= 256, 1024, 4096
). Thus, I have to find the proper m, p, bits
to generate such a ciphertext with these slots. But for these m, p, bits
, I don't know how to set mvec, gens, ords
.
Here is a particular example:
long m = 12800;
long p = 127;
long r = 1;
long bits = 119;
long c = 2;
vector<long> mvec = {25, 512};
vector<long> gens = {2, 128};
vector<long> ords = {43, 4351};
Throw an exception: terminating with uncaught exception of type helib::LogicError: Bad user-supplied generator
// Some Information about this context:
m = 12800, p = 127, phi(m) = 5120
ord(p) = 20
normBnd = 1.23107
polyNormBnd = 1.23107
factors = [2 5]
generator 43 has order (== Z_m^*) of 128
generator 4351 has order (== Z_m^*) of 2
r = 1
nslots = 256
hwt = 0
ctxtPrimes = [6,7]
specialPrimes = [8]
number of bits = 173
security level = 98.4643
Update: I run an example with the parameters found by HElib (misc/psi/params.cpp
), but throw an exception LogicError: rawModSwitch scaled noise exceeds bound: 309684.692524
.
The given parameters are: phim=7056, d=28, m=12789, m=(3^2)*7^2*{29}, m/phim(m)=1.81, C=74 D=2 E=2, mvec="[49 261]" gens="[11224 7106]" ords="[42 6]"
The code is written for performing multiple multiplications while checking the noise and performing bootstrapping.
long m = 12789;
long p = 127;
long r = 1;
long bits = 119;
long c = 2;
// Factorisation of m required for bootstrapping.
vector<long> mvec = {49, 261};
// Generating set of Zm* group.
vector<long> gens = {11224, 7106};
// Orders of the previous generators.
vector<long> ords = {42, 6};
Context context = ContextBuilder<BGV>()
.m(m)
.p(p)
.r(r)
.gens(gens)
.ords(ords)
.bits(bits)
.c(c)
.bootstrappable(true)
.mvec(mvec)
.build();
// Key management
SecKey secret_key(context);
secret_key.GenSecKey();
addSome1DMatrices(secret_key);
addFrbMatrices(secret_key);
secret_key.genRecryptData();
const PubKey& public_key = secret_key;
const EncryptedArray& ea = context.getEA();
// create a ciphertext
std::vector<long> ptxt(nslots);
for (int i = 0; i < nslots; ++i) {
ptxt[i] = 2;
}
Ctxt ctxt(public_key);
ea.encrypt(ctxt, public_key, ptxt);
// multiplication and bootstrapping
for (int i = 0; i < 10; i++) {
if (ctxt.bitCapacity() <= 50)
{
cout << "Begin bootstrapping!" << endl;
public_key.thinReCrypt(ctxt);
}
ctxt.square();
}
The exception:
Begin bootstrapping!
libc++abi: terminating with uncaught exception of type helib::LogicError: rawModSwitch scaled noise exceeds bound: 309684.692524
terminating with uncaught exception of type helib::LogicError: rawModSwitch scaled noise exceeds bound: 309684.692524