Be ware of HElib and corresponding NTL versions

Today I tested an old HElib version (back to mid-2017), but met following compile errors:

......
In file included from EncryptedArray.cpp:15:
EncryptedArray.h:301:19: error: ‘FHE_DEFINE_LOWER_DISPATCH’ has not been declared
  301 |   NTL_FOREACH_ARG(FHE_DEFINE_LOWER_DISPATCH)
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~
EncryptedArray.h:303:3: error: ISO C++ forbids declaration of ‘NTL_FOREACH_ARG’ with no type [-fpermissive]
  303 |   const RX& getG() const { return mappingData.getG(); }
      |   ^~~~~
......

After some investigation, I found the problem was the NTL on my system is too new (version is 11.3.2). So I downloaded an old NTL version, and specified using this version in Makefile:

CFLAGS = -g -O2 -std=c++11 -I../../ntl-10.5.0/include ......

Then it worked like a charm!

Build legacy test files in HElib

In HElib src directory, there are some files which begin with Test_ prefix. Since HElib uses CMake to build it, these Test_* files won’t be compiled by default. To build and use them, ENABLE_LEGACY_TEST option should be turned ON:

$ cmake -DENABLE_LEGACY_TEST=ON ..
$ make

The executable files will be generated in bin folder:

$ cd bin/
$ ls
Test_approxNums     Test_bootstrapping  Test_General    Test_PAlgebra      Test_PtrVector          Test_ThinEvalMap
Test_binaryArith    Test_EaCx           Test_intraSlot  Test_Permutations  Test_Replicate          Test_Timing
Test_binaryCompare  Test_EvalMap        Test_IO         Test_PolyEval      Test_tableLookup
Test_Bin_IO         Test_extractDigits  Test_matmul     Test_Powerful      Test_ThinBootstrapping

 

Read Ctxt from stream in using HElib

Assume you need to read Ctxt from a stream (file, socket, or whatever) in using HElib, the general pattern is like this:

Ctxt ctxt(*pubKey);
while (fs >> ctxt)
{
    std::cout << ++count << std::endl;
}

But this will trigger following error (If you use one version of HElib to encrypt Ctxt, while use another version of HElib to process Ctxt, this error may occur too.):

Searching for cc='[' (ascii 91), found c='▒' (ascii -1)

The root cause of this issue is about handling EOF. To solve this issue, there are 2 methods:

(1)

Ctxt ctxt(*pubKey);
while (!fs.eof())
{
    fs >> ctxt >> std::ws;
    if (fs.fail())
    {
        break;
    }
}

fs >> ctxt >> std::ws; will stop when the EOF is met. Since fs.fail() won’t return true when eofbit is set (please refer here), fs.eof() will becometrue to terminate while-loop.

(2) know how many Ctxt will be read in advance. For example:

Ctxt ctxt(*pubKey);
for (int i = 0; i < 10; i++)
{
    fs >> ctxt;
}

Be careful of FHEcontext’s shallow copy feature in HElib

Check following code which uses HElib:

class A
{
    FHEcontext context;
public:
    FHEcontext& getContext()
    {
        return context;
    }
};

void func()
{
    auto context = a.getContext();
    ......
}

A a;

int main(void)
{
    ......
    func();
    ......
    return 0;
}

In func():

......
auto context = a.getContext();
......

It will allocate a local variable context whose type is FHEcontext, not “FHEcontext&“, and the point is it will be shallow copy of FHEcontext:

class FHEcontext {

......
  //! @breif A default EncryptedArray
  const EncryptedArray* ea;
......
}

FHEcontext::~FHEcontext()
{
  delete ea;
}

So when the local variable context is destroyed, the memory of ea is also released; this will lead to context member of class A references a already freed memory. That will be a disaster!

References:
auto specifier type deduction for references;
The issue about FHEcontext’s copy constructor/assignment operator.

 

Use Ctxt::isCorrect() to check Ctxt valid in using HElib

During using HElib, if the calculation made Ctxt‘s noise too big, it will cause Ctxt can’t be decrypted successfully, and the decrypted result is messy like this:

333317397173303 1016371194582039 217550837977960
737191953777559 1103851234911944 454685807668230
625213263895453 743713807221034 1036409711005678
447878070619549 603715795412661 948856958008786
......

You can leverage Ctxt::isCorrect() method to check whether Ctxt is still valid or not:

std::cout << "Ctxt is valid: " << c.isCorrect() << '\n';

Reference:
Maybe the bug in EncryptedArray’s shift function.