libpir.cpp 6.3 KB

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