networkClient.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. #include <iostream>
  2. #include <fstream>
  3. #include <sstream>
  4. #include "networkClient.hpp"
  5. /********************************************************
  6. ********* *********
  7. ********* client networking public functions *********
  8. ********* *********
  9. ********************************************************/
  10. /*
  11. * CREATOR FOR A NEW CLIENT
  12. */
  13. PrsonaClient *create_client(
  14. std::default_random_engine& rng,
  15. const std::vector<std::string>& serverIPs,
  16. const std::vector<int>& serverPorts,
  17. size_t numServers)
  18. {
  19. std::vector<size_t> bandwidthData(2);
  20. // Get the servers' public BGN key
  21. BGNPublicKey publicKey = get_bgn_public_key(rng, serverIPs, serverPorts);
  22. // Get the H point used in ElGamal operations
  23. std::vector<Proof> generatorProof;
  24. Twistpoint blindGenerator = get_generator(rng, serverIPs, serverPorts, false, generatorProof, bandwidthData);
  25. // Make the actual client object
  26. PrsonaClient *retval = new PrsonaClient(generatorProof, blindGenerator, publicKey, numServers);
  27. // Get the current fresh generator
  28. generatorProof.clear();
  29. Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
  30. // Load this fresh generator into the client object
  31. retval->receive_fresh_generator(generatorProof, freshGenerator);
  32. // Make the client's current short term public key
  33. Proof proofOfValidSTPK;
  34. Twistpoint shortTermPublicKey = retval->get_short_term_public_key(proofOfValidSTPK);
  35. // Register this client with the servers
  36. register_new_client(rng, retval, serverIPs, serverPorts, proofOfValidSTPK, shortTermPublicKey);
  37. return retval;
  38. }
  39. /*
  40. * FUNCTIONS TO PERFORM OPERATIONS FOR EXPERIMENT
  41. */
  42. void make_vote(
  43. std::default_random_engine& rng,
  44. PrsonaClient* prsonaClient,
  45. const std::vector<std::string>& serverIPs,
  46. const std::vector<int>& serverPorts,
  47. const std::string& target,
  48. int targetPort,
  49. size_t numClients,
  50. const CivetServer& civetServer,
  51. std::mutex& outputMtx,
  52. const std::string& outputFilename,
  53. std::mutex& usageMtx,
  54. const std::string& usageFilename)
  55. {
  56. std::uniform_int_distribution<int> voteDistribution(0, PrsonaBase::get_max_allowed_vote());
  57. std::uniform_int_distribution<int> numVoteDistribution(0, numClients);
  58. size_t numVotes = numVoteDistribution(rng);
  59. std::vector<size_t> bandwidthData(2);
  60. bandwidthData[0] = 0;
  61. bandwidthData[1] = 0;
  62. // Make the correct number of new votes, but shuffle where they go
  63. std::vector<Scalar> votes;
  64. std::vector<bool> replaces;
  65. for (size_t j = 0; j < numClients; j++)
  66. {
  67. votes.push_back(Scalar(voteDistribution(rng)));
  68. replaces.push_back(j < numVotes);
  69. }
  70. shuffle(replaces.begin(), replaces.end(), rng);
  71. std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer.getContext());
  72. std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
  73. clock_t cpuTimeBefore = clock();
  74. // Get current fresh generator (it's not guaranteed we've done this in the current epoch)
  75. std::vector<Proof> generatorProof;
  76. Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
  77. // Load fresh generator into client object
  78. prsonaClient->receive_fresh_generator(generatorProof, freshGenerator);
  79. // Make current short term public key
  80. Twistpoint shortTermPublicKey = prsonaClient->get_short_term_public_key();
  81. // Get this client's current encrypted votes
  82. std::vector<Proof> fullProof;
  83. std::vector<TwistBipoint> encryptedVotes = get_server_committed_val<std::vector<TwistBipoint>>(rng, serverIPs, serverPorts, REQUEST_VOTE_ROW_URI, REQUEST_VOTE_ROW_COMMITMENT_URI, fullProof, shortTermPublicKey, bandwidthData);
  84. // Use the client's method to make valid new votes (and their proof)
  85. std::vector<Proof> voteProof;
  86. encryptedVotes = prsonaClient->make_votes(voteProof, fullProof, encryptedVotes, votes, replaces);
  87. // Serialize this data
  88. std::string data = make_vote_string(voteProof, encryptedVotes, shortTermPublicKey);
  89. // Send the new votes (and their proof) to the chosen server
  90. send_item(rng, target, targetPort, SUBMIT_VOTE_URI, data, false, bandwidthData);
  91. clock_t cpuTimeAfter = clock();
  92. std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
  93. std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer.getContext());
  94. std::vector<double> timingData(2);
  95. timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
  96. timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
  97. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
  98. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
  99. write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
  100. write_usage_data(usageMtx, usageFilename);
  101. }
  102. bool make_reputation_proof(
  103. std::default_random_engine& rng,
  104. PrsonaClient* prsonaClient,
  105. const std::vector<std::string>& serverIPs,
  106. const std::vector<int>& serverPorts,
  107. const std::string& target,
  108. int targetPort,
  109. size_t numClients,
  110. const CivetServer& civetServer,
  111. std::mutex& outputMtx,
  112. const std::string& outputFilename,
  113. std::mutex& usageMtx,
  114. const std::string& usageFilename)
  115. {
  116. std::vector<double> timingData(2);
  117. std::vector<size_t> bandwidthData(2), bandwidthDataMidA(2), bandwidthDataMidB(2);
  118. bandwidthData[0] = 0;
  119. bandwidthData[1] = 0;
  120. std::string extraOutput = outputFilename + ".extra";
  121. std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer.getContext());
  122. std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
  123. clock_t cpuTimeBefore = clock();
  124. // Get current fresh generator (it's not guaranteed we've done this in the current epoch)
  125. std::vector<Proof> generatorProof;
  126. Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
  127. // EXTRA 1
  128. bandwidthDataMidA = bandwidthData;
  129. write_log_data(outputMtx, extraOutput, timingData, bandwidthData);
  130. // Load fresh generator into client object
  131. prsonaClient->receive_fresh_generator(generatorProof, freshGenerator);
  132. // Make current short term public key
  133. Twistpoint shortTermPublicKey = prsonaClient->get_short_term_public_key();
  134. // Get this client's current encrypted score
  135. std::vector<Proof> encryptedScoreProof;
  136. EGCiphertext encryptedScore = get_server_committed_val<EGCiphertext>(rng, serverIPs, serverPorts, REQUEST_CLIENT_TALLY_URI, REQUEST_CLIENT_TALLY_COMMITMENT_URI, encryptedScoreProof, shortTermPublicKey, bandwidthData);
  137. // EXTRA 2
  138. bandwidthDataMidB[0] = bandwidthData[0] - bandwidthDataMidA[0];
  139. bandwidthDataMidB[1] = bandwidthData[1] - bandwidthDataMidA[1];
  140. bandwidthDataMidA = bandwidthData;
  141. write_log_data(outputMtx, extraOutput, timingData, bandwidthDataMidB);
  142. // Load this current encrypted score into client object
  143. prsonaClient->receive_vote_tally(encryptedScoreProof, encryptedScore);
  144. // Zero will always be a valid threshold
  145. Scalar threshold(0);
  146. // Use client object to generate a correct reputation proof with the chosen parameters
  147. std::vector<Proof> repProof = prsonaClient->generate_reputation_proof(threshold, numClients);
  148. // Serialize that proof
  149. std::string data = make_rep_proof_string(repProof, shortTermPublicKey, threshold);
  150. // Send that proof to a chosen client (and set up a file to receive whether or not the client accepted the proof)
  151. char *responseFile = send_item(rng, target, targetPort, VERIFY_REPUTATION_PROOF_URI, data, true, bandwidthData);
  152. // EXTRA 3
  153. bandwidthDataMidB[0] = bandwidthData[0] - bandwidthDataMidA[0];
  154. bandwidthDataMidB[1] = bandwidthData[1] - bandwidthDataMidA[1];
  155. write_log_data(outputMtx, extraOutput, timingData, bandwidthDataMidB);
  156. clock_t cpuTimeAfter = clock();
  157. std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
  158. std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer.getContext());
  159. timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
  160. timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
  161. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
  162. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
  163. write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
  164. write_usage_data(usageMtx, usageFilename);
  165. // The other client will give one byte back, containing whether or not it accepted the proof
  166. std::ifstream response(responseFile);
  167. char passed = response.get();
  168. // Delete the temp file
  169. remove(responseFile);
  170. delete [] responseFile;
  171. return passed == '\x01';
  172. }
  173. /*********************************************************
  174. ********* *********
  175. ********* client networking private functions *********
  176. ********* *********
  177. *********************************************************/
  178. /*
  179. * HELPERS TO ADD THIS CLIENT TO SERVERS
  180. */
  181. void register_new_client(
  182. std::default_random_engine& rng,
  183. PrsonaClient *newUser,
  184. const std::vector<std::string>& serverIPs,
  185. const std::vector<int>& serverPorts,
  186. const Proof& proofOfValidSTPK,
  187. const Twistpoint& shortTermPublicKey)
  188. {
  189. struct synchronization_tool sync;
  190. char *filename = NULL;
  191. struct mg_connection *conn = NULL;
  192. // Serialize the relevant data that needs to be sent
  193. std::stringstream buffer;
  194. std::string data;
  195. buffer << proofOfValidSTPK;
  196. buffer << shortTermPublicKey;
  197. data = buffer.str();
  198. // Set up connection to a server
  199. std::unique_lock<std::mutex> lck(sync.mtx);
  200. sync.val = 0;
  201. while (!conn)
  202. {
  203. // Pick a (pseudo-)random server to register this client with
  204. std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
  205. size_t whichServer = distribution(rng);
  206. conn = mg_connect_websocket_client(serverIPs[whichServer].c_str(), serverPorts[whichServer], USE_SSL, NULL, 0, SUBMIT_NEW_CLIENT_URI, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
  207. if (!conn)
  208. std::cerr << "Couldn't register new client" << std::endl;
  209. }
  210. // Establish a file to receive proof of addition to system at
  211. filename = set_temp_filename(rng, conn);
  212. // Send client data
  213. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
  214. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  215. // Wait for response
  216. while (!sync.val)
  217. sync.cv.wait(lck);
  218. // Close connection
  219. mg_close_connection(conn);
  220. // Un-serialize proof of addition to system
  221. std::vector<Proof> proofOfValidAddition = get_valid_addition_proof_from_file(filename);
  222. // Remove temp file used to receive serialized data
  223. remove(filename);
  224. delete [] filename;
  225. // Verify that the client was correctly added to the server
  226. verify_valid_addition(rng, newUser, serverIPs, serverPorts, proofOfValidAddition, shortTermPublicKey);
  227. }
  228. void verify_valid_addition(
  229. std::default_random_engine& rng,
  230. PrsonaClient *newUser,
  231. const std::vector<std::string>& serverIPs,
  232. const std::vector<int>& serverPorts,
  233. const std::vector<Proof>& proofOfValidAddition,
  234. const Twistpoint& shortTermPublicKey)
  235. {
  236. std::vector<size_t> bandwidthData(2);
  237. // Get general information on state of system from servers
  238. std::vector<Proof> serverEncryptedScoreProof;
  239. CurveBipoint serverEncryptedScore = get_server_committed_val<CurveBipoint>(rng, serverIPs, serverPorts, REQUEST_SERVER_TALLY_URI, REQUEST_SERVER_TALLY_COMMITMENT_URI, serverEncryptedScoreProof, shortTermPublicKey, bandwidthData);
  240. std::vector<Proof> userEncryptedScoreProof;
  241. EGCiphertext userEncryptedScore = get_server_committed_val<EGCiphertext>(rng, serverIPs, serverPorts, REQUEST_CLIENT_TALLY_URI, REQUEST_CLIENT_TALLY_COMMITMENT_URI, userEncryptedScoreProof, shortTermPublicKey, bandwidthData);
  242. std::vector<Proof> voteMatrixProof;
  243. std::vector<std::vector<TwistBipoint>> voteMatrix = get_server_committed_val<std::vector<std::vector<TwistBipoint>>>(rng, serverIPs, serverPorts, REQUEST_VOTE_MATRIX_URI, REQUEST_VOTE_MATRIX_COMMITMENT_URI, voteMatrixProof, shortTermPublicKey, bandwidthData);
  244. std::vector<Proof> pseudonymsProof;
  245. std::vector<Twistpoint> currentPseudonyms = get_server_committed_val<std::vector<Twistpoint>>(rng, serverIPs, serverPorts, REQUEST_PSEUDONYMS_URI, REQUEST_PSEUDONYMS_COMMITMENT_URI, pseudonymsProof, shortTermPublicKey, bandwidthData);
  246. // Use client's normal verification method
  247. newUser->receive_new_user_data(proofOfValidAddition, serverEncryptedScoreProof, serverEncryptedScore, userEncryptedScoreProof, userEncryptedScore, voteMatrixProof, voteMatrix, pseudonymsProof, currentPseudonyms);
  248. }
  249. /*
  250. * GETTERS FOR VARIOUS SERVER VALUES
  251. */
  252. Twistpoint get_generator(
  253. std::default_random_engine& rng,
  254. const std::vector<std::string>& serverIPs,
  255. const std::vector<int>& serverPorts,
  256. bool fresh,
  257. std::vector<Proof>& pi,
  258. std::vector<size_t>& bandwidthData)
  259. {
  260. pi.clear();
  261. struct synchronization_tool sync;
  262. char *filename = NULL;
  263. struct mg_connection *conn = NULL;
  264. const char* whichUri = (fresh ? REQUEST_FRESH_GENERATOR_URI : REQUEST_EG_BLIND_GENERATOR_URI);
  265. // Set up connection to a server
  266. std::unique_lock<std::mutex> lck(sync.mtx);
  267. sync.val = 0;
  268. while (!conn)
  269. {
  270. // Pick a (pseudo-)random server to get the generator from
  271. std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
  272. size_t whichServer = distribution(rng);
  273. conn = mg_connect_websocket_client(serverIPs[whichServer].c_str(), serverPorts[whichServer], USE_SSL, NULL, 0, whichUri, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
  274. if (!conn)
  275. std::cerr << "Couldn't connect to servers to get generator" << std::endl;
  276. }
  277. std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
  278. // Establish a file to receive generator at
  279. filename = set_temp_filename(rng, conn);
  280. // Tell server to go ahead with data
  281. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  282. // Wait for data
  283. while (!sync.val)
  284. sync.cv.wait(lck);
  285. std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
  286. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
  287. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
  288. // Close connection
  289. mg_close_connection(conn);
  290. // Un-serialize generator
  291. Twistpoint retval = get_generator_from_file(filename, pi);
  292. // Remove temp file used to receive serialized data
  293. remove(filename);
  294. delete [] filename;
  295. return retval;
  296. }
  297. BGNPublicKey get_bgn_public_key(
  298. std::default_random_engine& rng,
  299. const std::vector<std::string>& serverIPs,
  300. const std::vector<int>& serverPorts)
  301. {
  302. struct synchronization_tool sync;
  303. char *filename = NULL;
  304. struct mg_connection *conn = NULL;
  305. // Set up connection to a server
  306. std::unique_lock<std::mutex> lck(sync.mtx);
  307. sync.val = 0;
  308. while (!conn)
  309. {
  310. // Pick a (pseudo-)random server to get bgn data from
  311. std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
  312. size_t whichServer = distribution(rng);
  313. conn = mg_connect_websocket_client(serverIPs[whichServer].c_str(), serverPorts[whichServer], USE_SSL, NULL, 0, REQUEST_BGN_PUBKEY_URI, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
  314. if (!conn)
  315. std::cerr << "Couldn't connect to servers to obtain BGN details" << std::endl;
  316. }
  317. // Establish a file to receive BGN public key at
  318. filename = set_temp_filename(rng, conn);
  319. // Tell server to go ahead with data
  320. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  321. // Wait for data
  322. while (!sync.val)
  323. sync.cv.wait(lck);
  324. // Close connection
  325. mg_close_connection(conn);
  326. // Un-serialize BGN public key
  327. BGNPublicKey retval = get_bgn_public_key_from_file(filename);
  328. // Remove temp file used to receive serialized data
  329. remove(filename);
  330. delete [] filename;
  331. return retval;
  332. }
  333. template <typename T>
  334. T get_server_committed_val(
  335. std::default_random_engine& rng,
  336. const std::vector<std::string>& serverIPs,
  337. const std::vector<int>& serverPorts,
  338. const char *firstUri,
  339. const char *commitUri,
  340. std::vector<Proof>& pi,
  341. const Twistpoint& shortTermPublicKey,
  342. std::vector<size_t>& bandwidthData)
  343. {
  344. pi.clear();
  345. // Pick a (pseudo-)random server to get a committed-to value from
  346. std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
  347. size_t whichServer = distribution(rng);
  348. // Get the value itself
  349. Proof firstProof;
  350. T retval = get_first_committed_val<T>(rng, serverIPs[whichServer], serverPorts[whichServer], firstUri, firstProof, shortTermPublicKey, bandwidthData);
  351. // Get all the other server's hashes of the value (to confirm they all agree on it)
  352. pi.push_back(firstProof);
  353. get_additional_commitment(rng, serverIPs, serverPorts, serverIPs[whichServer], serverPorts[whichServer], commitUri, pi, shortTermPublicKey, bandwidthData);
  354. return retval;
  355. }
  356. template EGCiphertext get_server_committed_val<EGCiphertext>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
  357. template CurveBipoint get_server_committed_val<CurveBipoint>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
  358. template std::vector<Twistpoint> get_server_committed_val<std::vector<Twistpoint>>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
  359. template std::vector<TwistBipoint> get_server_committed_val<std::vector<TwistBipoint>>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
  360. template std::vector<std::vector<TwistBipoint>> get_server_committed_val<std::vector<std::vector<TwistBipoint>>>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
  361. /*
  362. * HELPERS FOR GENERALIZED GETTER FUNCTION
  363. */
  364. template <typename T>
  365. T get_first_committed_val(
  366. std::default_random_engine& rng,
  367. const std::string& serverIP,
  368. int serverPort,
  369. const char *firstUri,
  370. Proof& pi,
  371. const Twistpoint& shortTermPublicKey,
  372. std::vector<size_t>& bandwidthData)
  373. {
  374. struct synchronization_tool sync;
  375. char *filename = NULL;
  376. struct mg_connection *conn = NULL;
  377. // Serialize the relevant data that needs to be sent
  378. std::stringstream buffer;
  379. std::string data;
  380. buffer << shortTermPublicKey;
  381. data = buffer.str();
  382. // Set up connection to a server
  383. std::unique_lock<std::mutex> lck(sync.mtx);
  384. sync.val = 0;
  385. while (!conn)
  386. {
  387. conn = mg_connect_websocket_client(serverIP.c_str(), serverPort, USE_SSL, NULL, 0, firstUri, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
  388. if (!conn)
  389. std::cerr << "Trouble getting encrypted score from server at " << serverIP << ":" << serverPort << std::endl;
  390. }
  391. std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
  392. // Establish a file to receive committed-to value at
  393. filename = set_temp_filename(rng, conn);
  394. // Send request data
  395. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
  396. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  397. // Wait for response
  398. while (!sync.val)
  399. sync.cv.wait(lck);
  400. std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
  401. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
  402. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
  403. // Close connection
  404. mg_close_connection(conn);
  405. // Un-serialize committed-to value
  406. T retval = get_committed_val_from_file<T>(filename, pi);
  407. // Remove temp file used to receive serialized data
  408. remove(filename);
  409. delete [] filename;
  410. return retval;
  411. }
  412. void get_additional_commitment(
  413. std::default_random_engine& rng,
  414. const std::vector<std::string>& serverIPs,
  415. const std::vector<int>& serverPorts,
  416. const std::string& skipIP,
  417. int skipPort,
  418. const char *commitUri,
  419. std::vector<Proof>& pi,
  420. const Twistpoint& shortTermPublicKey,
  421. std::vector<size_t>& bandwidthData)
  422. {
  423. std::vector<char *> commitmentFilenames;
  424. std::vector<struct synchronization_tool *> commitmentSyncs;
  425. // Serialize the relevant data that needs to be sent
  426. std::stringstream buffer;
  427. std::string data;
  428. buffer << shortTermPublicKey;
  429. data = buffer.str();
  430. // Ask each server (besides the one we got the value from) what the hash of it is
  431. for (size_t i = 0; i < serverIPs.size(); i++)
  432. {
  433. if (serverIPs[i] == skipIP && serverPorts[i] == skipPort)
  434. continue;
  435. struct synchronization_tool *currSync = new struct synchronization_tool;
  436. commitmentSyncs.push_back(currSync);
  437. struct mg_connection *conn = NULL;
  438. // Set up connection to a server
  439. std::unique_lock<std::mutex> lck(currSync->mtx);
  440. currSync->val = 0;
  441. while (!conn)
  442. {
  443. conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, commitUri, "null", file_websocket_data_handler, file_websocket_close_handler, currSync);
  444. if (!conn)
  445. std::cerr << "Trouble getting commitment from server at " << serverIPs[i] << ":" << serverPorts[i] << std::endl;
  446. }
  447. std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
  448. // Establish a file to receive hash at
  449. commitmentFilenames.push_back(set_temp_filename(rng, conn));
  450. // Send request data
  451. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
  452. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  453. // Wait for response
  454. while (!currSync->val)
  455. currSync->cv.wait(lck);
  456. std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
  457. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
  458. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
  459. // Close connection
  460. mg_close_connection(conn);
  461. }
  462. for (size_t i = 0; i < commitmentFilenames.size(); i++)
  463. {
  464. // Un-serialize hash
  465. pi.push_back(get_commitment_from_file(commitmentSyncs[i], commitmentFilenames[i]));
  466. // Clean up the std::mutex used for this hash
  467. delete commitmentSyncs[i];
  468. // Delete temp file used to receive serialized data
  469. remove(commitmentFilenames[i]);
  470. delete [] commitmentFilenames[i];
  471. }
  472. }
  473. /*
  474. * FILE I/O HELPERS FOR ALL GETTERS
  475. */
  476. std::vector<Proof> get_valid_addition_proof_from_file(
  477. const char *filename)
  478. {
  479. std::ifstream additionFile(filename);
  480. std::vector<Proof> retval;
  481. BinarySizeT sizeOfVector;
  482. additionFile >> sizeOfVector;
  483. for (size_t i = 0; i < sizeOfVector.val(); i++)
  484. {
  485. Proof currProof;
  486. additionFile >> currProof;
  487. retval.push_back(currProof);
  488. }
  489. return retval;
  490. }
  491. Twistpoint get_generator_from_file(
  492. const char *filename,
  493. std::vector<Proof>& pi)
  494. {
  495. std::ifstream genFile(filename);
  496. BinarySizeT sizeOfVector;
  497. genFile >> sizeOfVector;
  498. for (size_t i = 0; i < sizeOfVector.val(); i++)
  499. {
  500. Proof currProof;
  501. genFile >> currProof;
  502. pi.push_back(currProof);
  503. }
  504. Twistpoint retval;
  505. genFile >> retval;
  506. return retval;
  507. }
  508. BGNPublicKey get_bgn_public_key_from_file(
  509. const char *filename)
  510. {
  511. std::ifstream bgnFile(filename);
  512. BGNPublicKey publicKey;
  513. bgnFile >> publicKey;
  514. return publicKey;
  515. }
  516. // User-encrytped score
  517. template <>
  518. EGCiphertext get_committed_val_from_file<EGCiphertext>(
  519. const char *filename,
  520. Proof& pi)
  521. {
  522. std::ifstream valFile(filename);
  523. EGCiphertext retval;
  524. valFile >> pi;
  525. valFile >> retval;
  526. return retval;
  527. }
  528. // Server-encrytped score
  529. template <>
  530. CurveBipoint get_committed_val_from_file<CurveBipoint>(
  531. const char *filename,
  532. Proof& pi)
  533. {
  534. std::ifstream valFile(filename);
  535. CurveBipoint retval;
  536. valFile >> pi;
  537. valFile >> retval;
  538. return retval;
  539. }
  540. // Current pseudonyms
  541. template <>
  542. std::vector<Twistpoint> get_committed_val_from_file<std::vector<Twistpoint>>(
  543. const char *filename,
  544. Proof& pi)
  545. {
  546. std::ifstream valFile(filename);
  547. valFile >> pi;
  548. std::vector<Twistpoint> retval;
  549. BinarySizeT sizeOfVector;
  550. valFile >> sizeOfVector;
  551. for (size_t i = 0; i < sizeOfVector.val(); i++)
  552. {
  553. Twistpoint currVote;
  554. valFile >> currVote;
  555. retval.push_back(currVote);
  556. }
  557. return retval;
  558. }
  559. // Vote row
  560. template <>
  561. std::vector<TwistBipoint> get_committed_val_from_file<std::vector<TwistBipoint>>(
  562. const char *filename,
  563. Proof& pi)
  564. {
  565. std::ifstream valFile(filename);
  566. valFile >> pi;
  567. std::vector<TwistBipoint> retval;
  568. BinarySizeT sizeOfVector;
  569. valFile >> sizeOfVector;
  570. for (size_t i = 0; i < sizeOfVector.val(); i++)
  571. {
  572. TwistBipoint currVote;
  573. valFile >> currVote;
  574. retval.push_back(currVote);
  575. }
  576. return retval;
  577. }
  578. // Full vote matrix
  579. template <>
  580. std::vector<std::vector<TwistBipoint>> get_committed_val_from_file<std::vector<std::vector<TwistBipoint>>>(
  581. const char *filename,
  582. Proof& pi)
  583. {
  584. std::ifstream valFile(filename);
  585. valFile >> pi;
  586. std::vector<std::vector<TwistBipoint>> retval;
  587. BinarySizeT sizeOfVector;
  588. valFile >> sizeOfVector;
  589. for (size_t i = 0; i < sizeOfVector.val(); i++)
  590. {
  591. std::vector<TwistBipoint> currRow;
  592. for (size_t j = 0; j < sizeOfVector.val(); j++)
  593. {
  594. TwistBipoint currVote;
  595. valFile >> currVote;
  596. currRow.push_back(currVote);
  597. }
  598. retval.push_back(currRow);
  599. }
  600. return retval;
  601. }
  602. // NOTE: this function is the weird only case in which its usage will not assume you already have possession of the file lock to read from
  603. Proof get_commitment_from_file(
  604. struct synchronization_tool *sync,
  605. const char *filename)
  606. {
  607. std::unique_lock<std::mutex> lck(sync->mtx);
  608. std::ifstream scoreFile(filename);
  609. Proof retval;
  610. scoreFile >> retval;
  611. return retval;
  612. }
  613. /*
  614. * GENERALIZED SENDER FOR ORCHESTRATOR-SIGNALED OPERATIONS
  615. */
  616. char *send_item(
  617. std::default_random_engine& rng,
  618. const std::string& target,
  619. int targetPort,
  620. const char* whichUri,
  621. const std::string& data,
  622. bool responseExpected,
  623. std::vector<size_t>& bandwidthData)
  624. {
  625. struct synchronization_tool sync;
  626. char *retval = NULL;
  627. struct mg_connection *conn = NULL;
  628. // Keep looping until item has been correctly received
  629. std::unique_lock<std::mutex> lck(sync.mtx);
  630. sync.val = 0;
  631. sync.val2 = 0;
  632. while (!sync.val)
  633. {
  634. // Set up connection to a server
  635. while (!conn)
  636. {
  637. if (responseExpected)
  638. conn = mg_connect_websocket_client(target.c_str(), targetPort, USE_SSL, NULL, 0, whichUri, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
  639. else
  640. conn = mg_connect_websocket_client(target.c_str(), targetPort, USE_SSL, NULL, 0, whichUri, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
  641. if (!conn)
  642. std::cerr << "Couldn't connect to server for purposes of sending item." << std::endl;
  643. }
  644. std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), false);
  645. // Set up a file to receive a response at (if it's expected)
  646. if (responseExpected)
  647. retval = set_temp_filename(rng, conn);
  648. // Send request data
  649. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
  650. mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  651. // Wait until the server has closed the connection
  652. while (!sync.val2)
  653. sync.cv.wait(lck);
  654. std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), false);
  655. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
  656. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
  657. // Close connection
  658. mg_close_connection(conn);
  659. conn = NULL;
  660. }
  661. return retval;
  662. }
  663. /*
  664. * DATA SERIALIZERS
  665. */
  666. std::string make_vote_string(
  667. const std::vector<Proof>& pi,
  668. const std::vector<TwistBipoint>& newVotes,
  669. const Twistpoint& shortTermPublicKey)
  670. {
  671. std::stringstream buffer;
  672. BinarySizeT sizeOfVector;
  673. sizeOfVector.set(pi.size());
  674. buffer << sizeOfVector;
  675. for (size_t i = 0; i < sizeOfVector.val(); i++)
  676. buffer << pi[i];
  677. sizeOfVector.set(newVotes.size());
  678. buffer << sizeOfVector;
  679. for (size_t i = 0; i < sizeOfVector.val(); i++)
  680. buffer << newVotes[i];
  681. buffer << shortTermPublicKey;
  682. // Clients always tell the server they should share the vote row with other servers; servers never tell other servers to do this
  683. BinaryBool shouldDeal(true);
  684. buffer << shouldDeal;
  685. return buffer.str();
  686. }
  687. std::string make_rep_proof_string(
  688. const std::vector<Proof>& pi,
  689. const Twistpoint& shortTermPublicKey,
  690. const Scalar& threshold)
  691. {
  692. std::stringstream buffer;
  693. BinarySizeT sizeOfVector;
  694. sizeOfVector.set(pi.size());
  695. buffer << sizeOfVector;
  696. for (size_t i = 0; i < sizeOfVector.val(); i++)
  697. buffer << pi[i];
  698. buffer << shortTermPublicKey;
  699. buffer << threshold;
  700. return buffer.str();
  701. }
  702. /**********************************************************
  703. **** ****
  704. **** other client-relevant handler member functions ****
  705. **** ****
  706. **********************************************************/
  707. /*
  708. * CLIENT READY HANDLER
  709. */
  710. ClientReadyHandler::ClientReadyHandler(
  711. struct synchronization_tool *exitSync)
  712. : exitSync(exitSync)
  713. { /* */ }
  714. bool ClientReadyHandler::handleGet(
  715. CivetServer *server,
  716. struct mg_connection *conn)
  717. {
  718. std::unique_lock<std::mutex> exitLock(exitSync->mtx, std::defer_lock);
  719. if (!exitLock.try_lock())
  720. {
  721. mg_printf(conn, "HTTP/1.1 503 Service Unavailable\r\n"
  722. "Content-Type: text/plain\r\n"
  723. "Connection: close\r\n\r\n");
  724. mg_printf(conn, "Client is still making previous votes or a reputation proof.\n");
  725. }
  726. else
  727. {
  728. mg_printf(conn, "HTTP/1.1 200 OK\r\n"
  729. "Content-Type: text/plain\r\n"
  730. "Connection: close\r\n\r\n");
  731. mg_printf(conn, "Client is ready to move forward.\n");
  732. }
  733. return true;
  734. }
  735. /*********************************************************
  736. **** ****
  737. **** PrsonaClientWebSocketHandler member functions ****
  738. **** ****
  739. *********************************************************/
  740. /*
  741. * CONSTRUCTOR
  742. */
  743. PrsonaClientWebSocketHandler::PrsonaClientWebSocketHandler(
  744. std::default_random_engine& rng,
  745. PrsonaClient *prsonaClient,
  746. const std::vector<std::string>& serverIPs,
  747. const std::vector<int>& serverPorts,
  748. std::mutex& outputMtx,
  749. const std::string& outputFilename,
  750. std::mutex& usageMtx,
  751. const std::string& usageFilename)
  752. : rng(rng), prsonaClient(prsonaClient), serverIPs(serverIPs), serverPorts(serverPorts), outputMtx(outputMtx), outputFilename(outputFilename), usageMtx(usageMtx), usageFilename(usageFilename)
  753. { /* */ }
  754. /*
  755. * REQUIRED BY INHERITED CLASS
  756. */
  757. bool PrsonaClientWebSocketHandler::handleConnection(
  758. CivetServer *server,
  759. const struct mg_connection *conn)
  760. {
  761. const struct mg_request_info *info = mg_get_request_info(conn);
  762. // Check if the request being made is something this client can respond to
  763. bool flag = (info->query_string && info->query_string[0] == PRSONA_VERIFY_REPUTATION_PROOF);
  764. return flag;
  765. }
  766. void PrsonaClientWebSocketHandler::handleReadyState(
  767. CivetServer *server,
  768. struct mg_connection *conn)
  769. {
  770. const struct mg_request_info *info = mg_get_request_info(conn);
  771. // Set filenames for query types that will need to un-serialize data to respond correctly
  772. switch (info->query_string[0])
  773. {
  774. case PRSONA_VERIFY_REPUTATION_PROOF:
  775. set_temp_filename(rng, conn);
  776. break;
  777. default:
  778. mg_set_user_connection_data(conn, NULL);
  779. break;
  780. }
  781. }
  782. bool PrsonaClientWebSocketHandler::handleData(
  783. CivetServer *server,
  784. struct mg_connection *conn,
  785. int bits,
  786. char *data,
  787. size_t data_len)
  788. {
  789. char *filename = (char *) mg_get_user_connection_data(conn);
  790. FILE *currFile = NULL;
  791. switch (bits & 0xf)
  792. {
  793. // Requester has indicated they have sent all relevant data
  794. case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
  795. case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
  796. generate_response(server, conn, filename);
  797. break;
  798. // Requester has sent more data (which may theoretically be broken up into multiple packets)
  799. case MG_WEBSOCKET_OPCODE_BINARY:
  800. case MG_WEBSOCKET_OPCODE_CONTINUATION:
  801. currFile = fopen(filename, "ab");
  802. fwrite(data, sizeof(char), data_len, currFile);
  803. fclose(currFile);
  804. return true;
  805. // Something strange has happened
  806. default:
  807. std::cerr << "Unknown packet type received. Failing." << std::endl;
  808. break;
  809. }
  810. return false;
  811. }
  812. void PrsonaClientWebSocketHandler::handleClose(
  813. CivetServer *server,
  814. const struct mg_connection *conn)
  815. {
  816. char *filename = (char *) mg_get_user_connection_data(conn);
  817. // If we didn't have a temp file for this request, don't do anything
  818. if (!filename)
  819. return;
  820. // If we did, delete it
  821. remove(filename);
  822. delete [] filename;
  823. }
  824. /*
  825. * RESPONSE ROUTER FUNCTION
  826. */
  827. void PrsonaClientWebSocketHandler::generate_response(
  828. CivetServer *server,
  829. struct mg_connection *conn,
  830. const char *filename)
  831. {
  832. const struct mg_request_info *info = mg_get_request_info(conn);
  833. // Select the correct response for this type of request
  834. switch (info->query_string[0])
  835. {
  836. case PRSONA_VERIFY_REPUTATION_PROOF:
  837. verify_reputation_proof(server, conn, filename);
  838. break;
  839. default:
  840. break;
  841. }
  842. }
  843. /*
  844. * REPUTATION PROOF RESPONSE
  845. */
  846. void PrsonaClientWebSocketHandler::verify_reputation_proof(
  847. CivetServer *civetServer,
  848. struct mg_connection *conn,
  849. const char *filename)
  850. {
  851. std::vector<Proof> pi;
  852. Twistpoint shortTermPublicKey;
  853. Scalar threshold;
  854. std::vector<size_t> bandwidthData(2);
  855. bandwidthData[0] = 0;
  856. bandwidthData[1] = 0;
  857. // Un-serialize the reputation proof
  858. std::ifstream file(filename);
  859. file.ignore(std::numeric_limits<std::streamsize>::max());
  860. std::streamsize bandwidthRcv = file.gcount();
  861. file.clear();
  862. file.seekg(0, std::ios_base::beg);
  863. BinarySizeT sizeOfVector;
  864. file >> sizeOfVector;
  865. for (size_t i = 0; i < sizeOfVector.val(); i++)
  866. {
  867. Proof currProof;
  868. file >> currProof;
  869. pi.push_back(currProof);
  870. }
  871. file >> shortTermPublicKey;
  872. file >> threshold;
  873. std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer->getContext());
  874. std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
  875. clock_t cpuTimeBefore = clock();
  876. // Get current fresh generator (it's not guaranteed we've done this in the current epoch)
  877. std::vector<Proof> generatorProof;
  878. Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
  879. // Load fresh generator into client object
  880. prsonaClient->receive_fresh_generator(generatorProof, freshGenerator);
  881. // Get what the servers say is this user's encrypted score
  882. std::vector<Proof> encryptedScoreProof;
  883. EGCiphertext encryptedScore = get_server_committed_val<EGCiphertext>(rng, serverIPs, serverPorts, REQUEST_CLIENT_TALLY_URI, REQUEST_CLIENT_TALLY_COMMITMENT_URI, encryptedScoreProof, shortTermPublicKey, bandwidthData);
  884. // Check if the proof verifies correctly
  885. bool flag = prsonaClient->verify_reputation_proof(pi, shortTermPublicKey, threshold, encryptedScoreProof, encryptedScore);
  886. clock_t cpuTimeAfter = clock();
  887. std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
  888. std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer->getContext());
  889. std::vector<double> timingData(2);
  890. timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
  891. timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
  892. bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0] + bandwidthRcv;
  893. bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1] + 1;
  894. write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
  895. write_usage_data(usageMtx, usageFilename);
  896. // Tell the prover whether or not we accept the proof
  897. std::string data = flag ? "\x01" : "\x00";
  898. mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), 1);
  899. mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  900. }