networkClient.cpp 36 KB

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