Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected same polynomials on plaintext operation when more than 1 number in each slot #516

Open
wahyudierwin opened this issue Jan 2, 2025 · 1 comment

Comments

@wahyudierwin
Copy link

wahyudierwin commented Jan 2, 2025

Hi,

I am trying to understand BGV plaintext encoding in HELib, using the following parameters (see the code). In my understanding, the multiplication is done for each slot, e.g. (ptxt1[i] * ptxt2[i]) mod F_i(x) where F_i(x) is the factorization of the polynomial modulo phi_m(x). If we use the parameter in the code, m = 14, then the polynomial has a degree of 6, and factored into 3 polynomials of degree 2, hence it has 3 slots.

#include <cstdlib>
#include <ctime>

#include <helib/helib.h>

int main(int argc, char* argv[])
{
  // Plaintext prime modulus
  unsigned long p = 13;
  
  // Cyclotomic polynomial - defines phi(m)
  unsigned long m = 14;

  // Hensel lifting (default = 1)
  unsigned long r = 1;
  // Number of bits of the modulus chain
  unsigned long bits = 8;
  
  // Number of columns of Key-Switching matrix (default = 2 or 3)
  unsigned long c = 2;

  std::cout << "Initialising context object..." << std::endl;
  // Initialize 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)
                               .bits(bits)
                               .c(c)
                               .build();

  // Print the context
  context.printout();

  // Print the security level
  std::cout << "Security: " << context.securityLevel() << std::endl;

  // Secret key management
  std::cout << "Creating secret key..." << std::endl;
  // Create a secret key associated with the context
  helib::SecKey secret_key(context);
  // Generate the secret key
  secret_key.GenSecKey();
  std::cout << "Generating key-switching matrices..." << std::endl;
  // Compute key-switching matrices that we need
  helib::addSome1DMatrices(secret_key);

  // Public key management
  // Set the secret key (upcast: SecKey is a subclass of PubKey)
  const helib::PubKey& public_key = secret_key;

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

  // Get the number of slot (phi(m))
  long nslots = ea.size();
  std::cout << "Number of slots: " << nslots << std::endl;

  // Create a vector of long with nslots elements
  helib::Ptxt<helib::BGV> ptxt1(context), ptxt2(context), ptxt3(context);
  
  // from the defined parameters, it can computed manually that nslots = 3
  ptxt1[0] = {4,3};
  ptxt1[1] = {4,3};
  ptxt1[2] = {4,3};

  ptxt2[0] = {8,9};
  ptxt2[1] = {8,9};
  ptxt2[2] = {8,9};

  // Print the plaintext
  std::cout << "Initial Plaintext 1: " << ptxt1 << std::endl;
  std::cout << "Initial Plaintext 2: " << ptxt2 << std::endl;

  std::cout << "ptxt1 * ptxt2 =\n";
  std::cout << ptxt1 * ptxt2 << "\n";
  

  return 0;
}

The output is like this:

Initialising context object...
m = 14, p = 13, phi(m) = 6
  ord(p) = 2
  normBnd = 1.2518
  polyNormBnd = 1.2518
  factors = [2 7]
  generator 9 has order (== Z_m^*) of 3
  T = [ 1 9 11 ]
r = 1
nslots = 3
hwt = 0
ctxtPrimes = [6]
specialPrimes = [7]
number of bits = 109

security level = 0
Security: 0
Creating secret key...
Generating key-switching matrices...
Number of slots: 3
Initial Plaintext 1: {"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[4,3],[4,3],[4,3]]},"serializationVersion":"0.0.1","type":"Ptxt"}
Initial Plaintext 2: {"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[8,9],[8,9],[8,9]]},"serializationVersion":"0.0.1","type":"Ptxt"}
ptxt1 * ptxt2 =
{"HElibVersion":"2.2.0","content":{"scheme":"BGV","slots":[[5,1],[5,1],[5,1]]},"serializationVersion":"0.0.1","type":"Ptxt"}

However, the output of each slot should be different, because F_i(x) is different for each i.

Is there any solution to this?

@wahyudierwin wahyudierwin changed the title Unexpected same polynomials on plaintext operation Unexpected same polynomials on plaintext operation when more than 1 number in each slot Jan 2, 2025
@wahyudierwin
Copy link
Author

It got me thinking: is this behavior intended? Even though each slot can hold more than one number if the smaller polynomial has a degree more than 1, BGV in HElib (or other libraries) only support one number for each slot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant