networkClient.cpp 38 KB

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