serverMain.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. #include <mutex>
  2. #include <condition_variable>
  3. #include <chrono>
  4. #include <iostream>
  5. #include <fstream>
  6. #include <cstring>
  7. #include <cstdlib>
  8. #include <vector>
  9. #include <string>
  10. #include "networkServer.hpp"
  11. #define EXIT_URI "/exit"
  12. #define BEGIN_URI "/begin"
  13. #define READY_URI "/ready"
  14. #define EPOCH_URI "/epoch"
  15. #define BGN_URI "/ws?p"
  16. #define GET_FRESH_GEN_URI "/ws?q"
  17. #define GIVE_FRESH_GEN_URI "/ws?r"
  18. #define GET_BLIND_GEN_URI "/ws?s"
  19. #define GIVE_BLIND_GEN_URI "/ws?t"
  20. #define EPOCH_BUILD_UP_URI "/ws?u"
  21. #define EPOCH_BREAK_DOWN_URI "/ws?v"
  22. #define GIVE_BLIND_GEN_URI "/ws?t"
  23. #define GET_DECRYPTION_URI "/ws?y"
  24. #define GIVE_DECRYPTION_URI "/ws?z"
  25. #define BGN_TMP_FILE "~/tmp/bgn"
  26. #define GEN_TMP_FILE "~/tmp/generator"
  27. #define EPOCH_GEN_TMP_FILE "~/tmp/epoch"
  28. using namespace std;
  29. struct synchronization_tool exitSync, bgnSync, generatorSync, readySync, updateSync, epochSync, tallySync;
  30. mutex updateMtx;
  31. size_t epochNum = 0;
  32. // Initialize the classes we use
  33. void initialize_prsona_classes()
  34. {
  35. Scalar::init();
  36. PrsonaBase::init();
  37. PrsonaBase::set_client_malicious();
  38. }
  39. PrsonaServer *create_server_from_bgn_file(size_t numServers)
  40. {
  41. unique_lock<mutex> lck(bgnSync.mtx);
  42. ifstream bgnFile(BGN_TMP_FILE);
  43. BGN privateKey;
  44. bgnFile >> privateKey;
  45. return new PrsonaServer(numServers, privateKey);
  46. }
  47. static int bgn_websocket_data_handler(
  48. struct mg_connection *conn,
  49. int bits,
  50. char *data,
  51. size_t data_len,
  52. void *user_data)
  53. {
  54. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE)
  55. return false;
  56. if ((bits & 0xf) != MG_WEBSOCKET_OPCODE_BINARY && (bits & 0xf) != MG_WEBSOCKET_OPCODE_CONTINUATION)
  57. {
  58. std::cerr << "Unknown opcode: failing." << std::endl;
  59. return false;
  60. }
  61. unique_lock<mutex> lck(bgnSync.mtx);
  62. FILE *currFile = fopen(BGN_TMP_FILE, "ab");
  63. fwrite(data, sizeof(char), data_len, currFile);
  64. fclose(currFile);
  65. return true;
  66. }
  67. static void bgn_websocket_close_handler(
  68. const struct mg_connection *conn,
  69. void *user_data)
  70. {
  71. unique_lock<mutex> lck(bgnSync.mtx);
  72. bgnSync.val = 1;
  73. bgnSync.cv.notify_all();
  74. }
  75. Twistpoint update_generator_from_gen_file(Proof& pi)
  76. {
  77. unique_lock<mutex> lck(generatorSync.mtx);
  78. ifstream genFile(GEN_TMP_FILE);
  79. Twistpoint retval;
  80. genFile >> pi;
  81. genFile >> retval;
  82. return retval;
  83. }
  84. Twistpoint update_data_from_epoch_gen_file(vector<Proof>& pi)
  85. {
  86. unique_lock<mutex> lck(epochSync.mtx);
  87. ifstream epochFile(EPOCH_GEN_TMP_FILE);
  88. Twistpoint retval;
  89. size_t piSize;
  90. pi.clear();
  91. epochFile >> piSize;
  92. for (size_t i = 0; i < piSize; i++)
  93. {
  94. Proof currProof;
  95. epochFile >> currProof;
  96. pi.push_back(currProof);
  97. }
  98. epochFile >> retval;
  99. return retval;
  100. }
  101. static int generator_websocket_data_handler(
  102. struct mg_connection *conn,
  103. int bits,
  104. char *data,
  105. size_t data_len,
  106. void *user_data)
  107. {
  108. struct synchronization_tool *synch = (struct synchronization_tool *) user_data;
  109. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE || (bits & 0xf) == MG_WEBSOCKET_OPCODE_DATACOMPLETE)
  110. return false;
  111. if ((bits & 0xf) != MG_WEBSOCKET_OPCODE_BINARY && (bits & 0xf) != MG_WEBSOCKET_OPCODE_CONTINUATION)
  112. {
  113. std::cerr << "Unknown opcode: failing." << std::endl;
  114. return false;
  115. }
  116. unique_lock<mutex> lck(generatorSync.mtx);
  117. FILE *currFile = fopen(GEN_TMP_FILE, "ab");
  118. fwrite(data, sizeof(char), data_len, currFile);
  119. fclose(currFile);
  120. return true;
  121. }
  122. static void generator_websocket_close_handler(
  123. const struct mg_connection *conn,
  124. void *user_data)
  125. {
  126. unique_lock<mutex> lck(generatorSync.mtx);
  127. generatorSync.val = 1;
  128. generatorSync.cv.notify_all();
  129. }
  130. static int epoch_websocket_data_handler(
  131. struct mg_connection *conn,
  132. int bits,
  133. char *data,
  134. size_t data_len,
  135. void *user_data)
  136. {
  137. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE)
  138. return false
  139. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_DATACOMPLETE)
  140. {
  141. unique_lock<mutex> lck(epochSync.mtx);
  142. epochSync.val++;
  143. return false;
  144. }
  145. if ((bits & 0xf) != MG_WEBSOCKET_OPCODE_BINARY && (bits & 0xf) != MG_WEBSOCKET_OPCODE_CONTINUATION)
  146. {
  147. std::cerr << "Unknown opcode: failing." << std::endl;
  148. return false;
  149. }
  150. unique_lock<mutex> lck(epochSync.mtx);
  151. FILE *currFile = fopen(EPOCH_GEN_TMP_FILE, "ab");
  152. fwrite(data, sizeof(char), data_len, currFile);
  153. fclose(currFile);
  154. return true;
  155. }
  156. static void epoch_websocket_close_handler(
  157. const struct mg_connection *conn,
  158. void *user_data)
  159. {
  160. unique_lock<mutex> lck(epochSync.mtx);
  161. epochSync.val2 = 0;
  162. epochSync.cv.notify_all();
  163. }
  164. static int tally_websocket_data_handler(
  165. struct mg_connection *conn,
  166. int bits,
  167. char *data,
  168. size_t data_len,
  169. void *user_data)
  170. {
  171. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE)
  172. return false;
  173. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_DATACOMPLETE)
  174. {
  175. unique_lock<mutex> lck(tallySync.mtx);
  176. tallySync.val++;
  177. tallySync.cv.notify_all();
  178. return false;
  179. }
  180. if ((bits & 0xf) != MG_WEBSOCKET_OPCODE_BINARY && (bits & 0xf) != MG_WEBSOCKET_OPCODE_CONTINUATION)
  181. {
  182. std::cerr << "Unknown opcode: failing." << std::endl;
  183. return false;
  184. }
  185. return true;
  186. }
  187. Twistpoint get_generator(
  188. vector<Proof>& pi,
  189. PrsonaServer *prsonaServer,
  190. const vector<string>& serverIPs,
  191. const string& selfIP,
  192. bool fresh)
  193. {
  194. Twistpoint retval = PrsonaServer::EL_GAMAL_GENERATOR;
  195. pi.clear();
  196. if (fresh)
  197. retval = prsonaServer->add_curr_seed_to_generator(pi, retval);
  198. else
  199. retval = prsonaServer->add_rand_seed_to_generator(pi, retval);
  200. for (size_t i = 0; i < serverIPs.size(); i++)
  201. {
  202. if (serverIPs[i] == selfIP)
  203. continue;
  204. char* which;
  205. if (fresh)
  206. which = GET_FRESH_GEN_URI;
  207. else
  208. which = GET_BLIND_GEN_URI;
  209. Proof currProof;
  210. struct mg_connection *conn =
  211. mg_connect_websocket_client(
  212. serverIPs[i].c_str(),
  213. PRSONA_PORT,
  214. USE_SSL,
  215. NULL,
  216. 0,
  217. which,
  218. "null",
  219. generator_websocket_data_handler,
  220. generator_websocket_close_handler,
  221. NULL);
  222. if (!conn)
  223. {
  224. cerr << "Couldn't get server " << i << "'s update on generator" << endl;
  225. return 1;
  226. }
  227. stringstream buffer;
  228. string data;
  229. buffer << retval;
  230. data = buffer.str();
  231. mg_websocket_client_write(
  232. conn,
  233. MG_WEBSOCKET_OPCODE_BINARY,
  234. data.c_str(),
  235. data.length());
  236. unique_lock<mutex> lck(generatorSync.mtx);
  237. remove(GEN_TMP_FILE);
  238. generatorSync.val = 0;
  239. mg_websocket_client_write(
  240. conn,
  241. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  242. "",
  243. 0);
  244. while (!generatorSync.val)
  245. generatorSync.cv.wait(lck);
  246. retval = update_generator_from_gen_file(currProof);
  247. pi.push_back(currProof);
  248. }
  249. return retval;
  250. }
  251. void handout_generator(
  252. const vector<Proof>& pi,
  253. const Twistpoint generator,
  254. PrsonaServer *prsonaServer,
  255. const vector<string> serverIPs,
  256. string selfIP,
  257. bool fresh)
  258. {
  259. if (fresh)
  260. prsonaServer->initialize_fresh_generator(pi, generator);
  261. else
  262. prsonaServer->set_EG_blind_generator(pi, generator);
  263. stringstream buffer;
  264. string data;
  265. buffer << pi.size();
  266. for (size_t i = 0; i < pi.size(); i++)
  267. buffer << pi[i];
  268. buffer << generator;
  269. data = buffer.str();
  270. for (size_t i = 0; i < serverIPs.size(); i++)
  271. {
  272. if (serverIPs[i] == selfIP)
  273. continue;
  274. char* which;
  275. if (fresh)
  276. which = GIVE_FRESH_GEN_URI;
  277. else
  278. which = GIVE_BLIND_GEN_URI;
  279. struct mg_connection *conn =
  280. mg_connect_websocket_client(
  281. serverIPs[i].c_str(),
  282. PRSONA_PORT,
  283. USE_SSL,
  284. NULL,
  285. 0,
  286. which,
  287. "null",
  288. empty_websocket_data_handler,
  289. empty_websocket_close_handler,
  290. NULL);
  291. if (!conn)
  292. {
  293. cerr << "Couldn't give " << (fresh ? "fresh" : "blind") << " generator to server " << i << endl;
  294. return 1;
  295. }
  296. mg_websocket_client_write(
  297. conn,
  298. MG_WEBSOCKET_OPCODE_BINARY,
  299. data.c_str(),
  300. data.length());
  301. mg_websocket_client_write(
  302. conn,
  303. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  304. "",
  305. 0);
  306. }
  307. }
  308. Twistpoint initiate_epoch_updates(
  309. const string& recipient,
  310. const string& data,
  311. vector<vector<Proof>>& generatorProofHolder,
  312. bool isBreakdown)
  313. {
  314. Twistpoint retval;
  315. struct synchronization_tool epochSync;
  316. bool flag = false;
  317. while (!flag)
  318. {
  319. char* which;
  320. if (isBreakdown)
  321. which = EPOCH_BREAK_DOWN_URI;
  322. else
  323. which = EPOCH_BUILD_UP_URI;
  324. struct mg_connection *conn =
  325. mg_connect_websocket_client(
  326. serverIPs[i].c_str(),
  327. PRSONA_PORT,
  328. USE_SSL,
  329. NULL,
  330. 0,
  331. which,
  332. "null",
  333. epoch_websocket_data_handler,
  334. epoch_websocket_close_handler,
  335. NULL);
  336. if (!conn)
  337. {
  338. std::cerr << "Trouble initiating epoch update with server at " << recipient << std::endl;
  339. continue;
  340. }
  341. unique_lock<mutex> lck(epochSync.mtx);
  342. remove(EPOCH_GEN_TMP_FILE);
  343. epochSync.val = 0;
  344. epochSync.val2 = 1;
  345. mg_websocket_client_write(
  346. conn,
  347. MG_WEBSOCKET_OPCODE_BINARY,
  348. data.c_str(),
  349. data.length());
  350. mg_websocket_client_write(
  351. conn,
  352. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  353. "",
  354. 0);
  355. while (epochSync.val2)
  356. epochSync.cv.wait(lck);
  357. if (!epochSync.val)
  358. flag = true;
  359. }
  360. if (isBreakdown)
  361. return retval;
  362. vector<Proof> generatorProof;
  363. generatorProofHolder.clear();
  364. retval = update_data_from_epoch_gen_file(generatorProof);
  365. generatorProofHolder.push_back(generatorProof);
  366. return retval;
  367. }
  368. vector<Proof> epoch_build_up(
  369. PrsonaServer *prsonaServer,
  370. const vector<string>& serverIPs,
  371. const string& selfIP,
  372. Twistpoint& nextGenerator)
  373. {
  374. std::vector<std::vector<std::vector<Proof>>> pi;
  375. std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
  376. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
  377. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
  378. std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
  379. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
  380. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
  381. std::vector<std::vector<Proof>> generatorProofHolder(1);
  382. for (size_t i = 0; i < serverIPs.size(); i++)
  383. {
  384. if (serverIPs[i] == selfIP)
  385. {
  386. pi.clear();
  387. permutationCommits.clear();
  388. freshPseudonymCommits.clear();
  389. freshPseudonymSeedCommits.clear();
  390. serverTallyCommits.clear();
  391. partwayVoteMatrixCommits.clear();
  392. finalVoteMatrixCommits.clear();
  393. pi.push_back(generatorProofHolder);
  394. prsonaServer->build_up_midway_pseudonyms(
  395. pi,
  396. permutationCommits,
  397. freshPseudonymCommits,
  398. freshPseudonymSeedCommits,
  399. serverTallyCommits,
  400. partwayVoteMatrixCommits,
  401. finalVoteMatrixCommits,
  402. nextGenerator);
  403. vector<vector<Twistpoint>> currUserTallyMaskCommits;
  404. vector<vector<Twistpoint>> currUserTallyMessageCommits;
  405. vector<vector<Twistpoint>> currUserTallySeedCommits;
  406. string data = make_epoch_update_string(
  407. pi[1],
  408. permutationCommits[0],
  409. freshPseudonymCommits[0],
  410. freshPseudonymSeedCommits[0],
  411. serverTallyCommits[0],
  412. partwayVoteMatrixCommits[0],
  413. finalVoteMatrixCommits[0],
  414. nextGenerator[0],
  415. currUserTallyMaskCommits,
  416. currUserTallyMessageCommits,
  417. currUserTallySeedCommits,
  418. nextGenerator,
  419. false);
  420. struct synchronization_tool epochSync;
  421. epochSync->val = 1;
  422. for (size_t j = 0; j < serverIPs.size(); j++)
  423. {
  424. if (i == j)
  425. continue;
  426. distribute_epoch_updates(
  427. serverIPs[j],
  428. data,
  429. &epochSync);
  430. }
  431. unique_lock<mutex> lck(epochSync);
  432. while (epochSync.val < serverIPs.size())
  433. epochSync.cv.wait(lck);
  434. generatorProofHolder = pi[0];
  435. }
  436. else
  437. {
  438. string data = make_epoch_initiator_string(
  439. generatorProofHolder[0],
  440. nextGenerator);
  441. nextGenerator = initiate_epoch_updates(
  442. serverIPs[j],
  443. data,
  444. generatorProofHolder,
  445. false);
  446. }
  447. }
  448. return generatorProofHolder[0];
  449. }
  450. void epoch_break_down(
  451. PrsonaServer *prsonaServer,
  452. const vector<string>& serverIPs,
  453. const string& selfIP,
  454. const vector<Proof>& generatorProof,
  455. const Twistpoint& nextGenerator)
  456. {
  457. std::vector<std::vector<std::vector<Proof>>> pi;
  458. std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
  459. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
  460. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
  461. std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
  462. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
  463. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
  464. std::vector<std::vector<std::vector<Twistpoint>>> userTallyMaskCommits;
  465. std::vector<std::vector<std::vector<Twistpoint>>> userTallyMessageCommits;
  466. std::vector<std::vector<std::vector<Twistpoint>>> userTallySeedCommits;
  467. for (size_t i = 0; i < serverIPs.size(); i++)
  468. {
  469. pi.clear();
  470. permutationCommits.clear();
  471. freshPseudonymCommits.clear();
  472. freshPseudonymSeedCommits.clear();
  473. serverTallyCommits.clear();
  474. partwayVoteMatrixCommits.clear();
  475. finalVoteMatrixCommits.clear();
  476. userTallyMaskCommits.clear();
  477. userTallyMessageCommits.clear();
  478. userTallySeedCommits.clear();
  479. if (serverIPs[i] == selfIP)
  480. {
  481. prsonaServer->break_down_midway_pseudonyms(
  482. generatorProof,
  483. pi,
  484. permutationCommits,
  485. freshPseudonymCommits,
  486. freshPseudonymSeedCommits,
  487. serverTallyCommits,
  488. partwayVoteMatrixCommits,
  489. finalVoteMatrixCommits,
  490. userTallyMaskCommits,
  491. userTallyMessageCommits,
  492. userTallySeedCommits,
  493. nextGenerator);
  494. string data = make_epoch_update_string(
  495. pi[0],
  496. permutationCommits[0],
  497. freshPseudonymCommits[0],
  498. freshPseudonymSeedCommits[0],
  499. serverTallyCommits[0],
  500. partwayVoteMatrixCommits[0],
  501. finalVoteMatrixCommits[0],
  502. nextGenerator[0],
  503. userTallyMaskCommits[0],
  504. userTallyMessageCommits[0],
  505. userTallySeedCommits[0],
  506. nextGenerator,
  507. true);
  508. struct synchronization_tool epochSync;
  509. epochSync->val = 1;
  510. for (size_t j = 0; j < serverIPs.size(); j++)
  511. {
  512. if (i == j)
  513. continue;
  514. distribute_epoch_updates(
  515. serverIPs[j],
  516. data,
  517. &epochSync);
  518. }
  519. unique_lock<mutex> lck(epochSync.mtx);
  520. while (epochSync.val < serverIPs.size())
  521. epochSync.cv.wait(lck);
  522. epochNum++;
  523. }
  524. else
  525. {
  526. vector<vector<Proof>> unused;
  527. string data = make_epoch_initiator_string(
  528. generatorProof,
  529. nextGenerator);
  530. initiate_epoch_updates(
  531. serverIPs[j],
  532. data,
  533. unused,
  534. true);
  535. }
  536. }
  537. }
  538. void tally_scores(
  539. PrsonaServer *prsonaServer,
  540. const vector<string>& serverIPs,
  541. const string& selfIP,
  542. const Twistpoint& nextGenerator,
  543. std::vector<EGCiphertext>& userTallyScores,
  544. std::vector<CurveBipoint>& serverTallyScores)
  545. {
  546. tallySync.val = 0;
  547. for (size_t i = 0; i < serverIPs.size(); i++)
  548. {
  549. if (serverIPs[i] == selfIP)
  550. {
  551. unique_lock<mutex> lck(tallySync.mtx);
  552. tallySync.val++;
  553. continue;
  554. }
  555. else
  556. {
  557. bool flag = false;
  558. while (!flag)
  559. {
  560. struct mg_connection *conn =
  561. mg_connect_websocket_client(
  562. serverIPs[i].c_str(),
  563. PRSONA_PORT,
  564. USE_SSL,
  565. NULL,
  566. 0,
  567. GET_DECRYPTION_URI,
  568. "null",
  569. tally_websocket_data_handler,
  570. empty_websocket_close_handler,
  571. NULL);
  572. if (!conn)
  573. {
  574. std::cerr << "Trouble initiating epoch update with server at " << recipient << std::endl;
  575. continue;
  576. }
  577. mg_websocket_client_write(
  578. conn,
  579. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  580. "",
  581. 0);
  582. }
  583. }
  584. }
  585. unique_lock<mutex> lck(tallySync.mtx)
  586. while (tallySync.val < serverIPs.size())
  587. tallySync.cv.wait(lck);
  588. std::vector<EGCiphertext> retval;
  589. std::vector<Scalar> decryptedTalliedScores = prsonaServer->tally_scores();
  590. mpz_class maxScorePossibleThisRound =
  591. prsonaServer->get_max_possible_score().toInt() *
  592. PrsonaBase::get_max_allowed_vote();
  593. mpz_class topOfScoreRange =
  594. decryptedTalliedScores.size() * PrsonaBase::get_max_allowed_vote();
  595. userTallyScores.clear();
  596. serverTallyScores.clear();
  597. for (size_t i = 0; i < decryptedTalliedScores.size(); i++)
  598. {
  599. decryptedTalliedScores[i] =
  600. Scalar(
  601. (decryptedTalliedScores[i].toInt() * topOfScoreRange) /
  602. maxScorePossibleThisRound
  603. );
  604. EGCiphertext currCiphertext;
  605. userTallyScores.push_back(currCiphertext);
  606. CurveBipoint currServerScore;
  607. serverTallyScores.push_back(currServerScore);
  608. Scalar currMask;
  609. currMask.set_random();
  610. // Give the server the new weights,
  611. // to get passed around to the other servers
  612. prsonaServer->bgnSystem.encrypt(
  613. serverTallyScores[i], decryptedTalliedScores[i]);
  614. userTallyScores[i].mask = prsonaServer->currentPseudonyms[i] * currMask;
  615. userTallyScores[i].encryptedMessage =
  616. (nextGenerator * currMask) +
  617. (prsonaServer->get_blinding_generator() * decryptedTalliedScores[i]);
  618. }
  619. }
  620. void distribute_tallied_scores(
  621. PrsonaServer *prsonaServer,
  622. const vector<string>& serverIPs,
  623. const string& selfIP,
  624. const Twistpoint& nextGenerator,
  625. const std::vector<EGCiphertext>& userTallyScores,
  626. const std::vector<CurveBipoint>& serverTallyScores)
  627. {
  628. stringstream buffer;
  629. string data;
  630. buffer << userTallyScores.size();
  631. for (size_t i = 0; i < userTallyScores.size(); i++)
  632. buffer << userTallyScores[i];
  633. for (size_t i = 0; i < serverTallyScores.size(); i++)
  634. buffer << serverTallyScores[i];
  635. data = buffer.str();
  636. tallySync.val = 0;
  637. for (size_t i = 0; i < serverIPs.size(); i++)
  638. {
  639. if (serverIPs[i] == selfIP)
  640. {
  641. prsonaServer->receive_tallied_scores(userTallyScores, serverTallyScores);
  642. unique_lock<mutex> lck(tallySync.mtx);
  643. tallySync.val++;
  644. continue;
  645. }
  646. else
  647. {
  648. bool flag = false;
  649. while (!flag)
  650. {
  651. struct mg_connection *conn =
  652. mg_connect_websocket_client(
  653. serverIPs[i].c_str(),
  654. PRSONA_PORT,
  655. USE_SSL,
  656. NULL,
  657. 0,
  658. GIVE_DECRYPTION_URI,
  659. "null",
  660. tally_websocket_data_handler,
  661. empty_websocket_close_handler,
  662. NULL);
  663. if (!conn)
  664. {
  665. std::cerr << "Trouble initiating epoch update with server at " << recipient << std::endl;
  666. continue;
  667. }
  668. mg_websocket_client_write(
  669. conn,
  670. MG_WEBSOCKET_OPCODE_BINARY,
  671. data.c_str(),
  672. data.length());
  673. mg_websocket_client_write(
  674. conn,
  675. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  676. "",
  677. 0);
  678. }
  679. }
  680. }
  681. unique_lock<mutex> lck(tallySync.mtx)
  682. while (tallySync.val < serverIPs.size())
  683. tallySync.cv.wait(lck);
  684. }
  685. void epoch(
  686. PrsonaServer *prsonaServer,
  687. const vector<string>& serverIPs,
  688. const string& selfIP)
  689. {
  690. Twistpoint nextGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
  691. unique_lock<mutex> lck(updateMtx, defer_lock);
  692. obtain_update_locks(
  693. lck,
  694. serverIPs,
  695. selfIP,
  696. updateSync);
  697. vector<Proof> generatorProof =
  698. epoch_build_up(
  699. prsonaServer,
  700. serverIPs,
  701. selfIP,
  702. nextGenerator);
  703. std::vector<EGCiphertext> currentUserEncryptedTallies;
  704. std::vector<CurveBipoint> currentServerEncryptedTallies;
  705. tally_scores(
  706. prsonaServer,
  707. serverIPs,
  708. selfIP,
  709. nextGenerator,
  710. currentUserEncryptedTallies,
  711. currentServerEncryptedTallies);
  712. distribute_tallied_scores(
  713. prsonaServer,
  714. serverIPs,
  715. selfIP,
  716. nextGenerator,
  717. currentUserEncryptedTallies,
  718. currentServerEncryptedTallies);
  719. epoch_break_down(
  720. prsonaServer,
  721. serverIPs,
  722. selfIP,
  723. generatorProof,
  724. nextGenerator);
  725. release_update_locks(
  726. lck,
  727. serverIPs,
  728. selfIP,
  729. updateSync);
  730. }
  731. class ExitHandler : public CivetHandler
  732. {
  733. public:
  734. bool handleGet(CivetServer *server, struct mg_connection *conn)
  735. {
  736. unique_lock<mutex> lck(exitSync.mtx);
  737. mg_printf(conn,
  738. "HTTP/1.1 200 OK\r\nContent-Type: "
  739. "text/plain\r\nConnection: close\r\n\r\n");
  740. mg_printf(conn, "Server coming down!\n");
  741. exitSync.val = 1;
  742. exitSync.cv.notify_all();
  743. return true;
  744. }
  745. };
  746. class BeginHandler : public CivetHandler
  747. {
  748. public:
  749. bool handleGet(CivetServer *server, struct mg_connection *conn)
  750. {
  751. unique_lock<mutex> lck(exitSync.mtx);
  752. mg_printf(conn,
  753. "HTTP/1.1 200 OK\r\nContent-Type: "
  754. "text/plain\r\nConnection: close\r\n\r\n");
  755. mg_printf(conn, "Server will begin periodically initiating epochs!\n");
  756. exitSync.val2 = 1;
  757. exitSync.cv.notify_all();
  758. return true;
  759. }
  760. };
  761. class ReadyHandler : public CivetHandler
  762. {
  763. public:
  764. bool handleGet(CivetServer *server, struct mg_connection *conn)
  765. {
  766. unique_lock<mutex> lck(readySync.mtx);
  767. mg_printf(conn,
  768. "HTTP/1.1 200 OK\r\nContent-Type: "
  769. "text/plain\r\nConnection: close\r\n\r\n");
  770. mg_printf(conn, "ACK\n");
  771. readySync.val++;
  772. readySync.cv.notify_all();
  773. return true;
  774. }
  775. };
  776. class EpochHandler : public CivetHandler
  777. {
  778. public:
  779. bool handleGet(CivetServer *server, struct mg_connection *conn)
  780. {
  781. mg_printf(conn,
  782. "HTTP/1.1 200 OK\r\nContent-Type: "
  783. "text/plain\r\nConnection: close\r\n\r\n");
  784. mg_printf(conn, "%lu\n", epochNum);
  785. return true;
  786. }
  787. };
  788. int main(int argc, char *argv[])
  789. {
  790. initialize_prsona_classes();
  791. #if USE_SSL
  792. mg_init_library(0);
  793. #else
  794. mg_init_library(MG_FEATURES_SSL);
  795. #endif
  796. const char *options[] = {"listening_ports", PRSONA_PORT, 0};
  797. vector<string> serverIPs;
  798. string selfIP, dealerIP;
  799. char buffer[40];
  800. ifstream serverConfig("serverIPs.cfg");
  801. while (!serverConfig.eof())
  802. {
  803. serverConfig.getline(buffer, 40);
  804. if (strlen(buffer) > 0)
  805. serverIPs.push_back(string(buffer));
  806. }
  807. ifstream selfConfig("selfIP.cfg");
  808. while (!selfConfig.eof())
  809. {
  810. selfConfig.getline(buffer, 40);
  811. if (strlen(buffer) > 0)
  812. selfIP = buffer;
  813. }
  814. ifstream dealerConfig("dealerIP.cfg");
  815. while (!dealerConfig.eof())
  816. {
  817. dealerConfig.getline(buffer, 40);
  818. if (strlen(buffer) > 0)
  819. dealerIP = buffer;
  820. }
  821. // Defaults
  822. size_t numServers = serverIPs.size();
  823. bool bgnDealer = selfIP == dealerIP;
  824. size_t timeToEpoch = 600;
  825. bool maliciousServers = true;
  826. if (argc > 1)
  827. timeToEpoch = atoi(argv[1]);
  828. if (argc > 2)
  829. {
  830. bool setting = argv[2][0] == 't' || argv[2][0] == 'T';
  831. maliciousServers = setting;
  832. }
  833. cout << "Establishing PRSONA server with the following parameters: " << endl;
  834. cout << numServers << " PRSONA servers" << endl;
  835. if (bgnDealer)
  836. {
  837. cout << "This server IS the trusted BGN dealer" << endl;
  838. cout << "The time between epochs is " << timeToEpoch << " seconds" << endl;
  839. }
  840. else
  841. {
  842. cout << "This server is NOT the trusted BGN dealer" << endl;
  843. }
  844. cout << "Servers are set to " << (maliciousServers ? "MALICIOUS" : "HBC") << " security" << endl;
  845. cout << "This server is at IP address: " << selfIP << endl;
  846. cout << "The BGN dealer is at IP address: " << dealerIP << endl;
  847. cout << endl;
  848. // Set malicious flags where necessary
  849. if (maliciousServers)
  850. PrsonaBase::set_server_malicious();
  851. // Entities we operate with
  852. PrsonaServer *prsonaServer;
  853. if (bgnDealer)
  854. prsonaServer = new PrsonaServer(numServers);
  855. else
  856. {
  857. struct mg_connection *conn =
  858. mg_connect_websocket_client(
  859. dealerIP.c_str(),
  860. PRSONA_PORT,
  861. USE_SSL,
  862. NULL,
  863. 0,
  864. BGN_URI,
  865. "null",
  866. bgn_websocket_data_handler,
  867. bgn_websocket_close_handler,
  868. NULL);
  869. if (!conn)
  870. {
  871. cerr << "Couldn't obtain BGN details" << endl;
  872. return 1;
  873. }
  874. unique_lock<mutex> lck(bgnSync.mtx);
  875. remove(BGN_TMP_FILE);
  876. bgnSync.val = 0;
  877. mg_websocket_client_write(
  878. conn,
  879. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  880. "",
  881. 0);
  882. while (!bgnSync.val)
  883. bgnSync.cv.wait(lck);
  884. prsonaServer = create_server_from_bgn_file(numServers);
  885. }
  886. CivetServer server(options);
  887. PrsonaServerWebSocketHandler wsHandler(prsonaServer, &updateMtx, &epochNum, serverIPs, selfIP);
  888. server.addWebSocketHandler("/ws", wsHandler);
  889. ReadyHandler readyHandler;
  890. server.addHandler(READY_URI, readyHandler);
  891. if (bgnDealer)
  892. {
  893. unique_lock<mutex> lck(readySync.mtx);
  894. readySync.val++;
  895. while (readySync.val < numServers)
  896. readySync.cv.wait(lck);
  897. vector<Proof> pi;
  898. Twistpoint freshGenerator =
  899. get_generator(pi, prsonaServer, serverIPs, true);
  900. handout_generator(pi, freshGenerator, prsonaServer, serverIPs, true);
  901. Twistpoint blindGenerator =
  902. get_generator(pi, prsonaServer, serverIPs, false);
  903. handout_generator(pi, freshGenerator, prsonaServer, serverIPs, false);
  904. }
  905. else
  906. {
  907. stringstream sysString;
  908. string data;
  909. struct mg_connection *conn =
  910. mg_connect_client(
  911. dealerIP,
  912. PRSONA_PORT,
  913. USE_SSL,
  914. NULL,
  915. 0);
  916. sysString << "GET " << READY_URI << " HTTP/1.1\r\n";
  917. sysString << "Host: " << dealerIP << "\r\n\r\n";
  918. data = sysString.str();
  919. mg_write(conn, data.c_str(), data.length());
  920. mg_close_connection(conn);
  921. }
  922. ExitHandler exitHandler;
  923. server.addHandler(EXIT_URI, exitHandler);
  924. if (bgnDealer)
  925. {
  926. BeginHandler beginHandler;
  927. server.addHandler(BEGIN_URI, beginHandler);
  928. unique_lock<mutex> lck(exitSync.mtx);
  929. while (!exitSync.val && !exitSync.val2)
  930. exitSync.cv.wait(lck);
  931. while (!exitSync.val)
  932. {
  933. epoch(prsonaServer);
  934. exitSync.cv.waitFor(lck, chrono::seconds(timeToEpoch));
  935. }
  936. }
  937. else
  938. {
  939. unique_lock<mutex> lck(exitSync.mtx);
  940. while (!exitSync.val)
  941. exitSync.cv.wait(lck)
  942. }
  943. mg_exit_library();
  944. delete prsonaServer;
  945. if (bgnDealer)
  946. {
  947. for (size_t i = 0; i < serverIPs.size(); i++)
  948. {
  949. if (serverIPs[i] == selfIP)
  950. continue;
  951. stringstream sysString;
  952. string data;
  953. struct mg_connection *conn =
  954. mg_connect_client(
  955. serverIPs[i],
  956. PRSONA_PORT,
  957. USE_SSL,
  958. NULL,
  959. 0);
  960. sysString << "GET " << EXIT_URI << " HTTP/1.1\r\n";
  961. sysString << "Host: " << serverIPs[i] << "\r\n\r\n";
  962. data = sysString.str();
  963. mg_write(conn, data.c_str(), data.length());
  964. mg_close_connection(conn);
  965. }
  966. }
  967. return 0;
  968. }