I’m using the CKKS cipher and encountered the following error:
The decryption failed because the approximation error is too high. Check the parameters.
I checked out Error “The decryption failed because the approximation error is too high. Check the parameters. ” after second EvalPolyPS() and Adjusting Parameters for “Approximation Error Too High” Error, but my result didn’t change.
I understand this error means that the error polynomial is large.So, e that satisfies <ct, sk> = m + e is too large.
And here’s the code.
#define PROFILE
#include "openfhe.h"
using namespace lbcrypto;
int main(int argc, char* argv[]) {
CCParams<CryptoContextCKKSRNS> parameters;
SecretKeyDist secretKeyDist = SPARSE_TERNARY;
parameters.SetSecretKeyDist(secretKeyDist);
parameters.SetSecurityLevel(HEStd_128_classic);
parameters.SetRingDim(1 << 16);
parameters.SetNumLargeDigits(3);
parameters.SetKeySwitchTechnique(HYBRID);
ScalingTechnique rescaleTech = FLEXIBLEAUTOEXT;
usint dcrtBits = 50;
usint firstMod = 57;
parameters.SetScalingModSize(dcrtBits);
parameters.SetScalingTechnique(rescaleTech);
parameters.SetFirstModSize(firstMod);
std::vector<uint32_t> levelBudget = {3, 3};
std::vector<uint32_t> bsgsDim = {0, 0};
uint32_t approxBootstrapDepth = 9;
uint32_t levelsAvailableAfterBootstrap = 7;
usint depth = levelsAvailableAfterBootstrap + FHECKKSRNS::GetBootstrapDepth(approxBootstrapDepth, levelBudget, secretKeyDist);
parameters.SetMultiplicativeDepth(depth);
CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);
cryptoContext->Enable(PKE);
cryptoContext->Enable(KEYSWITCH);
cryptoContext->Enable(LEVELEDSHE);
cryptoContext->Enable(ADVANCEDSHE);
cryptoContext->Enable(FHE);
usint ringDim = cryptoContext->GetRingDimension();
std::cout << "CKKS scheme is using ring dimension " << ringDim << std::endl << std::endl;
uint32_t numSlots = ringDim/2;
cryptoContext->EvalBootstrapSetup(levelBudget, bsgsDim, numSlots);
auto keyPair = cryptoContext->KeyGen();
cryptoContext->EvalMultKeyGen(keyPair.secretKey);
cryptoContext->EvalBootstrapKeyGen(keyPair.secretKey, numSlots);
std::vector<double> x;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0.0, 1.0);
for (size_t i = 0; i < numSlots; i++) {
x.push_back(dis(gen));
}
Plaintext ptxt = cryptoContext->MakeCKKSPackedPlaintext(x, 1, depth - 5, nullptr, numSlots);
Ciphertext<DCRTPoly> ciph = cryptoContext->Encrypt(keyPair.publicKey, ptxt);
//product storage
Ciphertext<DCRTPoly> product_storage = cryptoContext->Encrypt(keyPair.publicKey, ptxt);
for (int i=0; i<4; i++){
//multiply by 1
std::vector<double> y(numSlots, 1);
Plaintext ptxt_1 = cryptoContext->MakeCKKSPackedPlaintext(y, 1, 0, nullptr, numSlots);
product_storage=cryptoContext->EvalAdd(product_storage, cryptoContext->EvalMult(ciph, ptxt_1));
}
//I've used up my budget, so I'm going to refresh myself.
auto ciphertextAfter = cryptoContext->EvalBootstrap(product_storage);
Plaintext result;
cryptoContext->Decrypt(keyPair.secretKey, ciphertextAfter, &result);
std::cout << "Output after bootstrapping \n\t" << result->GetRealPackedValue()[0] << std::endl;
//correct result
cryptoContext->Decrypt(keyPair.secretKey, product_storage, &result);
std::cout << "Output after bootstrapping \n\t" << result->GetRealPackedValue()[0] << std::endl;
}
I also tried setting uint32_t numSlots = ringDim/32 and it worked.
I’m sure that the this is caused by bootstrapping because the ciphertext without bootstrapping was decrypted correctly.
If you know of any causes or improvements, please let me know.