How can I extract the imformation of each polynomial and ciphertext?

Hello,

Detailed explanations on your example codes are very helpful to me in understanding how to use the library and general FHE.

However, due to the lack of knowledge of FHE and C++, I have questions about using OpenFHE.
All of my questions are based on RNS-CKKS.

  1. I want to get the coefficient of plaintext and keys (eval, secret, public, etc.).
    How can I print that values?
  • 1.1. std::cout<< plaintext <<std::endl;
    print the values in the slot, not the coefficient.

  • 1.2. std::cout<< cc->GetAllEvalMultKeys()<<std::endl;
    print the below errors:

In file included from /usr/local/include/openfhe/pke/openfhe.h:41:
In file included from /usr/local/include/openfhe/core/openfhecore.h:41:
In file included from /usr/local/include/openfhe/core/math/hal.h:55:
In file included from /usr/local/include/openfhe/core/math/hal/bigintbackend.h:71:
In file included from /usr/local/include/openfhe/core/math/hal/bigintdyn/backenddyn.h:41:
In file included from /usr/local/include/openfhe/core/math/hal/bigintdyn/mubintvecdyn.h:45:
/usr/local/include/openfhe/core/math/hal/bigintdyn/ubintdyn.h:408:37: error: no member named
      'ConvertToInt' in 'std::map<std::__cxx11::basic_string<char, std::char_traits<char>,
      std::allocator<char> >,
      std::vector<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > >,
      std::allocator<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>,
      std::allocator<char> > >, std::allocator<std::pair<const std::__cxx11::basic_string<char,
      std::char_traits<char>, std::allocator<char> >,
      std::vector<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > >,
      std::allocator<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > > > > > > >'
    ubint(const T& val) : ubint(val.ConvertToInt()) {}  // NOLINT
                                ~~~ ^
/home/hhlee/openfhe_test/test.cpp:215:39: note: in instantiation of function template specialization
      'bigintdyn::ubint<unsigned int>::ubint<std::map<std::__cxx11::basic_string<char,
      std::char_traits<char>, std::allocator<char> >,
      std::vector<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > >,
      std::allocator<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>,
      std::allocator<char> > >, std::allocator<std::pair<const std::__cxx11::basic_string<char,
      std::char_traits<char>, std::allocator<char> >,
      std::vector<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > >,
      std::allocator<std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned
      int> > > > > > > > > >, true>' requested here
    std::cout << "EvalMultKey :  " << cc->GetAllEvalMultKeys() << std::endl;
                                      ^
