networkClient.cpp 37 KB

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