networkClient.cpp 38 KB

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