homenc / HElib

HElib is an open-source software library that implements homomorphic encryption. It supports the BGV scheme with bootstrapping and the Approximate Number CKKS scheme. HElib also includes optimizations for efficient homomorphic evaluation, focusing on effective use of ciphertext packing techniques and on the Gentry-Halevi-Smart optimizations.
https://homenc.github.io/HElib
Other
3.15k stars 763 forks source link

Setting FHEcontext object with a negative order via File IO causes an error of rotation for packed-ciphertext #110

Open makky0y opened 8 years ago

makky0y commented 8 years ago

Suppose an FHEcontext object contains negative order in zMStar and that object is written into a file, loading the FHEcontext object from the file causes a different context since writing a FHEcontext object into a file calls PAlgebra.OrderOf function. This causes a shift/rotate error on EncryptedArray objects. PAlgebra.OrderOf returns the absolute value of a specific order in PAlgebra.ords. In the Client-Server model, where FHEcontext object is set via file I/O, the object of FHEcontext on the server side is different from that on the client side. In that case, actually rotate operation causes wrong result on the server side. Should the member function OrderOf in PAlgebra return not absolute value of an order in some parameter settings?

I have referred to Test_Boostrapping.cpp and used some same parameters defined as mValues[]. For example, mValues[5] contains a negative order "-8". But it is written into a file as "8" when outputting the obj of FHEcontext on the client side. That means that the server set the context object whose zMStar contains the order not -8 but 8. Is this possible to use parameters containing negative orders?

shaih commented 8 years ago

Can you append a short piece of code that demonstrate this problem? Thanks, -- Shai

makky0y commented 8 years ago

I have written a code that just conducts one-left cyclic rotation for an encrypted vector. So given a vector [ 0 0 0 0 0 1 1 1 .....1 1 1], it must become [0 0 0 0 1 1 1 .....1 1 1 0] This vector is encrypted on the client side, and is sent to the server. The server conducts cyclic rotation for it. Then it is returned back to the client.

I put the code in TestIt function of Test_boostrapping.cpp. All of the parameters I used are same as those used in Test_bootstrapping.cpp. I remove the recryption procedure since it is not needed here. When I use mValues[3],[4] or other params containing negative order value, a rotation does not work well.

//mvec gens ords and other parameters are determined above 
std::cout << "*************************** Key generation on client side *******************************" << std::endl; 
FHEcontext context(m, p, r, gens, ords);
context.bitsPerLevel = B;
buildModChain(context, L, c);
context.makeBootstrappable(mvec, /*t=*/0, cons);
if (skHwt>0) context.rcData.skHwt = skHwt;
context.zMStar.set_cM(mValues[idx][13]/100.0);
FHESecKey secretKey(context);
FHEPubKey& publicKey = secretKey;
secretKey.GenSecKey(64); 
addSome1DMatrices(secretKey);
addFrbMatrices(secretKey);
secretKey.genRecryptData();
EncryptedArray ea(context);

std::cout << "encoding and encryption " << std::endl;     
Ctxt c1(publicKey);
std::vector<long> vec1(ea.size(),1);
for(int i=0;i<ea.size();i++){
    if(i<5) vec1[i]=0;
}
std::cout << "to be encrypted vector " << std::endl; 
std::cerr << vec1 << std::endl; 
ea.encrypt(c1,publicKey,vec1);

std::cout << "  file writing... " << std::endl;             
std::string file = "iofile";
{   
    fstream keyFile( file,fstream::out| fstream::binary|fstream::trunc );
    writeContextBase(keyFile, context);
    keyFile << context;
    keyFile << publicKey;
    keyFile << c1; 
    keyFile << secretKey;
    keyFile.close();
}   

std::cout << "************************** Receive on server side *******************************" << std::endl; 
FHEcontext *context2;
FHEPubKey  *publicKey2;
FHESecKey  *secretKey2;
Ctxt *c2;

{   
    fstream keyFile(file,fstream::in|fstream::binary);
    unsigned long m1, p1, r1; 
    vector<long> gens2,ords2;
    readContextBase(keyFile,m1,p1,r1,gens2,ords2);
    context2 = new FHEcontext(m1,p1,r1,gens2,ords2);
    publicKey2 = new FHEPubKey(*context2);
    secretKey2 = new FHESecKey(*context2);
    keyFile >> *context2;
    keyFile >> *publicKey2;
    c2 = new Ctxt(*publicKey2);
    keyFile >> *c2;
    keyFile >> *secretKey2;
    keyFile.close();
}   
std::cout << "1-left rotation " << std::endl; 
EncryptedArray ea2(*context2);
ea2.rotate(*c2,-1);
{
    fstream keyFile( file,fstream::out| fstream::binary|fstream::trunc );
    keyFile << *c2;
    keyFile.close();
}

ea2.decrypt(*c2,*secretKey2,vec1);
std::cout << "*** decryption on server side 1-left rotated vector" << std::endl; 
std::cout << vec1 << std::endl; 

Ctxt cdec(publicKey);
{
    fstream keyFile(file,fstream::in|fstream::binary);
    keyFile >> cdec;                                                                                                                  
    keyFile.close();
}
ea.decrypt(cdec,secretKey,vec1);
std::cout << "*** decryption on client side 1-left rotated vector" << std::endl; 
std::cout <<  vec1 << std::endl;