1 error generated.
CMakeFiles/test.dir/build.make:75: recipe for target 'CMakeFiles/test.dir/test.cpp.o' failed
make[2]: *** [CMakeFiles/test.dir/test.cpp.o] Error 1
CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/test.dir/all' failed
make[1]: *** [CMakeFiles/test.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2

How can I see the evalmultkeys? or fix this error?

  • 1.3. also, cc->GetPrivateKey() print the ‘0’, cc->GetCryptoParameters() and cc->GetScheme() print the address of them (0x…). How can I show any information?
  • 1.4. Are there functions to see the information of cipher/plaintext, evaluation key, secret key, and public key?
    Like prime, coefficient values, level, etc.
  1. I can print the coefficient of ciphertext by simply std::cout<<ciphertext;.
    From the printed results of the ciphertext, I can show the
    Element 0: 0: EVAL: […], 1: EVAL […] , 2: …,
    Element 1: 0: EVAL: […], 1: EVAL […], 3: …,
  • 2.1. EVAL means the NTT form of the polynomials?
  • 2.2. What does (Element 0,Element 1) mean, (m+as+e,a) or (a,m+as+e) ?
  1. Can I see the intra-operation results?
    I want to see the primitive level operations result like NTT/iNTT, base conversion (with modup and moddown result), automorphism (rotated result before key switching), etc.
    Just code each primitive operation and print the results? Or exist any functions to see that?

I’m sorry about the basic question about using your library.
Thank you for reading the long questions.

@lee2h It looks like you are asking 3 different/unrelated groups of questions (questions 1, 2, and 4 refer to the ability of printing our polynomial elements, question 3 is about CKKS parameters, and question 5 is about CKKS bootstrapping). Our policy is one question (a group of related questions) per topic. Could you create 3 separate topics, and we will be happy to answer them.

1 Like

@ypolyakov
I’ll create a separate topic for three groups of questions.
I’ve edited this post to only include questions related to the title.
Thanks for your answer.

Hi, OpenFHE is built for speed and performance – that’s why it is in C++ and not python or java.
some of these are C++ related , some relate to the way our objects are constructed, I’ll attempt to
give a quick answer to some – and to other developers, please feel free to jump in and augment if I am unclear or correct me if I am wrong.

1.1 the intent of plaintext.operator<< is to print the contents of the object in a form as close to the original data as possible. Even that often requires interpretation (such as desired length of vector).

1.2 Looks like one problem you have is that, for the most part, the user does not care exactly what a Ciphertext “is” so your needs are not covered by most standard functions. You can “<<” most objects to std::cout, but you have to be careful. In your case you show:

    std::cout << "EvalMultKey :  " << cc->GetAllEvalMultKeys() << std::endl;

failing. That’s becuase what this returns is a complicated object (it is a map, basically whose signature covers all those lines of error code) that does not have an operator<< defined for it. In those circumstances, your best bet might be to compile the code in debug mode, and use an IDE that supports breakpoints and code inspection to disect the results. That will at least point you to the correct class definition. It is always possible to make a local branch and print the contents of the code individually.

Another option is to serialize the object to a json file, which is (somewhat) human readable, but beware that complicated objects can give you huge output that you have to parse through by hand, though json viewers that let you hide fields are available.

1.3: if you get an address, then you are working with s pointer, and you need to de-reference that poitner to get the content of the object. Most of the time that works if the object has an “operator<<” method defined.
i.e., if:
cout <<foo<<endl;
gives an address then you need to say
cout<<*foo<<endl;
instead. this is standard c/c++ behavior. Note in most cases these are smart pointers vs. regular pointers, but that should not matter, but will confuse the issue (if you see std::shared_ptr<> in the error output, that indicates a pointer is being used).

1.4 If you go to the definition of the object in the source code, you can usually find getters that let you pull out a copy of those components. you can then manipulate them including printing them out. Using an IDE like eclipse or vscode helps with this immensely – often you can right click on a variable, and jump to the declaration or definition, then look for the methods that are defined.
Realize if you are wanting to dig into the details that aren’t commonly used by others, you may have to define your own getters in your own repo.

2.1 Eval is the format which means the vector AFTER an NTT is performed (COEF is before). Equivalent to the frequency domain of an FFT.
Most of our objects stay in EVAL as that is where we do most math. we convert to COEF (inverse NTT) when we need to get at the coefficients (mostly during key switch operations), but often convert back again (unless we are decrypting).

The ciphertext here has two major elements (DCRTpolys), both of which contains several vectors in Eval Form. The first DCRT poly is l listed as Element 0, and you can see the vectors 0:, 1: etc. the contents of which are in the square brackets] each element of that vector is a machine native size integer. I can’t recall which element corresponds to a but you have the right idea. If you dive into the object definition it may tell you the order of those two. Internally it is a vector of two DCRTpoly.

  1. You can, but you have to instrument the code yourself. Those tend to be things only interesting during debugging. Some of the source code may have DEBUG statements, you can look for the debug.h file to see how they can be enabled, or how you can add your own in your own branch.
1 Like

@lee2h In addition to the response by @dcousins, I am including here some examples to cover different cases you were asking about. All crypto objects are composed of polynomials (DCTPoly in the case of RNS variants). You can always get to the underlying polynomials and output them.

Below I am including a revised simple-integers.cpp example with all these examples.

To output a ciphertext, you can do the following:

    // example of showing polynomials in ciphertexts
    auto ciphertextElements = ciphertext1->GetElements();
    for (size_t i = 0; i < ciphertextElements.size(); i++)
    	std::cout << "Polynomial " << i << " " << ciphertextElements[i] << std::endl;

