I am trying to write a CKKS code and modify the parameters. Wanted to ask if there is way to set lower size for ciphertext modulus, as I set to lower ring dimensions. Wanted to understand how to go about it and should I be concerned about other parameter dependencies for it to work? Any pointers would be appreciated!
You can control the dimension of the ciphertext modulus by setting parameters.SetScalingModSize (size of one limb), parameters.SetFirstModSize (size of the first limb) and parameters.SetMultiplicativeDepth (total number of limbs). However, when determining the ring dimension in order to get a certain security level, it matters if you are using Hybrid Key Switching, which uses an extended ciphertext modulus. This can be controlled by parameters.SetKeySwitchTechnique and parameters.SetNumLargeDigits. Checkout how to print all limbs here OpenFHE CKKS chooses modulus chain that doesn't guarantee 128 bits of security.
Further, please check these discourse posts discussing dependencies and how to set the bit size of the moduli.
- Why do my parameters not comply with 128 bit security?
- Setting security parameters according to 128 bit security (very small CKKS scaling factor)
- Relationship between ScaleModSize and RingDimension
- Parameter settings in BFV, BGV, and CKKS - #2 by ypolyakov
- OpenFHE CKKS chooses modulus chain that doesn't guarantee 128 bits of security
Thank you so much. That is very helpful. I see that when I am trying to reduce the values of dcrtBits and firstMod, the precision decreases. Is there any mathematical reason as to how they are connected to precision so that I can modify accordingly for a lower dimension, say 2^9?
dcrtBits represents the size of the scaling factor, which is directly related to precision. firstMod is represents the number of bits of the modulus on which the decryption happens (assuming you consume all levels) which also affects the precision (rather correctness) of the returned result. Precision is also affected by using modes such as FLEXIBLEAUTOEXT, which incurs the least error at the cost of an extra small prime. To see concrete relations between the error (therefore the precision) and the ring dimension, please read Approximate Homomorphic Encryption with Reduced Approximation Error. For some higher-level useful discussions related to setting dcrtBits and firstMod in CKKS, see Meaning of the bit precision Bis, How should the outputs of the Precision Estimator be understood?, Is there a way to estimate the precision for a calculation?, Setting security parameters according to 128 bit security (very small CKKS scaling factor),
That being said, a ring dimension of 2^9 is very small, and 128-bit security might not be achieved with it (even for additive FHE, so multiplicative depth 0). You can consult the tables in https://eprint.iacr.org/2024/463.pdf to get some sense of what size of ring dimension would correspond to 128-bits for certain ciphertext modulus.
That’s extremely helpful. Thank you for all the details! Apologies for the last question, can you help provide a reference to which paper was used to implement the EvalBootstrap() for CKKS please? It would help me interpret the steps in the bootstrapping code (ckksrns-fhe.cpp).
I recommend you first search the forums, as there are many answers and resources already available. For instance, the relevant papers related to OpenFHE’s implementation of CKKS bootstrapping can be found here What is the CKKS bootstrapping algorithm in openfhe?.
Thank you so much. While I try to understand the bootstrap algorithm in ckksrns-fhe.cpp, it mentions in the comment section of EvalBootstrap that only level 0 is used before modular reduction. From bootstrapping math, I believe it should be done for all levels right? Is it just a software optimisation opted by openFHE to make bootstrapping faster?
“Level 0” is used before modulus raising, not before modular reduction, and the reason to drop to level 0 is indeed to save some computations; the same computations could be done at whatever level the ciphertext is at. Modulus reduction will always happen on “all levels”.
The intuition of CKKS bootstrapping is the following. You have a depleted ciphertext, which is either on level 0, or has too few levels to continue with the desired computation. We first raise the modulus, which corresponds to adding, say, L new levels. This step is sufficient to allow new computations, but it is vacuous on its own since the message is now corrupted by some overflows. Therefore, the next step of modular reduction is intended to extract the message, and is performed over all L levels, and will return a ciphertext on L - L_mr levels. This was a simplified discussion to show the intuition; in practice, there are more levels consumed during bootstrapping in order to perform the slots to coefficients and coefficients to slots transformations.
Thank you! That really helps