/* Copyright (C) 2014 Carlos Aguilar Melchor, Joris Barrier, Marc-Olivier Killijian * This file is part of XPIR. * * XPIR is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * XPIR is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XPIR. If not, see . */ #include "OptimService.hpp" const std::string OptimService::folderName = "exp/"; const std::string OptimService::fileName = "preCompute"; const std::string OptimService::absFileExtension = ".abs"; const std::string OptimService::decFileExtension = ".dec"; const std::string OptimService::encFileExtension = ".enc"; const std::string OptimService::getCurrentTime() { time_t now = time(0); struct tm tstruct; char buf[80]; tstruct = *localtime(&now); strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct); return buf; } void OptimService::getAllOptimData(std::vector& fixed_vars_vec, std::string testValuesFileName) { unsigned int experience_nbr = getNumberOfExperiences(testValuesFileName); for(unsigned int i = 0 ; i < experience_nbr ; i++) { FixedVars vars; readTestValues(i, vars, testValuesFileName); fixed_vars_vec.push_back(vars); } } int OptimService::getNumberOfExperiences(std::string testValuesFileName) { std::string line; std::ifstream f(testValuesFileName); int i = 0; if(!f.is_open()) return -1; while (std::getline(f, line)) { if(!(line.c_str()[0] == '#')) i++;//jump over commented line } f.close(); return --i; } int OptimService::readTestValues(unsigned int i, FixedVars& vars, std::string testValuesFileName) { std::ifstream f(testValuesFileName, std::ios::in); std::string line; std::vector fields; if (f.is_open()) { for (unsigned k = 0 ; k < i+1 ; k++) { std::getline(f, line); if(line.c_str()[0] == '#') i++;//jump over commented line } boost::algorithm::split(fields, line, boost::algorithm::is_any_of(" ")); vars.n = atoi(fields[0].c_str()); vars.l = atoi(fields[1].c_str()); vars.Tupc = vars.Tdos = static_cast(atol(fields[2].c_str())); vars.Tdoc = vars.Tups = static_cast(atol(fields[3].c_str())); vars.k = atoi(fields[4].c_str()); vars.alphaMax = atoi(fields[5].c_str()); vars.dMax = atoi(fields[6].c_str()); } else { return 1; } f.close(); return 0; } void OptimService::writeHeadFile(unsigned int i, FixedVars& fixedVars) { std::ofstream file(std::string("exp/exp"+ std::to_string(i)).c_str(), std::ios::out); file << "# " << std::string("exp" + std::to_string(i)) << " " << getCurrentTime() << std::endl; file << "#Fixed Param : n " << fixedVars.n << ", l " << fixedVars.l << ", Tupc " << fixedVars.Tupc << ", Tdoc " << fixedVars.Tdoc <<", k " << fixedVars.k << std::endl; file << "#Bound Param : " << ", alphaMax " << fixedVars.alphaMax << ", dMax " << fixedVars.dMax << std::endl; file << "#1:d 2a:alpha_min\t 2b:alpha_max\t 2c:current_best_alpha\t2d:alpha_lowbound\t2e:alpha_upbound\t3:GenQ \t 4:SendQ \t 5:GenR \t 6:SendR \t 7:DecR \t 8:Total Time (pot. pipelined)" << std::endl; file.close(); } int OptimService::readEntireFile(std::string& file_content, const std::string& file_path) { std::ifstream f(file_path); if (!f.is_open()) { f.close(); return 1; } getline(f, file_content, (char)EOF); f.close(); return 0; } int OptimService::readOptimData(map& values, const std::string& file_path) { std::ifstream f(file_path); if(!f.good()) { f.close(); return 1; } std::string line; std::vector fields; while (std::getline(f, line)) { boost::algorithm::split(fields, line, boost::algorithm::is_any_of(" ")); values[fields.at(0)] = atof(fields.at(1).c_str()); } f.close(); return 0; } /** * Write test result into file exp/exp{$exp_nbr} * Params are self explanatory **/ void OptimService::writeTestCurrentResult(unsigned int alpha_min, unsigned int alpha_max, unsigned int alpha_curr, unsigned int a_inf_bound, unsigned int a_sup_bound, unsigned int d, unsigned int exp_nbr, OptimVars& vars) { // Open output file exp/exp{$exp_nbr} std::ofstream file(std::string("exp/exp"+ std::to_string(exp_nbr)).c_str(), std::ios::out | std::ios::app ); // Try to output double values always with the same amount of decimals file.setf( std::ios::fixed, std:: ios::floatfield ); // Output test result in a line file << d << "\t" << alpha_min << "\t" << alpha_max << "\t" << alpha_curr << "\t" << a_inf_bound << " \t" << a_sup_bound << "\t" << vars.getGenQ() << " \t " << vars.getSendQ() << " \t " << vars.getGenR() << "\t" << vars.getSendR() << " \t " << vars.getDecR() << "\t" << vars.getValue() << std::endl; file.close(); } int OptimService::writeOptimData(double encrypt_time, double decrypt_time, std::string crypto_params_desc, std::string crypto_name) { std::ofstream fdec(folderName + fileName + crypto_name + decFileExtension, ios::app); std::ofstream fenc(folderName + fileName + crypto_name + encFileExtension, ios::app); fdec.setf( std::ios::fixed, std:: ios::floatfield ); fenc.setf( std::ios::fixed, std:: ios::floatfield ); if (!fdec.good() || !fenc.good()) { fenc.close(); fdec.close(); return 1; } fenc << crypto_params_desc << " " << encrypt_time << std::endl; fdec << crypto_params_desc << " " << decrypt_time << std::endl; return 0; } int OptimService::writeOptimDataBuffer(const std::string& buffer, const std::string& file_path) { std::ofstream f(file_path); if (!f.good()) { f.close(); return 1; } f << buffer; f.close(); return 0; } void OptimService::gotoLine(std::ifstream& file, unsigned int num) { if (num > 0) { file.seekg(std::ios::beg); for (unsigned int i = 0 ; i < num ; ++i) { file.ignore(std::numeric_limits::max(),'\n'); } } } void OptimService::writeFootFile(unsigned int i) { std::ofstream file(std::string("exp/exp"+ std::to_string(i)).c_str(), std::ios::out | std::ios::app ); file << std::endl <<"#End " << getCurrentTime() << std::endl; file.close(); } void OptimService::writeTestCurrentResult(unsigned int alpha, unsigned int alphaMul, unsigned int d, unsigned int i, OptimVars& vars) { std::ofstream file(std::string("exp/exp"+ std::to_string(i)).c_str(), std::ios::out | std::ios::app ); file.setf( std::ios::fixed, std:: ios::floatfield ); file << d << "\t" << alpha << " \t" << alphaMul << "\t" << vars.getGenQ() << " \t " << vars.getSendQ() << " \t " << vars.getGenR() << "\t" << vars.getSendR() << " \t " << vars.getDecR() << "\t" << vars.getValue() << std::endl; file.close(); } void OptimService::writeMessage(unsigned int i, std::string const& message) { std::ofstream file(std::string("exp/exp"+ std::to_string(i)).c_str(), std::ios::out | std::ios::app ); file << message << std::endl; file.close(); } void OptimService::writeConfigFile(unsigned int alpha, unsigned int alphaMul, unsigned int d, unsigned int exp_nbr) { std::ofstream file(std::string("configFile" + std::to_string(exp_nbr)).c_str(), std::ios::out); file << "alpha\t" << alpha << endl; file << "alphaM\t" << alphaMul << endl; file.close(); } void OptimService::writeLWEFile(unsigned int order, unsigned int p_size, unsigned int exp_nbr) { std::ofstream file(std::string("LWEFile" + std::to_string(exp_nbr)).c_str(), std::ios::out); file << "degree\t" << order << endl; file << "p_size\t" << p_size << endl; file.close(); } // Ugly test can cause segfault if file is somehow too big // Should try to build a cache dictionary and test whether the // desired crypto_params have been filled int OptimService::verifyOptimData(set crypto_params_set, const std::string& fenc_path, const std::string& fdec_path) { string line_dec, line_enc; unsigned int params_nbr = crypto_params_set.size(); int return_value = 1; std::ifstream fdec(fenc_path); std::ifstream fenc(fdec_path); if (!fenc.is_open() || !fdec.is_open()) { return 0; } if(getNumberOfLines(fdec) < params_nbr || getNumberOfLines(fenc) < params_nbr) { fdec.close(); fenc.close(); std::ofstream fdec_in(fdec_path); std::ofstream fenc_in(fenc_path); fdec_in.close(); fdec_in.close(); return_value = 0; } fdec.close(); fenc.close(); return return_value; } unsigned int OptimService::getNumberOfLines(std::ifstream& f) { unsigned int i = 0; string line; while (std::getline(f, line)) { if(!(line.c_str()[0] == '#')) i++;//jump over commented line } return i; } // Returns true if optimization file does not exist or is outdated bool OptimService::fileOutdated(std::string crypto_name, std::string extension) { map cache; std::string file_path(OptimService::folderName + OptimService::fileName + crypto_name + extension); // Try to open and read the file // If it fails suppose that it is because the file does not exist if(readOptimData(cache, file_path)) { std::cout << "OptimService: Could not access cache file" << std::endl; return true; } // Get a set with all the crypto parameters of the requested cryptosystem CryptographicSystem* crypto_ptr = HomomorphicCryptoFactory_internal::getCrypto(crypto_name); std::set crypto_params_set; crypto_ptr->getAllCryptoParams(crypto_params_set); // Try to find each crypto_param in the cache and remove it for (auto crypto_param : crypto_params_set) { // If there is an element missing in the cache file is outdated if (cache.erase(crypto_param) == 0) { std::cout << "OptimService: "<< crypto_param << " not found in the cache" << std::endl; delete crypto_ptr; return true; } } // If some values in the cache do not correspond to a crypto_param file is outdated if(!cache.empty()) { std::cout << "OptimService: " << extension << " cache has too many entries" << std::endl; delete crypto_ptr; return true; } delete crypto_ptr; return false; }