I hope to run CKKS ciphertext with a message count of 2^14 on a machine with 60GB of memory. When converted to FHEW ciphertext, it takes up 59.3GB of memory space (my computer also has other programs running, which takes up about 8GB). When calculating the EvalSign of FHEW, the program is directly killed. Is there a way to change parameters so that the program can run. I don’t know if using reset()
can clear memory, here is my code:
// Step 1: Setup CryptoContext for CKKS
ScalingTechnique scTech = FLEXIBLEAUTO;
uint32_t multDepth = 17;
if (scTech == FLEXIBLEAUTOEXT)
multDepth += 1;
uint32_t scaleModSize = 42;
uint32_t firstModSize = 48;
uint32_t ringDim = 1<<15;
SecurityLevel sl = HEStd_NotSet;
BINFHE_PARAMSET slBin = TOY;
uint32_t logQ_ccLWE = 17;
uint32_t slots = 1<<14; // full-packed
uint32_t batchSize = slots;
CCParams<CryptoContextCKKSRNS> parameters;
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetScalingModSize(scaleModSize);
parameters.SetFirstModSize(firstModSize);
parameters.SetScalingTechnique(scTech);
parameters.SetSecurityLevel(sl);
parameters.SetRingDim(ringDim);
parameters.SetBatchSize(batchSize);
parameters.SetSecretKeyDist(UNIFORM_TERNARY);
parameters.SetKeySwitchTechnique(HYBRID);
parameters.SetNumLargeDigits(4);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
// Enable the features that you wish to use
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
cc->Enable(ADVANCEDSHE);
cc->Enable(SCHEMESWITCH);
std::cout << "CKKS scheme is using ring dimension " << cc->GetRingDimension();
std::cout << ", number of slots " << slots << ", and supports a multiplicative depth of " << multDepth << std::endl
<< std::endl;
// Generate encryption keys
auto keys = cc->KeyGen();
// Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
SchSwchParams params;
params.SetSecurityLevelCKKS(sl);
params.SetSecurityLevelFHEW(slBin);
params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE);
params.SetNumSlotsCKKS(slots);
params.SetNumValues(slots);
auto privateKeyFHEW = cc->EvalSchemeSwitchingSetup(params);
auto ccLWE = cc->GetBinCCForSchemeSwitch();
ccLWE->BTKeyGen(privateKeyFHEW);
cc->EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW);
std::cout << "FHEW scheme is using lattice parameter " << ccLWE->GetParams()->GetLWEParams()->Getn();
std::cout << ", logQ " << logQ_ccLWE;
std::cout << ", and modulus q " << ccLWE->GetParams()->GetLWEParams()->Getq() << std::endl << std::endl;
// Set the scaling factor to be able to decrypt; the LWE mod switch is performed on the ciphertext at the last level
auto pLWE1 = ccLWE->GetMaxPlaintextSpace().ConvertToInt(); // Small precision
double scaleSignFHEW = 1.0;
cc->EvalCompareSwitchPrecompute(pLWE1, scaleSignFHEW);
std::cout<<"x1: "<<std::endl;
std::vector<double> x1(slots);
for(unsigned int i=0;i<slots;i++){
x1[i]=-30+i*0.001;
}std::cout<<"x1 end!!!\n";
// Encoding as plaintexts
Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(x1, 1, 0, nullptr, slots);
// Encrypt the encoded vectors
auto c1 = cc->Encrypt(keys.publicKey, ptxt1);
ptxt1.reset();
std::cout << "CKKS->FHEW before:"<<c1->GetLevel() << std::endl;
auto LWECiphertexts = cc->EvalCKKStoFHEW(c1, slots);
c1.reset();
std::cout << "Cryptography conversion completed" << std::endl;
// std::vector<LWECiphertext> LWESign(slots);
// LWEPlaintext plainLWE;
for(uint32_t i=0;i<slots;++i){
LWECiphertexts[i]=ccLWE->EvalSign(LWECiphertexts[i]);
// if(i<1000){
// ccLWE->Decrypt(privateKeyFHEW, LWECiphertexts[i], &plainLWE, pLWE1);
// std::cout << plainLWE << " ";
// }
}
std::cout << "sign Calculation completed" << std::endl;
auto c2 = cc->EvalFHEWtoCKKS(LWECiphertexts, slots);
LWECiphertexts.clear();
std::cout << "FHEW->CKKS end:"<<c2->GetLevel() << std::endl;
Plaintext plaintextDec3;
cc->Decrypt(keys.secretKey, c2, &plaintextDec3);
plaintextDec3->SetLength(slots);
std::cout << "Decrypted switched result: " << plaintextDec3 << std::endl;