How to set bootstrapping parameters with ringdimensions of 2^16 and 128-bit security

Hello everyone!
Thank you for always providing such a great library!

I’m currently conducting research using CKKS and am a beginner.

I’ve never used bootstrapping before, in particular.

So, I have a question: when achieving 128-bit security with ring dimension = 2^16, how should I set the bootstrapping parameters?

I created the following program based on advanced-ckks-bootstrapping.ccp, but an error occurred.

#define PROFILE

#include "openfhe.h"

using namespace lbcrypto;

void BootstrapExample(uint32_t numSlots);

int main(int argc, char* argv[]) {
    BootstrapExample(8);
}

void BootstrapExample(uint32_t numSlots) {
    CCParams<CryptoContextCKKSRNS> parameters;

    SecretKeyDist secretKeyDist = UNIFORM_TERNARY;
    parameters.SetSecretKeyDist(secretKeyDist);

    parameters.SetSecurityLevel(HEStd_128_classic); //changed
    parameters.SetRingDim(1 << 16); //changed

    parameters.SetNumLargeDigits(3);
    parameters.SetKeySwitchTechnique(HYBRID);

#if NATIVEINT == 128
    ScalingTechnique rescaleTech = FIXEDAUTO;
    usint dcrtBits               = 78;
    usint firstMod               = 89;
#else
    ScalingTechnique rescaleTech = FLEXIBLEAUTO;
    usint dcrtBits               = 59;
    usint firstMod               = 60;
#endif

    parameters.SetScalingModSize(dcrtBits);
    parameters.SetScalingTechnique(rescaleTech);
    parameters.SetFirstModSize(firstMod);

    std::vector<uint32_t> levelBudget = {4, 4}; //changed

    std::vector<uint32_t> bsgsDim = {0, 0};

    uint32_t levelsAvailableAfterBootstrap = 3; //changed
    usint depth = levelsAvailableAfterBootstrap + FHECKKSRNS::GetBootstrapDepth(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;

    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 - 1, nullptr, numSlots);
    ptxt->SetLength(numSlots);
    std::cout << "Input: " << ptxt << std::endl;

    Ciphertext<DCRTPoly> ciph = cryptoContext->Encrypt(keyPair.publicKey, ptxt);

    std::cout << "Initial number of levels remaining: " << depth - ciph->GetLevel() << std::endl;

    auto ciphertextAfter = cryptoContext->EvalBootstrap(ciph);

    std::cout << "Number of levels remaining after bootstrapping: " << depth - ciphertextAfter->GetLevel() << std::endl
              << std::endl;

    Plaintext result;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextAfter, &result);
    result->SetLength(numSlots);
    std::cout << "Output after bootstrapping \n\t" << result << std::endl;
}

openfhe-development/src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp:l.148:ParamsGenCKKSRNSInternal(): The specified ring dimension (65536) does not comply with HE standards recommendation (131072).

Looking at other papers, it appears that bootstrapping has been successfully performed while achieving 128-bit security with N = 2^16.

Thank you in advance for your help.

The issue is that the modulus QP computed internally for your parameters is larger than the maximum modulus for N=2^{16} that stills support 128 bits of security (this is based on Table 5.2 of https://cic.iacr.org/p/1/4/26/). To fix this, you can either increase the ring dimension from 2^{16} to 2^{17} or simply comment out the SetRingDim line. Alternatively, you could try to play with various parameters, like the number of larger digits, to see if you could find a configuration that works for N=2^{16} for your case. The latter requires deeper understanding of CKKS bootstrapping.

1 Like

Thanks for your reply.

As you said, I tried various numbers of digits and was able to bootstrap.

I referenced this paper