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.11k stars 760 forks source link

Decrypting a polynomial of degree close to the cyclotomic polynomial degree m (x^m+1) is incorrect #454

Open badr007-01 opened 2 years ago

badr007-01 commented 2 years ago

Hello, i am a new user of this library. My main goal is to convert a text to binary ("e" =01100101 ) and pack it into the a polynomial P2. Then apply computations in these polynomials. you will find my code above. Please let me know if anyone has another solution to propose. `

          #include <helib/Context.h>
          #include <helib/polyEval.h>
          #include <helib/PolyMod.h>
          #include <sstream>
          #include <helib/PAlgebra.h>
          #include <helib/timing.h>
          #include <helib/zzX.h>
          #include <helib/range.h>

          #include <climits>   // CHAR_BIT
          #include <cstddef>   // std::size_t
          #include <iostream>  // std::cout, std::endl

          #include <iostream>

          #include <helib/helib.h>
          #include <helib/binaryArith.h>
          #include <helib/intraSlot.h>
          #include <iostream>
          #include <bitset>
          using namespace std;

    // convert from text to binary string for example : "e" = 01100101.
        string TextToBinaryString(string words) {
                    string binaryString = "";
                    for (char& _char : words) {
                        binaryString +=bitset<8>(_char).to_string();
                    }
                    return binaryString;
        }

        // Constructing a polynomial of degree m-1 through a text in binary. for exemple P2 ("e", 20) = 0 + 0x^1 + 0x^2 + 0x^3 + 0x^4 + 0x^5 + 0x^6 + 0x^7 + 0x^8 + 0x^9 + 0x^10 + 0x^11 + 0x^12 + -1x^13 + 0x^14 + -1x^15 + 0x^16 + 0x^17 + -1x^18 + -1x^19

        NTL::ZZX P2 (string pattern, int n){
            // Create the polynomial
        NTL::ZZX poly_P2;

        //Fill in the polynomial
        for (int i = 1; i < TextToBinaryString(pattern).length(); i++) {
        NTL::SetCoeff(poly_P2, n-i, TextToBinaryString(pattern)[i] %2) ;
        }
        poly_P2 *=-1;
        NTL::SetCoeff(poly_P2, 0, TextToBinaryString(pattern)[0] %2) ;
        //trunc(poly_P2x, poly_P2,101);
        return poly_P2;
        }

       //To print the polynomial 
        void printPoly1(NTL::ZZX poly)
        {
            int n =deg(poly)+1 ;
            for (int i=0; i<n; i++)
            {
                std::cout << poly[i];
               if (i != 0)
                   std::cout << "x^" << i ;
               if (i != n-1)
                   std::cout << " + ";
            }
            std::cout << "\n";
        }

        int main()
        {
                        string pattern = "e";
                     // Plaintext prime modulus p^r.
                    long p = 2;
                    long r = 4;
                    // Number of bits of the modulus chain. ?????
                    long bits = 500;
                    // Number of columns of Key-Switching matrix (typically 2 or 3).
                    long c = 2;
                    bool bootstrappableFlag_ = false;
                    // ordre of Cyclotomic polynomial.
                     long m = 2047;

                    // Initialize the context.
                    // This object will hold information about the algebra created from the
                    // previously set parameters.
                    helib::Context context = helib::ContextBuilder<helib::BGV>()
                    .m(m)
                    .p(p)
                    .r(r)
                    .c(c)
                    .bits(bits)
                    .bootstrappable(false)
                    .build();
                    // Print the context.
                    context.printout();
                    std::cout << std::endl;

                    // Create a secret key associated with the context.
                    std::cout << "Creating secret key..." << std::endl;
                    helib::SecKey secret_key(context);

                    // Generate the secret key.
                    secret_key.GenSecKey();

                    // Get the EncryptedArray of the context.
                    const helib::EncryptedArray& ea = context.getEA();

                    const helib::PubKey& public_key = secret_key;

                    long bitSize = pattern.length(); // la taille de palintext
                    std::cout << "Bitsize est  : " << bitSize << std::endl;

                    /****************************************************************************************
                     * Encryption of P2
                     *  **********************************************************************************/

                    // Create a ciphertext object for P2
                    helib::Ctxt ctxt_P2(public_key);
                    // Encrypt the package of Pm1 using the public_key
                    NTL::ZZX  poly_P2;
                    poly_P2= P2( pattern , m ); // i want to get a polynomial of degree m-1 to pack my pattern
                    public_key.Encrypt(ctxt_P2,poly_P2);

                     /****************************************************************************************
                     * Decryption of P2
                     *  **********************************************************************************/
                    NTL::ZZX Decpoly_P2 ;
                    secret_key.Decrypt(Decpoly_P2, ctxt_P2);
                    std::cout << "P2 Result without encryption " <<endl; printPoly1(P2(pattern,m));
                    std::cout << "Decrypted of P2 Result   " <<endl; printPoly1(Decpoly_P2);
                     /****************************************************************************************
                     *This is my issue :the result of P2  before and after encryption is not equal
                     *  **********************************************************************************/ 
            return 0;
            }
        `

I invite you to run the code and compare the two results of P2 before and after encryption. What are the conditions for decryption and why is it wrong?

Thanks for helping.