networkClient.cpp 34 KB

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