To output all multiplication evaluation keys, you can do something like this

    // example of showing polynomials in an eval key (relinearization key)
    auto multMap = cryptoContext->GetAllEvalMultKeys();
    for (auto it = multMap.begin(); it != multMap.end();) {
        std::cout << it->first[0] << std::endl;
    	auto keyElementsA = it->second[0]->GetAVector();
    	auto keyElementsB = it->second[0]->GetBVector();
        for (size_t i = 0; i < keyElementsA.size(); i++) {
        	std::cout << "Polynomial A" << i << " " << keyElementsA[i] << std::endl;
        	std::cout << "Polynomial B" << i << " " << keyElementsB[i] << std::endl;
        }
        ++it;
    }

To display a secret key polynomial:

    // example of showing the polynomials in the secret key
    DCRTPoly skElement = keyPair.secretKey->GetPrivateElement();
  	std::cout << "SK Polynomial in EVAL" << skElement << std::endl;

if you want to switch from EVALUATION presentation (NTT form) to COEFFICIENT, you can do something like this

  	skElement.SetFormat(Format::COEFFICIENT);
  	std::cout << "SK Polynomial in COEFF" << skElement << std::endl;

You can also look at the OpenFHE API documentation (OpenFHE Library API — OpenFHE documentation) for other crypto objects. Here is, for example, the public key API: Template Class PublicKeyImpl — OpenFHE documentation

#include "openfhe.h"

using namespace lbcrypto;

