20 #ifndef __ITCLIENT_IMPL_H__
21 #define __ITCLIENT_IMPL_H__
28 #include "percyresult.h"
29 #include "rsdecoder.h"
31 template <
typename GF2E_Element>
32 inline void setCoeffs(GF2X &GF2X_P);
35 inline void setCoeffs<GF28_Element>(GF2X &GF2X_P) {
36 SetCoeff(GF2X_P, 8, 1);
37 SetCoeff(GF2X_P, 4, 1);
38 SetCoeff(GF2X_P, 3, 1);
39 SetCoeff(GF2X_P, 1, 1);
40 SetCoeff(GF2X_P, 0, 1);
44 inline void setCoeffs<GF216_Element>(GF2X &GF2X_P) {
45 SetCoeff(GF2X_P, 16, 1);
46 SetCoeff(GF2X_P, 14, 1);
47 SetCoeff(GF2X_P, 12, 1);
48 SetCoeff(GF2X_P, 7, 1);
49 SetCoeff(GF2X_P, 6, 1);
50 SetCoeff(GF2X_P, 4, 1);
51 SetCoeff(GF2X_P, 2, 1);
52 SetCoeff(GF2X_P, 1, 1);
53 SetCoeff(GF2X_P, 0, 1);
57 template <
typename GF2E_Element>
59 nservers_t num_servers, nservers_t t, sid_t * sids,
PercyStats * stats) :
61 params(static_cast<const
GF2EParams*>(params->percy_params())),
65 vecs_interp_indices(),
73 setCoeffs<GF2E_Element>(MODULUS_P);
75 GF2E::init(MODULUS_P);
79 nqueries_t max_qbs = num_servers - 1 - this->params->tau();
80 choose_interp_indices(max_qbs);
83 template <
typename GF2E_Element>
86 if (indices != NULL) {
89 if (interp_indices != NULL) {
90 delete[] interp_indices;
92 while (answers.size() > 0) {
93 if (answers.back() != NULL) {
94 delete[] answers.back();
98 typename map<nqueries_t, GF2E_Element *>::iterator siter;
99 for (siter = stored_shares.begin(); siter != stored_shares.end(); ++siter) {
100 delete[] siter->second;
102 stored_shares.clear();
107 template <
typename GF2E_Element>
108 static void genshares_GF2E(nservers_t t, nservers_t l,
109 const GF2E_Element *indices, GF2E_Element *values, GF2E_Element secret)
112 GF2E_Element * coeffs =
new GF2E_Element[t+1];
114 for (nservers_t i=1;i<=t;++i) {
115 coeffs[i] = RandomBits_ulong(8*
sizeof(GF2E_Element));
119 for (nservers_t i=0; i<l; ++i) {
120 values[i] = evalpoly_GF2E<GF2E_Element>(coeffs, t, indices[i]);
125 #ifdef VERBOSE_ITCLIENT
126 template <
typename GF2E_Element>
127 static void showpoly(
const char *label,
const GF2E_Element *poly,
128 nqueries_t numcoeffs)
131 fprintf(stderr,
"%s", label);
133 fprintf(stderr,
"[ ");
134 for (nqueries_t i = 0; i < numcoeffs; ++i) {
135 fprintf(stderr,
"%02x ", poly[i]);
137 fprintf(stderr,
"]\n");
142 template <
typename GF2E_Element>
143 static void gensharesmulti_GF2E(nservers_t t, nservers_t l,
144 const GF2E_Element *indices, GF2E_Element *values,
145 const GF2E_Element* secret,
const GF2E_Element *interp_indices,
151 for (nservers_t i=0; i<l; ++i) {
152 values[i] = interpolate_GF2E(interp_indices, secret, qbs,
159 GF2E_Element * randpoly =
new GF2E_Element[t];
160 for (nservers_t i=0; i<t; ++i) {
161 randpoly[i] = RandomBits_ulong(8*
sizeof(GF2E_Element));
164 GF2E_Element * buildroots =
new GF2E_Element[qbs+1];
165 polyfromroots_GF2E(buildroots, interp_indices, qbs);
166 GF2E_Element *
final =
new GF2E_Element[t+qbs];
167 multpoly_GF2E(
final, randpoly, t-1, buildroots, qbs);
170 for (nservers_t i=0; i<l; ++i) {
171 values[i] = evalpoly_GF2E<GF2E_Element>(
final, t+qbs-1, indices[i]) ^
172 interpolate_GF2E(interp_indices, secret, qbs,
180 template <
typename GF2E_Element>
182 indices =
new GF2E_Element[num_servers];
183 for (nservers_t j=0; j<num_servers; ++j) {
186 indices[j] = (GF2E_Element)sids[j];
192 r = RandomLen_long(8*
sizeof(GF2E_Element));
195 for (nservers_t k=0;k<j;++k) {
196 if (indices[k] == r) {
207 indices_ntl.SetLength(num_servers);
208 for (nservers_t ix=0; ix<num_servers; ++ix) {
209 conv(indices_ntl[ix],
210 GF2XFromBytes((
unsigned char *)(indices + ix),
211 sizeof(GF2E_Element)));
216 template <
typename GF2E_Element>
218 vec_interp_indices.SetLength(qbs);
219 interp_indices =
new GF2E_Element[qbs];
220 GF2E_Element candidate = 0x00;
223 bool in_server_indices =
false;
224 for (nservers_t s=0; s<num_servers; s++){
225 if (indices[s] == candidate){
226 in_server_indices =
true;
229 if (!in_server_indices) {
230 interp_indices[i] = candidate;
231 conv(vec_interp_indices[i],
232 GF2XFromBytes((
unsigned char *)(interp_indices + i),
233 sizeof(GF2E_Element)));
242 template <
typename GF2E_Element>
244 nqueries_t request_identifier)
246 const vector<dbsize_t>& block_numbers = get_block_numbers(request_identifier);
247 nqueries_t qbs = get_qbs(request_identifier);
248 nqueries_t num_block_requests = block_numbers.size();
249 nqueries_t num_queries = (num_block_requests+qbs-1)/qbs;
252 randmults[request_identifier] = vector<GF2E_Element>();
253 vector<GF2E_Element>& request_randmults = randmults[request_identifier];
254 for (nqueries_t i = 0; i < num_queries * num_servers; ++i) {
257 r = RandomLen_long(8*
sizeof(GF2E_Element));
259 request_randmults.push_back(r);
264 dbsize_t num_virtual_blocks = params->num_virtual_blocks();
265 dbsize_t virtual_block_size = params->virtual_block_size();
266 GF2E_Element * shares =
new GF2E_Element[num_queries * num_virtual_blocks * num_servers];
267 nqueries_t current_query = 0;
268 GF2E_Element* secrets =
new GF2E_Element[qbs];
269 for (nqueries_t q=0; q<num_block_requests; q += qbs) {
270 nqueries_t tmpblock = (num_block_requests - q) > qbs ?
271 qbs : (num_block_requests - q);
272 vec_GF2E interps = vec_interp_indices;
273 interps.SetLength(tmpblock);
274 vecs_interp_indices.push_back(interps);
275 for (dbsize_t i = 0; i < num_virtual_blocks; ++i) {
277 dbsize_t virtual_block_number = block_numbers[q] / virtual_block_size;
278 genshares_GF2E<GF2E_Element>(t, num_servers, indices,
279 shares + (current_query * num_virtual_blocks + i) * num_servers,
280 i == virtual_block_number);
283 for (nqueries_t k = 0; k < tmpblock; k++) {
284 dbsize_t virtual_block_number = block_numbers[q+k] / virtual_block_size;
285 if (virtual_block_number == i) {
286 secrets[k] = (GF2E_Element)(1);
288 secrets[k] = (GF2E_Element)(0);
291 gensharesmulti_GF2E<GF2E_Element>(t, num_servers, indices,
292 shares + (current_query * num_virtual_blocks + i) * num_servers,
293 secrets, interp_indices, tmpblock);
302 vector<GF2E_Element>& request_randmults = randmults[request_identifier];
303 for (nservers_t p = 0; p < num_servers; ++p) {
304 for (nqueries_t i = 0; i < num_queries; ++i) {
305 for (dbsize_t j = 0; j < num_virtual_blocks; ++j) {
306 dbsize_t index = (i * num_virtual_blocks + j) * num_servers
309 multiply_GF2E<GF2E_Element>(shares[index],
310 request_randmults[p*num_queries + i]);
317 stored_shares[request_identifier] = shares;
320 template <
typename GF2E_Element>
322 nqueries_t request_identifier, vector<ostream*> &osvec,
323 bool send_num_queries)
326 GF2E_Element * shares = stored_shares[request_identifier];
327 nqueries_t qbs = get_qbs(request_identifier);
328 nqueries_t num_block_requests = get_block_numbers(request_identifier).size();
329 nqueries_t num_queries = (num_block_requests+qbs-1)/qbs;
330 dbsize_t num_virtual_blocks = params->num_virtual_blocks();
333 if (num_servers != osvec.size()) {
334 std::cerr <<
"Incorrect iostream vector size passed to "
335 "send_request_GF2E.\n";
336 std::cerr <<
"Was " << osvec.size() <<
", should be " << num_servers
342 for (nservers_t j = 0; j < num_servers; ++j) {
343 if (send_num_queries) {
344 percy_write_le_uint16(*osvec[j], num_queries);
346 for (nqueries_t q=0; q<num_queries; ++q) {
347 for (dbsize_t i = 0; i < num_virtual_blocks; ++i) {
348 dbsize_t index = (q * num_virtual_blocks + i) * num_servers + j;
349 char *shareptr = (
char *)&(shares[index]);
350 osvec[j]->write(shareptr,
sizeof(GF2E_Element));
358 stored_shares.erase(request_identifier);
360 return num_servers * ((send_num_queries ? 2 : 0) + num_queries *
361 num_virtual_blocks *
sizeof(GF2E_Element));
366 template <
typename GF2E_Element>
368 nqueries_t request_identifier, vector<istream*> &isvec)
370 dbsize_t words_per_block = params->words_per_block();
371 nqueries_t qbs = get_qbs(request_identifier);
372 nqueries_t num_block_requests = get_block_numbers(request_identifier).size();
373 nqueries_t num_queries = (num_block_requests+qbs-1)/qbs;
380 nqueries_t prev = answers.size();
381 for (nqueries_t q = 0; q < num_queries; ++q) {
382 answers.push_back(
new GF2E_Element[words_per_block * num_servers]);
386 for (nservers_t j = 0; j < num_servers; ++j) {
388 for (nqueries_t q = prev; q < prev + num_queries; ++q) {
389 for (dbsize_t i = 0; isgood && i < words_per_block; ++i) {
390 isvec[j]->read((
char *)(answers[q] + i * num_servers + j),
391 sizeof(GF2E_Element));
392 if (isvec[j]->eof()) {
393 std::cerr <<
"Server " << j+1 <<
" did not send complete reply.\n";
394 std::cerr <<
"Marking server " << j+1 <<
" as bad.\n";
398 if ((dbsize_t)(isvec[j]->gcount()) < 1) {
400 std::cerr <<
"Marking server " << j+1 <<
" as bad.\n";
407 goodservers.push_back(j);
413 vector<GF2E_Element>& request_randmults = randmults[request_identifier];
414 for (nservers_t j = 0; j < num_servers; ++j) {
415 for (nqueries_t q = 0; q < num_queries; ++q) {
416 GF2E_Element randmult_inv =
417 inverse_GF2E<GF2E_Element>(request_randmults[j*num_queries + q]);
418 for (dbsize_t i = 0; i < words_per_block; ++i) {
419 answers[q+prev][i*num_servers + j] = multiply_GF2E<GF2E_Element>(
420 answers[q+prev][i*num_servers + j], randmult_inv);
424 randmults.erase(request_identifier);
428 for (q=0; q<num_queries; ++q) {
429 unfinished_results.push_back(
431 decoded.push_back(std::set<dbsize_t>());
434 return num_servers * num_queries * words_per_block *
sizeof(GF2E_Element);
440 template <
typename GF2E_Element>
442 GF2E_Element alpha, nservers_t firstpoint, nservers_t numpoints)
444 for (nservers_t i=0; i < numpoints; ++i) {
445 GF2E_Element numer = 1, denom = 1;
446 for (nservers_t j=0; j < numpoints; ++j) {
448 GF2E_Element numerdiff = indices[goodservers[firstpoint+j]] ^
450 GF2E_Element denomdiff = indices[goodservers[firstpoint+j]] ^
451 indices[goodservers[firstpoint+i]];
452 numer = multiply_GF2E<GF2E_Element>(numer, numerdiff);
453 denom = multiply_GF2E<GF2E_Element>(denom, denomdiff);
455 coeffs[i] = multiply_GF2E<GF2E_Element>(numer,
456 inverse_GF2E<GF2E_Element>(denom));
463 template <
typename GF2E_Element>
465 const GF2E_Element *word_answers,
const GF2E_Element *coeffs,
466 nservers_t firstpoint, nservers_t numpoints)
468 GF2E_Element res = 0;
470 for (nservers_t i = 0; i < numpoints; ++i) {
471 res ^= multiply_GF2E<GF2E_Element>(coeffs[i],
472 word_answers[goodservers[firstpoint+i]]);
478 template <
typename GF2E_Element>
480 vector<vector<PercyResult> > &results)
482 dbsize_t words_per_block = params->words_per_block();
483 nqueries_t num_queries = vecs_interp_indices.size();
484 nservers_t k = goodservers.size();
486 if (k <= t)
return false;
489 for (nqueries_t q = 0; q < num_queries; ++q) {
492 nqueries_t bpq = vecs_interp_indices[q].length();
496 const bool justzero = (bpq == 0);
500 GF2E_Element *resblock =
new GF2E_Element[words_per_block * bpq];
508 GF2E_Element *result_coeffs =
new GF2E_Element[bpq*(t+bpq)];
509 for (nservers_t a = 0; a < bpq; ++a) {
510 construct_lagrange_coeffs(result_coeffs + a*(t+bpq),
511 justzero ? 0 : interp_indices[a],
517 GF2E_Element *check_coeffs =
new GF2E_Element[(k-t-bpq)*(t+bpq)];
518 for (nservers_t a = 0; a < k-t-bpq; ++a) {
519 construct_lagrange_coeffs(check_coeffs + a*(t+bpq),
520 indices[goodservers[a]],
524 for (dbsize_t word = 0; word < words_per_block; ++word) {
527 for (nservers_t a = 0; a < k-t-bpq; ++a) {
528 GF2E_Element expectedans =
529 answers[q][word*num_servers + goodservers[a]];
530 GF2E_Element actualans = interpolate(
531 answers[q] + word*num_servers,
532 check_coeffs + a*(t+bpq), k-t-bpq, t+bpq);
534 if (expectedans != actualans) {
540 delete[] check_coeffs;
541 delete[] result_coeffs;
546 for (nservers_t a = 0; a < bpq; ++a) {
547 resblock[a*words_per_block+word] = interpolate(
548 answers[q] + word*num_servers,
549 result_coeffs + a*(t+bpq), k-t-bpq, t+bpq);
552 for (nservers_t a = 0; a < bpq; ++a) {
554 string((
char *)(resblock + a*words_per_block),
555 words_per_block*
sizeof(GF2E_Element)));
556 results.push_back(vector<PercyResult>(1, thisresult));
559 delete[] result_coeffs;
560 delete[] check_coeffs;
569 template <
typename GF2E_Element>
571 vector<vector<PercyResult> >& results)
573 dbsize_t words_per_block = params->words_per_block();
574 nservers_t tau = params->tau();
577 if (!(results.empty())) {
578 std::cerr <<
"The results vector must be empty\n";
582 if (try_fast_recover(h, results)) {
584 while (answers.size() > 0) {
585 if (answers.back() != NULL) {
586 delete[] answers.back();
591 unfinished_results.clear();
593 vecs_interp_indices.clear();
598 for (nqueries_t q = answers_ntl.size(); q < answers.size(); ++q) {
599 answers_ntl.push_back(vector<vec_GF2E>(words_per_block));
600 for (dbsize_t c = 0; c < words_per_block; ++c) {
601 answers_ntl[q][c].SetLength(num_servers);
602 for (nservers_t j = 0; j < num_servers; ++j) {
603 conv(answers_ntl[q][c][j],
604 GF2XFromBytes((
unsigned char *)(answers[q] +
605 c * num_servers + j),
sizeof(GF2E_Element)));
613 bool res = decoder.
Recover(
sizeof(GF2E_Element), t+tau, h, goodservers,
614 answers_ntl, indices_ntl, unfinished_results, decoded,
615 vecs_interp_indices);
619 GF2E_Element *sigma =
new GF2E_Element[words_per_block];
620 for (nqueries_t q = 0; q < answers.size(); ++q) {
621 for (dbsize_t i = 0; i < unfinished_results[q].size(); ++i) {
622 ssize_t indices_len = vecs_interp_indices[q].length();
623 const int num_subqueries = indices_len > 0 ? indices_len : 1;
624 for (
int sub_query = 0; sub_query < num_subqueries; sub_query++) {
625 results.push_back(vector<PercyResult>());
626 vector<PercyResult> &block_results = results.back();
627 if (decoded[q].size() == words_per_block) {
628 for (dbsize_t j = 0; j < words_per_block; ++j) {
629 BytesFromGF2X((
unsigned char *)(sigma + j),
630 rep(unfinished_results[q][i].recovered[sub_query][j]),
631 sizeof(GF2E_Element));
633 block_results.push_back(
PercyResult(unfinished_results[q][i].G,
634 string((
char *)sigma, words_per_block *
sizeof(GF2E_Element))));
639 if (decoded[q].size() == words_per_block) {
641 if (answers[q] != NULL) {
644 answers.erase(answers.begin() + q);
645 answers_ntl.erase(answers_ntl.begin() + q);
646 unfinished_results.erase(unfinished_results.begin() + q);
647 decoded.erase(decoded.begin() + q);
648 vecs_interp_indices.erase(vecs_interp_indices.begin() + q);
655 return answers.size();
Client parameters.
Definition: percyparams.h:189
Definition: percyresult.h:30
Definition: percystats.h:66
Reed-Solomon Decoder.
Definition: rsdecoder.h:161
Contains the results (so far) of decoding words.
Definition: rsdecoder.h:87
A PIR client for the IT-PIR protocol by Goldberg (2007) over GF(2^E).
Definition: itclient.h:147
bool Recover(dbsize_t bytes_per_word, nservers_t t, nservers_t h, const vector< nservers_t > &goodservers, const vector< vector< vec_F > > &values, const vec_F &server_indices, vector< vector< DecoderResult< F > > > &results, vector< std::set< dbsize_t > > &decoded, const vector< vec_F > &vec_interp_indices, const nqueries_t multi_only=0)
The main method to do the Reed-Solomon Decoding.
Definition: rsdecoder_impl.h:2823
virtual ~PercyClient_GF2E()
Destructor.
Definition: itclient_impl.h:84
An abstract base class for a PIR client.
Definition: percyclient.h:35
PercyClient_GF2E(const PercyClientParams *params, nservers_t num_servers, nservers_t t, sid_t *sids, PercyStats *stats=NULL)
Constructor.
Definition: itclient_impl.h:58
Definition: itparams.h:144