Hi,
I encountered an issue when operating within an invalid encryption context.
When using encryption parameters with multiplicative depth set to 0, attempting a multiplication (e.g., EvalMult
) does not throw any exceptions in BFV/BGV. Instead, it produces meaningless values.
While I understand that performing a multiplication in this context is not allowed, I believe the library should fail explicitly — for example, by throwing a "Not enough towers"
or similar descriptive exception — rather than silently producing invalid results.
Code Examples
Here’s the simple version of code examples (v1.2.4):
- In both cases (BFV and BGV), the output varies across executions, yielding inconsistent values.
- In the BFV example, I intentionally used
EvalMult
with two ciphertexts, while in the BGV example, I used it with a ciphertext and a plaintext. However, the same issue occurs in the reverse scenario as well — that is, when multiplying a ciphertext with a plaintext in BFV, or two ciphertexts in BGV.
BFV
int main(void)
{
CCParams<CryptoContextBFVRNS> parameters;
parameters.SetRingDim(32768);
parameters.SetMultiplicativeDepth(0);
parameters.SetPlaintextModulus(65537);
parameters.SetScalingModSize(54);
parameters.SetSecurityLevel(HEStd_192_classic);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
KeyPair<DCRTPoly> keyPair;
keyPair = cc->KeyGen();
cc->EvalMultKeyGen(keyPair.secretKey);
size_t slots(4795);
vector<int64_t> tmp_vec_(4795);
Plaintext tmp;
int rots_num = 20;
vector<int> rots(rots_num + 1);
for (int i = 0; i < rots_num + 1; ++i)
{
rots[i] = i;
}
cc->EvalRotateKeyGen(keyPair.secretKey, rots);
Ciphertext<DCRTPoly> tmp_;
Ciphertext<DCRTPoly> x, y;
int yP;
int yC;
int c;
vector<int64_t> tmp_vec_1 = {320, 539, 94, 741, 167};
tmp = cc->MakePackedPlaintext(tmp_vec_1);
x = cc->Encrypt(keyPair.publicKey, tmp);
vector<int64_t> tmp_vec_2 = {1, 1, 1, 1, 1};
tmp = cc->MakePackedPlaintext(tmp_vec_2);
y = cc->Encrypt(keyPair.publicKey, tmp);
x = cc->EvalMult(x, y);
cc->Decrypt(keyPair.secretKey, x, &tmp);
tmp->SetLength(5);
tmp_vec_ = tmp->GetPackedValue();
for (auto v : tmp_vec_)
{
cout << v << " ";
}
cout << endl;
return 0;
}
BGV
int main(void) {
CCParams<CryptoContextBGVRNS> parameters;
parameters.SetRingDim(8192);
parameters.SetMultiplicativeDepth(0);
parameters.SetPlaintextModulus(65537);
parameters.SetSecurityLevel(HEStd_192_classic);
parameters.SetScalingTechnique(FIXEDMANUAL);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
KeyPair<DCRTPoly> keyPair;
keyPair = cc->KeyGen();
cc->EvalMultKeyGen(keyPair.secretKey);
size_t slots(2352);
vector<int64_t> tmp_vec_(2352);
Plaintext tmp;
int rots_num = 20;
vector<int> rots(rots_num + 1);
for(int i = 0; i < rots_num + 1; ++i) {
rots[i] = i;
}
cc->EvalRotateKeyGen(keyPair.secretKey, rots);
Ciphertext<DCRTPoly> tmp_;
Ciphertext<DCRTPoly> x, y;
int yP;
int yC;
int c;
vector<int64_t> tmp_vec_1 = { 156, 480, 303, 314, 241 };
tmp = cc->MakePackedPlaintext(tmp_vec_1);
x = cc->Encrypt(keyPair.publicKey, tmp);
yP = 1;
fill(tmp_vec_.begin(), tmp_vec_.end(), yP);
tmp = cc->MakePackedPlaintext(tmp_vec_);
x = cc->EvalMult(x, tmp);
cc->Decrypt(keyPair.secretKey, x, &tmp);
tmp->SetLength(5);
tmp_vec_ = tmp->GetPackedValue();
for (auto v : tmp_vec_) {
cout << v << " ";
}
cout << endl;
return 0;
}
Would love to hear your thoughts. Thanks in advance!