I’m studying Blind Rotation in FHEW/TFHE, and I’ve found that if I modify the loop order of the Blind Rotation, for example, changing the loop order of i from [0, 1, ..., n-1] to [n-1, n-2, ..., 0], the values of a and b in the LWE ciphertext before decryption change, but the decryption result remains the same.
BlindRotation loop:
void RingGSWAccumulatorCGGI::EvalAcc in rgsw-acc-cggi.cpp
for (size_t i = 0; i < n; ++i) {
AddToAccCGGI(…);
}
For example, normal order:
LWECiphertext a = [613, 759, 482, …, 501]
LWECiphertext b = 143
Reversed order:
LWECiphertext a = [10, 247, 76, …, 122]
LWECiphertext b = 631
But the decryption result is 1 in both cases.
I understand that mathematically this is because each step of Blind Rotation is homomorphic to a CMUX operation, so changing the order changes the result of the AddToAccCGGI polynomial operation, but the final decryption result remains unchanged.
I now want to verify the RLWECiphertext& acc accumulated by AddToAccCGGI, that is, add a helper function to decrypt RLWECiphertext acc to verify that each step of Blind Rotation is indeed equivalent to rotation for the RLWE ciphertext.
However, I checked rlwe-ciphertext.h under binfhe, and I didn’t find any interface provided by OpenFHE for the rlwe key and decryption function of RLWE ciphertexts in TFHE.
So I would like to know how I can obtain the rlwe secret key and decryption function for RLWE ciphertexts in FHEW/TFHE?
Currently the RLWE secret key is not used anywhere outside the KeyGen method (see openfhe-development/src/binfhe/lib/binfhe-base-scheme.cpp at v1.4.2 · openfheorg/openfhe-development · GitHub) You could modify the KeyGen method to store it somewhere (only for debugging purposes), e.g., in a global variable. The RLWE secret key is not needed for normal FHEW/TFHE operations in OpenFHE.
For RLWE decrypt, you could write a code similar to openfhe-development/src/pke/lib/schemelet/rlwe-mp.cpp at main · openfheorg/openfhe-development · GitHub - here we are dealing with a more general case (when the RLWE moduli are larger than 60 bits).
Thank you very much! Happy New Year!
I have solved the first question, which means store the RLWE secret key as a global variable.
But for RLWE decrypt, i noticed that the test vector was constructed as follows in BootstrapGateCore of binfhe-base-scheme.cpp.
std::vector<NativePoly> res(2);
auto& polyParams = RGSWParams->GetPolyParams();
// no need to do NTT as all coefficients of this poly are zero
res[0] = NativePoly(polyParams, Format::EVALUATION, true);
res[1] = NativePoly(polyParams, Format::COEFFICIENT, false);
res[1].SetValues(std::move(m), Format::COEFFICIENT);
res[1].SetFormat(Format::EVALUATION);
The res should be tLweNoiselessTrivial: (0, VX^{-b}), in the format EVALUATION.
However, for RLWE decryption, when I only perform RLWE[1] - RLWE[0]*RLWEKey, the decryption result seems meaningless. I’m not sure if this is because I’m not using the correct decoding method. So, is the code here applicable to RLWE ciphertexts? openfhe-development/src/pke/lib/schemelet/rlwe-mp.cpp at main · openfheorg/openfhe-development · GitHub.
I’ve been researching this, but it seems many of the methods in DecryptCoeff don’t appear in FHEW/TFHE, and I’m having trouble correlating them with the mathematical form of RLWE ciphertexts. Could you please provide me with some paper resources?
For RLWE decryption, I suggest reviewing Section 2 of Bootstrapping in FHEW-like Cryptosystems. Do not forget to round RLWE[1] - RLWE[0]*RLWEKey and make sure you do the rounding in the COEFFICIENT representation (note that the multiplication is done in the EVALUATION representation).