libpir.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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::setPirParams(param);
  62. }
  63. void PIRReplyGenerator::pushQuery(char* rawQuery) {
  64. PIRReplyGeneratorNFL_internal::pushQuery(rawQuery);
  65. }
  66. imported_database* PIRReplyGenerator::importData(uint64_t offset, uint64_t bytes_per_db_element) {
  67. uint64_t usable_memory = getTotalSystemMemory();
  68. if(bytes_per_db_element*dbhandler->getNbStream()*4>usable_memory/10) {
  69. 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;
  70. }
  71. importDataNFL(offset,bytes_per_db_element);
  72. imported_database* precomputed = new imported_database();
  73. precomputed->imported_database_ptr=input_data;
  74. precomputed->nbElements = ceil((float)dbhandler->getNbStream()/pirParam.alpha);
  75. precomputed->polysPerElement = currentMaxNbPolys;
  76. precomputed->beforeImportElementBytesize=bytes_per_db_element;
  77. return precomputed;
  78. }
  79. void PIRReplyGenerator::generateReply(const imported_database* database)
  80. {
  81. // Init
  82. nbRepliesToHandle=0;
  83. nbRepliesGenerated=0;
  84. currentReply=0;
  85. freeResult();
  86. // Test memory
  87. uint64_t usable_memory = getTotalSystemMemory();
  88. nbRepliesGenerated=nbRepliesToHandle=computeReplySizeInChunks(database->beforeImportElementBytesize);
  89. uint64_t polysize = cryptoMethod->getpolyDegree() * cryptoMethod->getnbModuli()*sizeof(uint64_t);
  90. uint64_t sizeOfReply=nbRepliesToHandle*polysize;
  91. if(sizeOfReply>usable_memory/10) {
  92. std::cerr<<"WARNING: going to use more than one tenth of the available memory for storing the reply"<<std::flush<<std::endl;
  93. }
  94. input_data = (lwe_in_data*) database->imported_database_ptr;
  95. currentMaxNbPolys = database->polysPerElement;
  96. // The internal generator is locked by default waiting for the query to be received
  97. // in this API we let the user deal with synchronisation so the lock is not needed
  98. PIRReplyGeneratorNFL_internal::mutex.try_lock();
  99. PIRReplyGeneratorNFL_internal::mutex.unlock();
  100. // Define the reply size
  101. repliesAmount = computeReplySizeInChunks(database->beforeImportElementBytesize);
  102. PIRReplyGeneratorNFL_internal::generateReply();
  103. }
  104. void PIRReplyGenerator::freeQueries(){
  105. PIRReplyGeneratorNFL_internal::freeQueries();
  106. }
  107. /** popReply that return false when the queue is over (true otherwise) and waits when its empty
  108. **/
  109. bool PIRReplyGenerator::popReply(char** reply) {
  110. // For each ciphertext in the reply
  111. if(nbRepliesToHandle--<=0) return false;
  112. while (repliesArray == NULL || repliesArray[currentReply] == NULL) {
  113. boost::this_thread::sleep(boost::posix_time::milliseconds(10));
  114. }
  115. *reply = repliesArray[currentReply];
  116. repliesArray[currentReply++]=NULL;
  117. return true;
  118. }
  119. uint64_t PIRReplyGenerator::getnbRepliesGenerated() {
  120. return nbRepliesGenerated;
  121. }
  122. uint64_t PIRReplyGenerator::getReplyElementBytesize()
  123. {
  124. return cryptoMethod->getPublicParameters().getCiphertextBitsize()/8;
  125. }
  126. /**
  127. * PIRReplyExtraction is Client side, it extracts the chosen element from the reply of the Server
  128. **/
  129. PIRReplyExtraction::PIRReplyExtraction(PIRParameters& pirParameters, HomomorphicCrypto& cryptoMethod_):
  130. PIRReplyExtraction_internal(pirParameters,cryptoMethod_), clearChunks("clearChunks"){
  131. nbPlaintextReplies=0;
  132. }
  133. void PIRReplyExtraction::pushEncryptedReply(char* rawBytes) {
  134. repliesBuffer.push(rawBytes);
  135. }
  136. void PIRReplyExtraction::extractReply(uint64_t maxFileBytesize){
  137. PIRReplyExtraction_internal::extractReply(pirParams.alpha*maxFileBytesize,&clearChunks);
  138. nbPlaintextReplies = getnbPlaintextReplies(maxFileBytesize);
  139. }
  140. bool PIRReplyExtraction::popPlaintextResult(char** result) {
  141. if(nbPlaintextReplies!=0) {
  142. *result=clearChunks.pop_front();
  143. nbPlaintextReplies--;
  144. return true;
  145. } else {
  146. return false;
  147. }
  148. }
  149. uint64_t PIRReplyExtraction::getPlaintextReplyBytesize(){
  150. return cryptoMethod.getPublicParameters().getAbsorptionBitsize(0)/GlobalConstant::kBitsPerByte;
  151. }
  152. uint64_t PIRReplyExtraction::getnbPlaintextReplies(uint64_t maxFileBytesize) {
  153. return ceil((float)maxFileBytesize*pirParams.alpha/getPlaintextReplyBytesize());
  154. }