clientMain.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. #include <mutex>
  2. #include <condition_variable>
  3. #include <chrono>
  4. #include <iostream>
  5. #include <fstream>
  6. #include <cstring>
  7. #include <cstdlib>
  8. #include "networkClient.hpp"
  9. using namespace std;
  10. enum EventType {
  11. CLIENT_MAKE_VOTE = 1,
  12. CLIENT_MAKE_REP_PROOF
  13. };
  14. struct synchronization_tool exitSync;
  15. // Initialize the classes we use
  16. void initialize_prsona_classes()
  17. {
  18. Scalar::init();
  19. PrsonaBase::init();
  20. PrsonaBase::set_client_malicious();
  21. }
  22. BGNPublicKey get_bgn_public_key_from_file(
  23. struct synchronization_tool *sync,
  24. const char *filename)
  25. {
  26. unique_lock<mutex> lck(sync->mtx);
  27. ifstream bgnFile(filename);
  28. BGNPublicKey publicKey;
  29. bgnFile >> publicKey;
  30. return publicKey;
  31. }
  32. vector<Proof> get_valid_addition_proof_from_file(
  33. struct synchronization_tool *sync,
  34. const char *filename)
  35. {
  36. unique_lock<mutex> lck(sync->mtx);
  37. ifstream additionFile(filename);
  38. vector<Proof> retval;
  39. BinarySizeT sizeOfVector;
  40. additionFile >> sizeOfVector;
  41. for (size_t i = 0; i < sizeOfVector.val(); i++)
  42. {
  43. Proof currProof;
  44. additionFile >> currProof;
  45. retval.push_back(currProof);
  46. }
  47. return retval;
  48. }
  49. BGNPublicKey get_bgn_public_key(
  50. default_random_engine *randomGenerator,
  51. const vector<string>& serverIPs,
  52. const vector<int>& serverPorts)
  53. {
  54. struct synchronization_tool sync;
  55. char *filename = NULL;
  56. uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
  57. size_t whichServer = distribution(*randomGenerator);
  58. bool flag = false;
  59. while (!flag)
  60. {
  61. struct mg_connection *conn = mg_connect_websocket_client(
  62. serverIPs[whichServer].c_str(),
  63. serverPorts[whichServer],
  64. USE_SSL,
  65. NULL,
  66. 0,
  67. PUBLIC_BGN_URI,
  68. "null",
  69. file_websocket_data_handler,
  70. file_websocket_close_handler,
  71. (void *) &sync);
  72. if (!conn)
  73. {
  74. cerr << "Couldn't obtain BGN details" << endl;
  75. continue;
  76. }
  77. unique_lock<mutex> lck(sync.mtx);
  78. filename = set_temp_filename(*randomGenerator, conn);
  79. sync.val = 0;
  80. mg_websocket_client_write(
  81. conn,
  82. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  83. "",
  84. 0);
  85. while (!sync.val)
  86. sync.cv.wait(lck);
  87. mg_close_connection(conn);
  88. flag = true;
  89. }
  90. BGNPublicKey retval =
  91. get_bgn_public_key_from_file(&sync, filename);
  92. remove(filename);
  93. delete filename;
  94. return retval;
  95. }
  96. void verify_valid_addition(
  97. PrsonaClient *newUser,
  98. default_random_engine *rng,
  99. const vector<string>& serverIPs,
  100. const vector<int>& serverPorts,
  101. const vector<Proof>& proofOfValidAddition,
  102. const Twistpoint& shortTermPublicKey)
  103. {
  104. vector<Proof> serverEncryptedScoreProof;
  105. CurveBipoint serverEncryptedScore =
  106. get_server_committed_val<CurveBipoint>(
  107. rng,
  108. serverIPs,
  109. serverPorts,
  110. serverEncryptedScoreProof,
  111. shortTermPublicKey,
  112. SERVER_TALLY_URI,
  113. SERVER_TALLY_COMMIT_URI);
  114. vector<Proof> userEncryptedScoreProof;
  115. EGCiphertext userEncryptedScore =
  116. get_server_committed_val<EGCiphertext>(
  117. rng,
  118. serverIPs,
  119. serverPorts,
  120. userEncryptedScoreProof,
  121. shortTermPublicKey,
  122. USER_TALLY_URI,
  123. USER_TALLY_COMMIT_URI);
  124. vector<Proof> voteMatrixProof;
  125. vector<vector<TwistBipoint>> voteMatrix =
  126. get_server_committed_val<vector<vector<TwistBipoint>>>(
  127. rng,
  128. serverIPs,
  129. serverPorts,
  130. voteMatrixProof,
  131. shortTermPublicKey,
  132. VOTE_MATRIX_URI,
  133. VOTE_MATRIX_COMMIT_URI);
  134. vector<Proof> pseudonymsProof;
  135. vector<Twistpoint> currentPseudonyms =
  136. get_server_committed_val<vector<Twistpoint>>(
  137. rng,
  138. serverIPs,
  139. serverPorts,
  140. pseudonymsProof,
  141. shortTermPublicKey,
  142. PSEUDONYMS_URI,
  143. PSEUDONYMS_COMMIT_URI);
  144. newUser->receive_new_user_data(
  145. proofOfValidAddition,
  146. serverEncryptedScoreProof,
  147. serverEncryptedScore,
  148. userEncryptedScoreProof,
  149. userEncryptedScore,
  150. voteMatrixProof,
  151. voteMatrix,
  152. pseudonymsProof,
  153. currentPseudonyms);
  154. }
  155. void register_new_client(
  156. default_random_engine *generator,
  157. const vector<string>& serverIPs,
  158. const vector<int>& serverPorts,
  159. PrsonaClient *newUser,
  160. const Proof& proofOfValidSTPK,
  161. const Twistpoint& shortTermPublicKey)
  162. {
  163. struct synchronization_tool sync;
  164. char *filename = NULL;
  165. stringstream buffer;
  166. string data;
  167. buffer << proofOfValidSTPK;
  168. buffer << shortTermPublicKey;
  169. data = buffer.str();
  170. uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
  171. size_t whichServer = distribution(*generator);
  172. bool flag = false;
  173. while (!flag)
  174. {
  175. struct mg_connection *conn = mg_connect_websocket_client(
  176. serverIPs[whichServer].c_str(),
  177. serverPorts[whichServer],
  178. USE_SSL,
  179. NULL,
  180. 0,
  181. PUBLIC_BGN_URI,
  182. "null",
  183. file_websocket_data_handler,
  184. file_websocket_close_handler,
  185. (void *) &sync);
  186. if (!conn)
  187. {
  188. cerr << "Couldn't register new client" << endl;
  189. continue;
  190. }
  191. unique_lock<mutex> lck(sync.mtx);
  192. filename = set_temp_filename(*generator, conn);
  193. sync.val = 0;
  194. mg_websocket_client_write(
  195. conn,
  196. MG_WEBSOCKET_OPCODE_BINARY,
  197. data.c_str(),
  198. data.length());
  199. mg_websocket_client_write(
  200. conn,
  201. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  202. "",
  203. 0);
  204. while (!sync.val)
  205. sync.cv.wait(lck);
  206. mg_close_connection(conn);
  207. flag = true;
  208. }
  209. vector<Proof> proofOfValidAddition =
  210. get_valid_addition_proof_from_file(&sync, filename);
  211. remove(filename);
  212. delete filename;
  213. verify_valid_addition(newUser, generator, serverIPs, serverPorts, proofOfValidAddition, shortTermPublicKey);
  214. }
  215. PrsonaClient *create_client(
  216. default_random_engine *generator,
  217. const vector<string>& serverIPs,
  218. const vector<int>& serverPorts,
  219. size_t numServers)
  220. {
  221. BGNPublicKey publicKey =
  222. get_bgn_public_key(
  223. generator,
  224. serverIPs,
  225. serverPorts);
  226. vector<Proof> generatorProof;
  227. Twistpoint blindGenerator =
  228. get_generator(
  229. generator,
  230. serverIPs,
  231. serverPorts,
  232. generatorProof,
  233. false);
  234. PrsonaClient *retval =
  235. new PrsonaClient(generatorProof, blindGenerator, publicKey, numServers);
  236. Proof proofOfValidSTPK;
  237. Twistpoint shortTermPublicKey = retval->get_short_term_public_key(
  238. proofOfValidSTPK);
  239. register_new_client(
  240. generator,
  241. serverIPs,
  242. serverPorts,
  243. retval,
  244. proofOfValidSTPK,
  245. shortTermPublicKey);
  246. return retval;
  247. }
  248. string make_vote_string(
  249. const vector<Proof>& pi,
  250. const vector<TwistBipoint>& newVotes,
  251. const Twistpoint& shortTermPublicKey)
  252. {
  253. stringstream buffer;
  254. BinarySizeT sizeOfVector;
  255. sizeOfVector.set(pi.size());
  256. buffer << sizeOfVector;
  257. for (size_t i = 0; i < sizeOfVector.val(); i++)
  258. buffer << pi[i];
  259. sizeOfVector.set(newVotes.size());
  260. buffer << sizeOfVector;
  261. for (size_t i = 0; i < sizeOfVector.val(); i++)
  262. buffer << newVotes[i];
  263. buffer << shortTermPublicKey;
  264. BinaryBool shouldDeal(true);
  265. buffer << shouldDeal;
  266. return buffer.str();
  267. }
  268. void send_item(
  269. const string& target, int targetPort, const string& data, const char* whichUri)
  270. {
  271. struct synchronization_tool sync;
  272. bool flag = false;
  273. while (!flag)
  274. {
  275. struct mg_connection *conn = mg_connect_websocket_client(
  276. target.c_str(),
  277. targetPort,
  278. USE_SSL,
  279. NULL,
  280. 0,
  281. whichUri,
  282. "null",
  283. synchro_websocket_data_handler,
  284. empty_websocket_close_handler,
  285. (void *) &sync);
  286. if (!conn)
  287. {
  288. cerr << "Couldn't obtain BGN details" << endl;
  289. continue;
  290. }
  291. unique_lock<mutex> lck(sync.mtx);
  292. sync.val = 0;
  293. mg_websocket_client_write(
  294. conn,
  295. MG_WEBSOCKET_OPCODE_BINARY,
  296. data.c_str(),
  297. data.length());
  298. mg_websocket_client_write(
  299. conn,
  300. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  301. "",
  302. 0);
  303. while (!sync.val)
  304. sync.cv.wait(lck);
  305. mg_close_connection(conn);
  306. flag = true;
  307. }
  308. }
  309. void make_vote(
  310. default_random_engine& generator,
  311. const string& target,
  312. int targetPort,
  313. PrsonaClient* prsonaClient,
  314. const vector<string>& serverIPs,
  315. const vector<int>& serverPorts,
  316. size_t numClients)
  317. {
  318. uniform_int_distribution<int> voteDistribution(
  319. 0, PrsonaBase::get_max_allowed_vote());
  320. uniform_int_distribution<int> numVoteDistribution(
  321. 0, numClients);
  322. size_t numVotes = numVoteDistribution(generator);
  323. // Make the correct number of new votes, but shuffle where they go
  324. vector<Scalar> votes;
  325. vector<bool> replaces;
  326. for (size_t j = 0; j < numClients; j++)
  327. {
  328. votes.push_back(Scalar(voteDistribution(generator)));
  329. replaces.push_back(j < numVotes);
  330. }
  331. shuffle(replaces.begin(), replaces.end(), generator);
  332. vector<Proof> generatorProof;
  333. Twistpoint freshGenerator =
  334. get_generator(
  335. &generator,
  336. serverIPs,
  337. serverPorts,
  338. generatorProof,
  339. true);
  340. prsonaClient->receive_fresh_generator(
  341. generatorProof, freshGenerator);
  342. Twistpoint shortTermPublicKey =
  343. prsonaClient->get_short_term_public_key();
  344. vector<Proof> fullProof;
  345. vector<TwistBipoint> encryptedVotes =
  346. get_server_committed_val<vector<TwistBipoint>>(
  347. &generator,
  348. serverIPs,
  349. serverPorts,
  350. fullProof,
  351. shortTermPublicKey,
  352. VOTES_BY_URI,
  353. VOTES_BY_COMMIT_URI);
  354. vector<Proof> voteProof;
  355. encryptedVotes =
  356. prsonaClient->make_votes(
  357. voteProof,
  358. fullProof,
  359. encryptedVotes,
  360. votes,
  361. replaces);
  362. string data =
  363. make_vote_string(voteProof, encryptedVotes, shortTermPublicKey);
  364. send_item(target, targetPort, data, GIVE_NEW_VOTE_URI);
  365. }
  366. string make_vote_string(
  367. const vector<Proof>& pi,
  368. const Twistpoint& shortTermPublicKey,
  369. const Scalar& threshold)
  370. {
  371. stringstream buffer;
  372. BinarySizeT sizeOfVector;
  373. sizeOfVector.set(pi.size());
  374. buffer << sizeOfVector;
  375. for (size_t i = 0; i < sizeOfVector.val(); i++)
  376. buffer << pi[i];
  377. buffer << shortTermPublicKey;
  378. buffer << threshold;
  379. return buffer.str();
  380. }
  381. string make_rep_proof_string(
  382. const vector<Proof>& pi,
  383. const Twistpoint& shortTermPublicKey,
  384. const Scalar& threshold)
  385. {
  386. stringstream buffer;
  387. BinarySizeT sizeOfVector;
  388. sizeOfVector.set(pi.size());
  389. buffer >> sizeOfVector;
  390. for (size_t i = 0; i < sizeOfVector.val(); i++)
  391. buffer << pi[i];
  392. buffer << shortTermPublicKey;
  393. buffer << threshold;
  394. return buffer.str();
  395. }
  396. void make_reputation_proof(
  397. default_random_engine& generator,
  398. const string& target,
  399. int targetPort,
  400. PrsonaClient* prsonaClient,
  401. const vector<string>& serverIPs,
  402. const vector<int>& serverPorts,
  403. size_t numClients)
  404. {
  405. vector<Proof> generatorProof;
  406. Twistpoint freshGenerator =
  407. get_generator(
  408. &generator,
  409. serverIPs,
  410. serverPorts,
  411. generatorProof,
  412. true);
  413. prsonaClient->receive_fresh_generator(
  414. generatorProof, freshGenerator);
  415. Twistpoint shortTermPublicKey =
  416. prsonaClient->get_short_term_public_key();
  417. vector<Proof> encryptedScoreProof;
  418. EGCiphertext encryptedScore =
  419. get_server_committed_val<EGCiphertext>(
  420. &generator,
  421. serverIPs,
  422. serverPorts,
  423. encryptedScoreProof,
  424. shortTermPublicKey,
  425. USER_TALLY_URI,
  426. USER_TALLY_COMMIT_URI);
  427. prsonaClient->receive_vote_tally(
  428. encryptedScoreProof,
  429. encryptedScore);
  430. Scalar threshold(0);
  431. vector<Proof> repProof =
  432. prsonaClient->generate_reputation_proof(
  433. threshold, numClients);
  434. string data =
  435. make_rep_proof_string(repProof, shortTermPublicKey, threshold);
  436. send_item(target, targetPort, data, REP_PROOF_URI);
  437. }
  438. int main(int argc, char *argv[])
  439. {
  440. initialize_prsona_classes();
  441. #if USE_SSL
  442. mg_init_library(0);
  443. #else
  444. mg_init_library(MG_FEATURES_SSL);
  445. #endif
  446. string id = "";
  447. if (argc > 1)
  448. id = argv[1];
  449. string seedStr;
  450. if (id.empty())
  451. seedStr = "default-client";
  452. else
  453. {
  454. seedStr = id;
  455. seedStr += "-client";
  456. }
  457. vector<string> serverIPs, clientIPs;
  458. vector<int> serverPorts, clientPorts;
  459. string selfIP, selfPortStr;
  460. int selfPort = 0;
  461. char buffer[46], *helper;
  462. ifstream serverConfig("cfg/serverIPs.cfg");
  463. while (!serverConfig.eof())
  464. {
  465. serverConfig.getline(buffer, 46);
  466. if (strlen(buffer) > 0)
  467. {
  468. helper = buffer;
  469. if (strchr(helper, ':'))
  470. {
  471. helper = strtok(helper, ":");
  472. serverIPs.push_back(string(helper));
  473. helper = strtok(NULL, ":");
  474. serverPorts.push_back(atoi(helper));
  475. }
  476. else
  477. {
  478. serverIPs.push_back(string(helper));
  479. serverPorts.push_back(atoi(PRSONA_PORT_STR));
  480. }
  481. }
  482. }
  483. ifstream clientConfig("cfg/clientIPs.cfg");
  484. while (!clientConfig.eof())
  485. {
  486. clientConfig.getline(buffer, 46);
  487. if (strlen(buffer) > 0)
  488. {
  489. helper = buffer;
  490. if (strchr(helper, ':'))
  491. {
  492. helper = strtok(helper, ":");
  493. clientIPs.push_back(string(helper));
  494. helper = strtok(NULL, ":");
  495. clientPorts.push_back(atoi(helper));
  496. }
  497. else
  498. {
  499. clientIPs.push_back(string(helper));
  500. clientPorts.push_back(atoi(PRSONA_PORT_STR));
  501. }
  502. }
  503. }
  504. string selfConfigFilename = "cfg/selfIP";
  505. if (!id.empty())
  506. {
  507. selfConfigFilename += "-";
  508. selfConfigFilename += id;
  509. }
  510. selfConfigFilename += ".cfg";
  511. ifstream selfConfig(selfConfigFilename);
  512. while (!selfConfig.eof())
  513. {
  514. selfConfig.getline(buffer, 46);
  515. if (strlen(buffer) > 0)
  516. {
  517. helper = buffer;
  518. if (strchr(helper, ':'))
  519. {
  520. helper = strtok(helper, ":");
  521. selfIP = helper;
  522. helper = strtok(NULL, ":");
  523. selfPortStr = helper;
  524. selfPort = atoi(helper);
  525. }
  526. else
  527. {
  528. selfIP = helper;
  529. selfPortStr = PRSONA_PORT_STR;
  530. selfPort = atoi(PRSONA_PORT_STR);
  531. }
  532. }
  533. }
  534. // Defaults
  535. size_t numServers = serverIPs.size();
  536. size_t numClients = clientIPs.size();
  537. bool maliciousServers = true;
  538. uniform_int_distribution<size_t> distribution(0, numServers - 1);
  539. const char *options[] = {"listening_ports", selfPortStr.c_str(), 0};
  540. if (argc > 2)
  541. {
  542. bool setting = argv[2][0] == 't' || argv[2][0] == 'T';
  543. maliciousServers = setting;
  544. }
  545. seed_seq seed(seedStr.begin(), seedStr.end());
  546. default_random_engine generator(seed);
  547. cout << "[" << seedStr << "] Establishing PRSONA client with the following parameters: " << endl;
  548. cout << "[" << seedStr << "] " << numServers << " PRSONA servers" << endl;
  549. cout << "[" << seedStr << "] " << numClients << " PRSONA clients" << endl;
  550. cout << "[" << seedStr << "] Servers are set to " << (maliciousServers ? "MALICIOUS" : "HBC") << " security" << endl;
  551. cout << "[" << seedStr << "] This client is at IP address: " << selfIP << ":" << selfPort << endl;
  552. cout << endl;
  553. // Set malicious flags where necessary
  554. if (maliciousServers)
  555. PrsonaBase::set_server_malicious();
  556. // Entities we operate with
  557. cout << "[" << seedStr << "] Creating PRSONA client." << endl;
  558. PrsonaClient *prsonaClient =
  559. create_client(&generator, serverIPs, serverPorts, numServers);
  560. CivetServer server(options);
  561. cout << "[" << seedStr << "] Setting up handlers for client." << endl;
  562. PrsonaClientWebSocketHandler wsHandler(prsonaClient, serverIPs, serverPorts, &generator);
  563. server.addWebSocketHandler("/ws", wsHandler);
  564. unique_lock<mutex> exitLock(exitSync.mtx);
  565. exitSync.val = 0;
  566. exitSync.val2 = 0;
  567. RemoteControlHandler exitHandler(&exitSync, "Client coming down!");
  568. server.addHandler(EXIT_URI, exitHandler);
  569. AltRemoteControlHandler triggerVoteHandler(CLIENT_MAKE_VOTE, &exitSync, "Client will make new votes!");
  570. server.addHandler(TRIGGER_VOTE_URI, triggerVoteHandler);
  571. AltRemoteControlHandler triggerRepHandler(CLIENT_MAKE_REP_PROOF, &exitSync, "Client will make new votes!");
  572. server.addHandler(TRIGGER_REP_URI, triggerRepHandler);
  573. cout << "[" << seedStr << "] Entering main ready loop." << endl;
  574. while (!exitSync.val)
  575. {
  576. while (!exitSync.val && !exitSync.val2)
  577. exitSync.cv.wait(exitLock);
  578. size_t whichServer = distribution(generator);
  579. string fullQuery, target;
  580. size_t colonLocation;
  581. int targetPort;
  582. switch (exitSync.val2)
  583. {
  584. case CLIENT_MAKE_VOTE:
  585. make_vote(
  586. generator,
  587. serverIPs[whichServer],
  588. serverPorts[whichServer],
  589. prsonaClient,
  590. serverIPs,
  591. serverPorts,
  592. numClients);
  593. break;
  594. case CLIENT_MAKE_REP_PROOF:
  595. fullQuery = triggerRepHandler.getQuery();
  596. colonLocation = fullQuery.find(":");
  597. target = fullQuery.substr(0, colonLocation);
  598. targetPort = stoi(fullQuery.substr(colonLocation + 1));
  599. make_reputation_proof(
  600. generator,
  601. target,
  602. targetPort,
  603. prsonaClient,
  604. serverIPs,
  605. serverPorts,
  606. numClients);
  607. break;
  608. default:
  609. break;
  610. }
  611. exitSync.val2 = 0;
  612. }
  613. mg_exit_library();
  614. delete prsonaClient;
  615. return 0;
  616. }