|
@@ -1,4 +1,5 @@
|
|
|
#include "pir_server.hpp"
|
|
|
+#include "pir_client.hpp"
|
|
|
|
|
|
using namespace std;
|
|
|
using namespace seal;
|
|
@@ -111,6 +112,7 @@ void PIRServer::set_database(const std::unique_ptr<const std::uint8_t[]> &bytes,
|
|
|
|
|
|
Plaintext plain;
|
|
|
vector_to_plaintext(coefficients, plain);
|
|
|
+ cout << i << "-th encoded plaintext = " << plain.to_string() << endl;
|
|
|
result->push_back(move(plain));
|
|
|
}
|
|
|
|
|
@@ -141,7 +143,7 @@ void PIRServer::set_galois_key(std::uint32_t client_id, seal::GaloisKeys galkey)
|
|
|
galoisKeys_[client_id] = galkey;
|
|
|
}
|
|
|
|
|
|
-PirReply PIRServer::generate_reply(PirQuery query, uint32_t client_id) {
|
|
|
+PirReply PIRServer::generate_reply(PirQuery query, uint32_t client_id, PIRClient &client) {
|
|
|
|
|
|
vector<uint64_t> nvec = pir_params_.nvec;
|
|
|
uint64_t product = 1;
|
|
@@ -159,7 +161,15 @@ PirReply PIRServer::generate_reply(PirQuery query, uint32_t client_id) {
|
|
|
|
|
|
for (uint32_t i = 0; i < nvec.size(); i++) {
|
|
|
uint64_t n_i = nvec[i];
|
|
|
- vector<Ciphertext> expanded_query = expand_query(query[i], n_i, client_id);
|
|
|
+ vector<Ciphertext> expanded_query = expand_query(query[i], n_i, client_id, client);
|
|
|
+ cout << "Checking expanded query ";
|
|
|
+ Plaintext tempPt;
|
|
|
+ for (int h = 0 ; h < expanded_query.size(); h++){
|
|
|
+ cout << "noise budget = " << client.decryptor_->invariant_noise_budget(expanded_query[h]) << ", ";
|
|
|
+ client.decryptor_->decrypt(expanded_query[h], tempPt);
|
|
|
+ cout << tempPt.to_string() << endl;
|
|
|
+ }
|
|
|
+ cout << endl;
|
|
|
|
|
|
// Transform expanded query to NTT, and ...
|
|
|
for (uint32_t jj = 0; jj < expanded_query.size(); jj++) {
|
|
@@ -224,7 +234,7 @@ PirReply PIRServer::generate_reply(PirQuery query, uint32_t client_id) {
|
|
|
}
|
|
|
|
|
|
inline vector<Ciphertext> PIRServer::expand_query(const Ciphertext &encrypted, uint32_t m,
|
|
|
- uint32_t client_id) {
|
|
|
+ uint32_t client_id, PIRClient &client) {
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
uint64_t plainMod = params_.plain_modulus().value();
|
|
@@ -239,10 +249,16 @@ inline vector<Ciphertext> PIRServer::expand_query(const Ciphertext &encrypted, u
|
|
|
|
|
|
vector<int> galois_elts;
|
|
|
auto n = params_.poly_modulus_degree();
|
|
|
+ if (logm > ceil(log2(n))){
|
|
|
+ throw logic_error("m > n is not allowed.");
|
|
|
+ }
|
|
|
|
|
|
+ cout << "galois elts at server: ";
|
|
|
for (uint32_t i = 0; i < logm; i++) {
|
|
|
galois_elts.push_back((n + exponentiate_uint64(2, i)) / exponentiate_uint64(2, i));
|
|
|
+ cout << galois_elts.back() << ", ";
|
|
|
}
|
|
|
+ cout << endl;
|
|
|
|
|
|
vector<Ciphertext> temp;
|
|
|
temp.push_back(encrypted);
|
|
@@ -257,17 +273,36 @@ inline vector<Ciphertext> PIRServer::expand_query(const Ciphertext &encrypted, u
|
|
|
// some scaling....
|
|
|
int index_raw = (n << 1) - (1 << i);
|
|
|
int index = (index_raw * galois_elts[i]) % (n << 1);
|
|
|
+ cout << i << "-th expansion round, noise budget = " << endl;
|
|
|
|
|
|
for (uint32_t a = 0; a < temp.size(); a++) {
|
|
|
|
|
|
evaluator_->apply_galois(temp[a], galois_elts[i], galkey, tempctxt_rotated);
|
|
|
+
|
|
|
+ cout << "rotate " << client.decryptor_->invariant_noise_budget(tempctxt_rotated) << ", ";
|
|
|
+
|
|
|
+
|
|
|
evaluator_->add(temp[a], tempctxt_rotated, newtemp[a]);
|
|
|
multiply_power_of_X(temp[a], tempctxt_shifted, index_raw);
|
|
|
+
|
|
|
+ cout << "mul by x^pow: " << client.decryptor_->invariant_noise_budget(tempctxt_shifted) << ", ";
|
|
|
+
|
|
|
+
|
|
|
multiply_power_of_X(tempctxt_rotated, tempctxt_rotatedshifted, index);
|
|
|
+
|
|
|
+ cout << "mul by x^pow: " << client.decryptor_->invariant_noise_budget(tempctxt_rotatedshifted) << ", ";
|
|
|
+
|
|
|
+
|
|
|
// Enc(2^i x^j) if j = 0 (mod 2**i).
|
|
|
evaluator_->add(tempctxt_shifted, tempctxt_rotatedshifted, newtemp[a + temp.size()]);
|
|
|
}
|
|
|
temp = newtemp;
|
|
|
+
|
|
|
+ cout << "end: ";
|
|
|
+ for (int h = 0; h < temp.size();h++){
|
|
|
+ cout << client.decryptor_->invariant_noise_budget(temp[h]) << ", ";
|
|
|
+ }
|
|
|
+ cout << endl;
|
|
|
}
|
|
|
|
|
|
// Last step of the loop
|
|
@@ -277,6 +312,7 @@ inline vector<Ciphertext> PIRServer::expand_query(const Ciphertext &encrypted, u
|
|
|
for (uint32_t a = 0; a < temp.size(); a++) {
|
|
|
if (a >= (m - (1 << (logm - 1)))) { // corner case.
|
|
|
evaluator_->multiply_plain(temp[a], two, newtemp[a]); // plain multiplication by 2.
|
|
|
+ cout << client.decryptor_->invariant_noise_budget(newtemp[a]) << ", ";
|
|
|
} else {
|
|
|
evaluator_->apply_galois(temp[a], galois_elts[logm - 1], galkey, tempctxt_rotated);
|
|
|
evaluator_->add(temp[a], tempctxt_rotated, newtemp[a]);
|
|
@@ -299,6 +335,9 @@ inline void PIRServer::multiply_power_of_X(const Ciphertext &encrypted, Cipherte
|
|
|
auto coeff_count = params_.poly_modulus_degree();
|
|
|
auto encrypted_count = encrypted.size();
|
|
|
|
|
|
+ //cout << "coeff mod count for power of X = " << coeff_mod_count << endl;
|
|
|
+ //cout << "coeff count for power of X = " << coeff_count << endl;
|
|
|
+
|
|
|
// First copy over.
|
|
|
destination = encrypted;
|
|
|
|
|
@@ -307,7 +346,7 @@ inline void PIRServer::multiply_power_of_X(const Ciphertext &encrypted, Cipherte
|
|
|
for (int i = 0; i < encrypted_count; i++) {
|
|
|
for (int j = 0; j < coeff_mod_count; j++) {
|
|
|
negacyclic_shift_poly_coeffmod(encrypted.data(i) + (j * coeff_count),
|
|
|
- coeff_count - 1, index,
|
|
|
+ coeff_count, index,
|
|
|
params_.coeff_modulus()[j],
|
|
|
destination.data(i) + (j * coeff_count));
|
|
|
}
|