-
Notifications
You must be signed in to change notification settings - Fork 763
Open
Description
I am trying to perform digit extraction homomorphically, and fortunately, HElib provides a function called extractDigits. However, I am getting incorrect results. Below is the code I'm using:
#include <cstdlib>
#include <ctime>
#include <helib/helib.h>
#include <helib/debugging.h>
#include <random>
#include <map>
#include <NTL/ZZ_pE.h>
#include <NTL/mat_ZZ_pE.h>
#include <helib/Ptxt.h>
void print_decrypted(const helib::Ctxt& ctxt, const helib::Context& context, const helib::SecKey& sk)
{
const helib::EncryptedArray& ea = context.getEA();
unsigned long ord_p = context.getOrdP();
long nSlots = ea.size();
std::vector<NTL::ZZX> decrypted(nSlots);
ea.decrypt(ctxt, sk, decrypted);
for(int i = 0; i < nSlots; i++)
{
helib::printZZX(std::cout, decrypted[i], ord_p);
}
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
// Plaintext prime modulus
unsigned long p = 7;
// Cyclotomic polynomial - defines phi(m)
unsigned long m = 678;
// Hensel lifting (default = 1)
unsigned long r = 3;
// Number of bits of the modulus chain
unsigned long bits = 1000;
// 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();
std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-" << 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;
//generate random data
std::random_device rd;
std::mt19937 eng(rd());
std::uniform_int_distribution<unsigned long> distr_u;
std::uniform_int_distribution<long> distr_i;
// get EncryptedArray
const helib::EncryptedArray& ea = context.getEA();
// get number of slots
long nslots = ea.size();
unsigned long input_range = context.getPPowR();
long input_x;
std::vector<long> x_vec(nslots);
// Generate input
for (int i = 0; i < nslots; i++){
input_x = distr_u(eng) % input_range;
x_vec[i] = input_x;
if (i == 0) x_vec[i] = input_range - 1;
if (i == 1) x_vec[i] = input_range/2;
if (i == 2) x_vec[i] = input_range/2 + 1;
}
// encrypt
helib::Ctxt ctxt_x(public_key);
ea.encrypt(ctxt_x, public_key, x_vec);
std::cout << "Input plaintext:\n";
for (int i = 0; i < nslots; i++){
std::cout << x_vec[i] << "\t";
}
std::cout << std::endl;
// test extract digits
std::vector<helib::Ctxt> ctxt_x_p;
helib::extractDigits(ctxt_x_p, ctxt_x, r);
// print extracted digits
for (int i=0 ; i<ctxt_x_p.size() ; i++){
print_decrypted(ctxt_x_p[i], context, secret_key);
}
return 0;
}
From the code, p is 7 and r is 3, which means the maximum input for each slot should be p^r = 7^3 = 343. However, after running the code, I get the following output:
Input plaintext:
342 171 172 11 26 64 119 70 34 226 247 154 289 96 210 241
[342][3][340][340][341][1][][][342][2][2][][2][341][][3]
[][3][46][2][46][2][3][3][47][46][][1][48][][2][48]
[][3][4][][1][1][2][1][1][5][5][3][6][2][4][5]
I expected that 342 when represented in base 7 would be 666, but the results are different from the expectation.
Questions:
- Could there be an issue with how
extractDigitsis applied? - Is there a bug or limitation in HElib's implementation of
extractDigits?
Any comments or suggestions are highly appreciated. Thank you!
Added
I also tried another parameters, p = 3, r = 4, m = 679 it gives incorrect results:
Input plaintext:
80 40 41 69 6 3 24 61 7 21 10 22
[80][1][80][][][][][1][1][][1][1]
[][1][26][26][26][1][26][26][26][1][][1]
[][1][8][8][1][][][1][1][8][1][8]
[][1][2][][][][1][2][][1][][1]
However, if p = 2, it produces correct results.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels