serverMain.cpp 31 KB

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