int main() {
    // Sample Program: Step 1: Set CryptoContext
    CCParams<CryptoContextBFVRNS> parameters;
    parameters.SetPlaintextModulus(65537);
    parameters.SetMultiplicativeDepth(3);
    parameters.SetRingDim(16);
    parameters.SetSecurityLevel(HEStd_NotSet);

    CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);
    // Enable features that you wish to use
    cryptoContext->Enable(PKE);
    cryptoContext->Enable(KEYSWITCH);
    cryptoContext->Enable(LEVELEDSHE);

    // Sample Program: Step 2: Key Generation

    // Initialize Public Key Containers
    KeyPair<DCRTPoly> keyPair;

    // Generate a public/private key pair
    keyPair = cryptoContext->KeyGen();

    // Generate the relinearization key
    cryptoContext->EvalMultKeyGen(keyPair.secretKey);

    // Generate the rotation evaluation keys
    cryptoContext->EvalRotateKeyGen(keyPair.secretKey, {1, 2, -1, -2});

    // Sample Program: Step 3: Encryption

    // First plaintext vector is encoded
    std::vector<int64_t> vectorOfInts1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    Plaintext plaintext1               = cryptoContext->MakePackedPlaintext(vectorOfInts1);
    // Second plaintext vector is encoded
    std::vector<int64_t> vectorOfInts2 = {3, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    Plaintext plaintext2               = cryptoContext->MakePackedPlaintext(vectorOfInts2);
    // Third plaintext vector is encoded
    std::vector<int64_t> vectorOfInts3 = {1, 2, 5, 2, 5, 6, 7, 8, 9, 10, 11, 12};
    Plaintext plaintext3               = cryptoContext->MakePackedPlaintext(vectorOfInts3);

    // The encoded vectors are encrypted
    auto ciphertext1 = cryptoContext->Encrypt(keyPair.publicKey, plaintext1);
    auto ciphertext2 = cryptoContext->Encrypt(keyPair.publicKey, plaintext2);
    auto ciphertext3 = cryptoContext->Encrypt(keyPair.publicKey, plaintext3);

    // example of showing polynomials in ciphertexts
    auto ciphertextElements = ciphertext1->GetElements();
    for (size_t i = 0; i < ciphertextElements.size(); i++)
    	std::cout << "Polynomial " << i << " " << ciphertextElements[i] << std::endl;

    // example of showing the polynomials in the secret key
    DCRTPoly skElement = keyPair.secretKey->GetPrivateElement();
  	std::cout << "SK Polynomial in EVAL" << skElement << std::endl;

  	skElement.SetFormat(Format::COEFFICIENT);
  	std::cout << "SK Polynomial in COEFF" << skElement << std::endl;

    // example of showing polynomials in an eval key (relinearization key)
    auto multMap = cryptoContext->GetAllEvalMultKeys();
    for (auto it = multMap.begin(); it != multMap.end();) {
        std::cout << it->first[0] << std::endl;
    	auto keyElementsA = it->second[0]->GetAVector();
    	auto keyElementsB = it->second[0]->GetBVector();
        for (size_t i = 0; i < keyElementsA.size(); i++) {
        	std::cout << "Polynomial A" << i << " " << keyElementsA[i] << std::endl;
        	std::cout << "Polynomial B" << i << " " << keyElementsB[i] << std::endl;
        }
        ++it;
    }

    // Sample Program: Step 4: Evaluation

    // Homomorphic additions
    auto ciphertextAdd12     = cryptoContext->EvalAdd(ciphertext1, ciphertext2);
    auto ciphertextAddResult = cryptoContext->EvalAdd(ciphertextAdd12, ciphertext3);

    // Homomorphic multiplications
    auto ciphertextMul12      = cryptoContext->EvalMult(ciphertext1, ciphertext2);
    auto ciphertextMultResult = cryptoContext->EvalMult(ciphertextMul12, ciphertext3);

    // Homomorphic rotations
    auto ciphertextRot1 = cryptoContext->EvalRotate(ciphertext1, 1);
    auto ciphertextRot2 = cryptoContext->EvalRotate(ciphertext1, 2);
    auto ciphertextRot3 = cryptoContext->EvalRotate(ciphertext1, -1);
    auto ciphertextRot4 = cryptoContext->EvalRotate(ciphertext1, -2);

    // Sample Program: Step 5: Decryption

    // Decrypt the result of additions
    Plaintext plaintextAddResult;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextAddResult, &plaintextAddResult);

    // Decrypt the result of multiplications
    Plaintext plaintextMultResult;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextMultResult, &plaintextMultResult);

    // Decrypt the result of rotations
    Plaintext plaintextRot1;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextRot1, &plaintextRot1);
    Plaintext plaintextRot2;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextRot2, &plaintextRot2);
    Plaintext plaintextRot3;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextRot3, &plaintextRot3);
    Plaintext plaintextRot4;
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextRot4, &plaintextRot4);

    plaintextRot1->SetLength(vectorOfInts1.size());
    plaintextRot2->SetLength(vectorOfInts1.size());
    plaintextRot3->SetLength(vectorOfInts1.size());
    plaintextRot4->SetLength(vectorOfInts1.size());

    std::cout << "Plaintext #1: " << plaintext1 << std::endl;
    std::cout << "Plaintext #2: " << plaintext2 << std::endl;
    std::cout << "Plaintext #3: " << plaintext3 << std::endl;

    // Output results
    std::cout << "\nResults of homomorphic computations" << std::endl;
    std::cout << "#1 + #2 + #3: " << plaintextAddResult << std::endl;
    std::cout << "#1 * #2 * #3: " << plaintextMultResult << std::endl;
    std::cout << "Left rotation of #1 by 1: " << plaintextRot1 << std::endl;
    std::cout << "Left rotation of #1 by 2: " << plaintextRot2 << std::endl;
    std::cout << "Right rotation of #1 by 1: " << plaintextRot3 << std::endl;
    std::cout << "Right rotation of #1 by 2: " << plaintextRot4 << std::endl;

    return 0;
}
3 Likes

@dcousins @ypolyakov
Thanks for your kind and detailed answers!

@ypolyakov hi there,

I am also trying to dump some of the data. I have 2 questions.

  1. Is the format of following code coefficient polynomial?
// example of showing polynomials in ciphertexts
auto ciphertextElements = ciphertext1->GetElements();
for (size_t i = 0; i < ciphertextElements.size(); i++)
    std::cout << "Polynomial " << i << " " << ciphertextElements[i] << std::endl;
  1. Could following code be used on converting ciphertext between DCRT and NTT formats?
skElement.SetFormat(Format::COEFFICIENT);

Thanks.

Hi @xuann6,

Yes, both are correct. Note that

skElement.SetFormat(Format::COEFFICIENT);

switches the small polynomials composing the Double-CRT polynomial from NTT/Evaluation representation to Coefficient representation. The Coefficient representation is used for RNS operations and the NTT representation is used for polynomial multiplication. This is what you probably meant but I just wanted to clarify it for other members of the Forum.

1 Like

Hi @ypolyakov,

Thanks for the reply.

Could you mark my answer as a Solution if you are happy with the answer.

Note that I removed the second part of your message as it referred to a different topic/question which I answered directly in that topic.

1 Like

Got it! I’ll check the post, thanks a lot.