Support to CKKS modulus chain with 32-bit co-primes

Hello there,

I am looking into parametrizing CKKS with modulus chain containing co-primes of up to 32 bits.
I try to enforce it by setting firstModSize=30 and scalingModSize=27, while the library is compiled with NATIVEINT=64.

For context, the parameters are set as per the code snippet below:

    lbcrypto::CCParams<lbcrypto::CryptoContextCKKSRNS> parameters;
    parameters.SetSecurityLevel(lbcrypto::HEStd_128_classic);
    parameters.SetRingDim(1 << 16);
    std::vector<uint32_t> levelBudget = {4, 4};
    SecretKeyDist secretKeyDist = UNIFORM_TERNARY;
    parameters.SetSecretKeyDist(secretKeyDist);
    uint32_t depth = 16 + lbcrypto::FHECKKSRNS::GetBootstrapDepth(8, levelBudget, secretKeyDist);
    parameters.SetMultiplicativeDepth(depth);
    // NATIVEINT comes from OpenFHE #defines.
    if (NATIVEINT == 128) {
        parameters.SetScalingModSize(78);
        parameters.SetFirstModSize(89);
    } else { // NATIVEINT=64 or NATIVEINT=32
        parameters.SetScalingModSize(27);
        parameters.SetFirstModSize(30);
    }

However, the modulus chain generated contains co-primes with 60 bits instead of breaking them down into co-primes of half the size – see below.

q_0: 1073479681,  log q_0: 29.9996
q_1: 158072833,  log q_1: 27.236
q_2: 113246209,  log q_2: 26.7549
q_3: 156499969,  log q_3: 27.2216
q_4: 114032641,  log q_4: 26.7649
q_5: 155189249,  log q_5: 27.2095
q_6: 115081217,  log q_6: 26.7781
q_7: 154533889,  log q_7: 27.2033
q_8: 115212289,  log q_8: 26.7797
q_9: 152174593,  log q_9: 27.1812
q_10: 115998721,  log q_10: 26.7895
q_11: 151388161,  log q_11: 27.1737
q_12: 117964801,  log q_12: 26.8138
q_13: 151257089,  log q_13: 27.1724
q_14: 118751233,  log q_14: 26.8234
q_15: 150863873,  log q_15: 27.1687
q_16: 120324097,  log q_16: 26.8424
q_17: 149815297,  log q_17: 27.1586
q_18: 120586241,  log q_18: 26.8455
q_19: 147849217,  log q_19: 27.1396
q_20: 123863041,  log q_20: 26.8842
q_21: 145489921,  log q_21: 27.1163
q_22: 125042689,  log q_22: 26.8978
q_23: 144310273,  log q_23: 27.1046
q_24: 125698049,  log q_24: 26.9054
q_25: 142344193,  log q_25: 27.0848
q_26: 126222337,  log q_26: 26.9114
q_27: 141557761,  log q_27: 27.0768
q_28: 126615553,  log q_28: 26.9159
q_29: 140771329,  log q_29: 27.0688
q_30: 127664129,  log q_30: 26.9278
q_31: 138412033,  log q_31: 27.0444
q_32: 127795201,  log q_32: 26.9293
q_33: 136314881,  log q_33: 27.0224
q_34: 130809857,  log q_34: 26.9629
q_35: 135135233,  log q_35: 27.0098
q_36: 132120577,  log q_36: 26.9773
q_37: 134348801,  log q_37: 27.0014
q_38: 1152921504606584833,  log q_38: 60
q_39: 1152921504598720513,  log q_39: 60
q_40: 1152921504597016577,  log q_40: 60
q_41: 1152921504595968001,  log q_41: 60
q_42: 1152921504592822273,  log q_42: 60
q_43: 1152921504592429057,  log q_43: 60
Total bit length: 1388.9

Why did it not just generated more co-primes instead of resorting to 60-bit ones?

Then, I recompiled the OpenFHE library with NATIVEINT=32 and recompiled the application with firstModSize=28, with which I got the following runtime error below.

fatal error: in "test_case": lbcrypto::math_error: /home/user/openfhe-development/src/core/lib/math/nbtheory.cpp:518 FirstPrime math exception

The question is how to ensure that each modulus in the chain respects the 32-bit word size.
In the current OpenFHE CKKS implementation is this possible/supported? If so, how to accomplish it?

Thanks in advance

I am not sure I fully understood your question, are you asking why you are getting 60-bit primes at the end of the primes chain?

If so, note that these primes q_38 to q_43, in your log, are auxiliary primes used in the Hybrid Key Switching operation. They are of constant size - 60-bit in 64-bit implementation, see here.

OpenFHE uses the highest possible bit-width, the underlying computing platform can support, for these auxiliary primes for efficiency reasons. Reducing the size to scalingModSize would require more primes, and would be less efficient.

1 Like

Thank you for the swift reply. Yes, you understood my question – sorry there was a typo there making the statement contradictory.

I suspected that the AUXMODSIZE was causing it to make them 60 bits.
What if the underlying platform supports up to 32 bits? Could we have these auxiliary primes under 32 bits? If so, how could we force that? In the target application, the scalingModSize is currently set to less than 32 bits.

Given this efficiency constraint about the Hybrid Key Switching operation (only 60 bits and above), what does it mean to compile the library with NATIVEINT=32? Which schemes does this compilation support?

Thank you in advance

We recommend running CKKS in 64-bit or 128-bit modes. 32-bit mode for CKKS has several issues related to security and precision, that’s why it is not recommended.

On the other hand, 32-bit mode can be used (and it is recommended for best performance) for the binfhe family of schemes.

Thank you again for the clarification. :slight_smile:

Could you point us to references that discuss the security/precision issue with 32-bit CKKS implementation? I am interested in learning more.

Thanks

For more details, see the following works:

  1. Precision
  2. Security

One more paper on security: https://eprint.iacr.org/2022/816.pdf (see especially the Conclusion)