libpir.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include "libpir.hpp"
  2. imported_database::~imported_database(){
  3. for (unsigned int i = 0 ; i < nbElements ; i++){
  4. free(((lwe_in_data *)imported_database_ptr)[i].p[0]);
  5. free(((lwe_in_data *)imported_database_ptr)[i].p);
  6. }
  7. }
  8. /**
  9. * HomomorphicCryptoFactory is used to create a generic cryptographic object (LWE, Paillier,
  10. * mocked-cryptography, etc.). This API only exposes the Ring-LWE cryptosystem, but we still
  11. * use the generic factory to get an instance of this cryptosystem to avoid code duplication.
  12. **/
  13. HomomorphicCrypto* HomomorphicCryptoFactory::getCryptoMethod(std::string cryptoType)
  14. {
  15. return HomomorphicCryptoFactory_internal::getCryptoMethod(cryptoType);
  16. }
  17. void HomomorphicCryptoFactory::printAllCryptoParams() {
  18. std::cout << "Available crypto parameters : (CryptoSystem::SecurityMax::PolyDegree::ModulusBitsize)" << std::endl;
  19. NFLLWE nfl;
  20. std::set<std::string> crypto_params_set;
  21. unsigned int i=nfl.getAllCryptoParams(crypto_params_set);
  22. for(auto const& crypto: crypto_params_set) {
  23. std::cout << crypto << std::endl;
  24. }
  25. std::cout<<std::endl;
  26. }
  27. /**
  28. * PIRQueryGenerator is Client side, it initiates the PIR protocol by generating a query
  29. * corresponding to the chosen element
  30. **/
  31. PIRQueryGenerator::PIRQueryGenerator(PIRParameters& pirParameters, HomomorphicCrypto& cryptoMethod_) :
  32. PIRQueryGenerator_internal(pirParameters,cryptoMethod_){
  33. }
  34. void PIRQueryGenerator::generateQuery(uint64_t _chosenElement ) {
  35. nbQueries=0;
  36. for(int i=0;i<pirParams.d;i++) nbQueries+=pirParams.n[i];
  37. PIRQueryGenerator_internal::setChosenElement(_chosenElement );
  38. PIRQueryGenerator_internal::generateQuery();
  39. }
  40. bool PIRQueryGenerator::popQuery(char** query) {
  41. if(nbQueries!=0) {
  42. *query=queryBuffer.pop_front();
  43. nbQueries--;
  44. return true;
  45. } else {
  46. return false;
  47. }
  48. }
  49. uint64_t PIRQueryGenerator::getQueryElementBytesize()
  50. {
  51. return cryptoMethod.getPublicParameters().getCiphertextBitsize()/8;
  52. }
  53. /**
  54. * PIRReplyGenerator is Server side, it handles the request generated by the client and generates the reply
  55. **/
  56. PIRReplyGenerator::PIRReplyGenerator(PIRParameters& param, HomomorphicCrypto& cryptoMethod_, DBHandler *db)
  57. : PIRReplyGeneratorNFL_internal (param,db)
  58. {
  59. PIRReplyGeneratorNFL_internal::setCryptoMethod(&cryptoMethod_);
  60. PIRReplyGeneratorNFL_internal::initQueriesBuffer();
  61. PIRReplyGeneratorNFL_internal::setPirParams(param);
  62. nbRepliesToHandle=0;
  63. nbRepliesGenerated=0;
  64. currentReply=0;
  65. }
  66. void PIRReplyGenerator::pushQuery(char* rawQuery) {
  67. PIRReplyGeneratorNFL_internal::pushQuery(rawQuery);
  68. }
  69. imported_database* PIRReplyGenerator::importData(uint64_t offset, uint64_t bytes_per_db_element) {
  70. uint64_t usable_memory = getTotalSystemMemory();
  71. if(bytes_per_db_element*dbhandler->getNbStream()*4>usable_memory/10) {
  72. std::cerr<<"WARNING: going to use more than one tenth of the available memory for storing the precomputed data, maybe you should reduce bytes_per_db_element when calling importData"<<std::flush<<std::endl;
  73. }
  74. importDataNFL(offset,bytes_per_db_element);
  75. imported_database* precomputed = new imported_database();
  76. precomputed->imported_database_ptr=input_data;
  77. precomputed->nbElements = ceil((float)dbhandler->getNbStream()/pirParam.alpha);
  78. precomputed->polysPerElement = currentMaxNbPolys;
  79. precomputed->beforeImportElementBytesize=bytes_per_db_element;
  80. return precomputed;
  81. }
  82. void PIRReplyGenerator::generateReply(const imported_database* database)
  83. {
  84. uint64_t usable_memory = getTotalSystemMemory();
  85. nbRepliesGenerated=nbRepliesToHandle=computeReplySizeInChunks(database->beforeImportElementBytesize);
  86. uint64_t polysize = cryptoMethod->getpolyDegree() * cryptoMethod->getnbModuli()*sizeof(uint64_t);
  87. uint64_t sizeOfReply=nbRepliesToHandle*polysize;
  88. if(sizeOfReply>usable_memory/10) {
  89. std::cerr<<"WARNING: going to use more than one tenth of the available memory for storing the reply"<<std::flush<<std::endl;
  90. }
  91. input_data = (lwe_in_data*) database->imported_database_ptr;
  92. currentMaxNbPolys = database->polysPerElement;
  93. // The internal generator is locked by default waiting for the query to be received
  94. // in this API we let the user deal with synchronisation so the lock is not needed
  95. PIRReplyGeneratorNFL_internal::mutex.unlock();
  96. PIRReplyGeneratorNFL_internal::generateReply();
  97. }
  98. void PIRReplyGenerator::freeQueries(){
  99. freeQuery();
  100. }
  101. /** popReply that return false when the queue is over (true otherwise) and waits when its empty
  102. **/
  103. bool PIRReplyGenerator::popReply(char** reply) {
  104. // For each ciphertext in the reply
  105. if(nbRepliesToHandle--<=0) return false;
  106. while (repliesArray == NULL || repliesArray[currentReply] == NULL) {
  107. boost::this_thread::sleep(boost::posix_time::milliseconds(10));
  108. }
  109. *reply = repliesArray[currentReply];
  110. repliesArray[currentReply++]=NULL;
  111. return true;
  112. }
  113. uint64_t PIRReplyGenerator::getnbRepliesGenerated() {
  114. return nbRepliesGenerated;
  115. }
  116. uint64_t PIRReplyGenerator::getReplyElementBytesize()
  117. {
  118. return cryptoMethod->getPublicParameters().getCiphertextBitsize()/8;
  119. }
  120. /**
  121. * PIRReplyExtraction is Client side, it extracts the chosen element from the reply of the Server
  122. **/
  123. PIRReplyExtraction::PIRReplyExtraction(PIRParameters& pirParameters, HomomorphicCrypto& cryptoMethod_):
  124. PIRReplyExtraction_internal(pirParameters,cryptoMethod_), clearChunks("clearChunks"){
  125. nbPlaintextReplies=0;
  126. }
  127. void PIRReplyExtraction::pushEncryptedReply(char* rawBytes) {
  128. repliesBuffer.push(rawBytes);
  129. }
  130. void PIRReplyExtraction::extractReply(uint64_t maxFileBytesize){
  131. PIRReplyExtraction_internal::extractReply(pirParams.alpha*maxFileBytesize,&clearChunks);
  132. nbPlaintextReplies = getnbPlaintextReplies(maxFileBytesize);
  133. }
  134. bool PIRReplyExtraction::popPlaintextResult(char** result) {
  135. if(nbPlaintextReplies!=0) {
  136. *result=clearChunks.pop_front();
  137. nbPlaintextReplies--;
  138. return true;
  139. } else {
  140. return false;
  141. }
  142. }
  143. uint64_t PIRReplyExtraction::getPlaintextReplyBytesize(){
  144. return cryptoMethod.getPublicParameters().getAbsorptionBitsize(0)/GlobalConstant::kBitsPerByte;
  145. }
  146. uint64_t PIRReplyExtraction::getnbPlaintextReplies(uint64_t maxFileBytesize) {
  147. return ceil((float)maxFileBytesize*pirParams.alpha/getPlaintextReplyBytesize());
  148. }