Hello! Me again!
I’m still in this journey of understanding OpenFHE. I’m trying to understand better why is the imaginary part used to see if a secret key attack occurred? and I got stuck in something silly like conjugate a vector…
This is in ckkspackedencoding.cpp
std::vector<std::complex<double>> Conjugate(const std::vector<std::complex<double>>& vec) {
uint32_t n = vec.size();
std::vector<std::complex<double>> result(n);
for (size_t i = 1; i < n; i++) {
result[i] = {-vec[n - i].imag(), -vec[n - i].real()};
}
result[0] = {vec[0].real(), -vec[0].imag()};
return result;
}
The zero index is how it was supposed to be implemented…
So i put a simple std::cerr to see a little bit whats going on. I put it in the same file but at 508, that conjugate is call for the secret key attack, and if I print the first 30 elements of the vector and its conjugate, I get the same elements… the only correct is the index zero…
(7.34012e+06, 16) (7.34012e+06,-16)
(7.2809e+06 ,-696052) (7.28086e+06,-695963)
(7.10487e+06,-1.37007e+06) (7.10535e+06,-1.36993e+06)
(6.81931e+06,-2.00041e+06) (6.81921e+06,-2.00057e+06)
(6.43361e+06,-2.56796e+06) (6.43351e+06,-2.56785e+06)
(5.96188e+06,-3.05483e+06) (5.96191e+06,-3.05459e+06)
...
I also remember that the plain text is expand to the double of the input size in a conjugate mirror way, so I thought that that’s why the result vector was fill with the elements of the original vector from last element to first.
But why each element of the result has as the real part the imaginary of the vector, and in the imaginary part the real part of the vector, and all with a minus. Why the real part is change?… Or for some reason the way that the mirror part is implemented it also flips the real part with the imaginary?
PD: Here is the example I’m using:
uint32_t multDepth = 1;
uint32_t scaleModSize = 30;
uint32_t firstModSize = 60;
uint32_t batchSize = 1024;
uint32_t ringDim= 2048;
ScalingTechnique rescaleTech = FIXEDMANUAL;
CCParams<CryptoContextCKKSRNS> parameters;
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetScalingModSize(scaleModSize);
parameters.SetFirstModSize(firstModSize);
parameters.SetBatchSize(batchSize);
parameters.SetRingDim(ringDim);
parameters.SetScalingTechnique(rescaleTech);
parameters.SetSecurityLevel(HEStd_NotSet);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
cc->Enable(PKE);
cc->Enable(LEVELEDSHE);
auto keys = cc->KeyGen();
std::vector<double> input = {0,1,2,3};
Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(input);
Ciphertext<DCRTPoly> c1 = cc->Encrypt(keys.publicKey, ptxt1);
Plaintext result;
std::vector<double> resultData(input.size());
cc->Decrypt(keys.secretKey, c1, &result);