serverEntity.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. #include <iostream>
  2. #include "serverEntity.hpp"
  3. /********************
  4. * PUBLIC FUNCTIONS *
  5. ********************/
  6. /*
  7. * CONSTRUCTORS
  8. */
  9. PrsonaServerEntity::PrsonaServerEntity(size_t numServers)
  10. {
  11. if (numServers < 1)
  12. {
  13. std::cerr << "You have to have at least 1 server. "
  14. << "I'm making it anyways." << std::endl;
  15. }
  16. // Make the first server, which makes the BGN parameters
  17. PrsonaServer firstServer(numServers);
  18. servers.push_back(firstServer);
  19. // Make the rest of the servers, which take the BGN parameters
  20. const BGN& sharedBGN = firstServer.get_bgn_details();
  21. for (size_t i = 1; i < numServers; i++)
  22. servers.push_back(PrsonaServer(numServers, sharedBGN));
  23. // After all servers have made their seeds,
  24. // make sure they have the initial fresh generator
  25. std::vector<Proof> pi;
  26. Curvepoint firstGenerator = get_fresh_generator(pi);
  27. for (size_t i = 0; i < numServers; i++)
  28. servers[i].initialize_fresh_generator(pi, firstGenerator);
  29. pi.clear();
  30. // It's important that no server knows the DLOG between g and h for ElGamal,
  31. // so have each server collaborate to make h.
  32. Curvepoint blindGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
  33. for (size_t i = 0; i < numServers; i++)
  34. {
  35. blindGenerator =
  36. servers[i].add_rand_seed_to_generator(pi, blindGenerator);
  37. }
  38. for (size_t i = 0; i < numServers; i++)
  39. servers[i].set_EG_blind_generator(pi, blindGenerator);
  40. }
  41. /*
  42. * BASIC PUBLIC SYSTEM INFO GETTERS
  43. */
  44. BGNPublicKey PrsonaServerEntity::get_bgn_public_key() const
  45. {
  46. return get_bgn_public_key(0);
  47. }
  48. BGNPublicKey PrsonaServerEntity::get_bgn_public_key(size_t which) const
  49. {
  50. return servers[which].get_bgn_public_key();
  51. }
  52. Curvepoint PrsonaServerEntity::get_blinding_generator() const
  53. {
  54. return get_blinding_generator(0);
  55. }
  56. Curvepoint PrsonaServerEntity::get_blinding_generator(size_t which) const
  57. {
  58. std::vector<Proof> pi;
  59. Curvepoint retval = get_blinding_generator(pi, which);
  60. if (!servers[which].verify_generator_proof(
  61. pi, retval, servers[which].get_num_servers()))
  62. {
  63. std::cerr << "Error making the generator, aborting." << std::endl;
  64. return Curvepoint();
  65. }
  66. return retval;
  67. }
  68. Curvepoint PrsonaServerEntity::get_blinding_generator(
  69. std::vector<Proof>& pi) const
  70. {
  71. return get_blinding_generator(pi, 0);
  72. }
  73. Curvepoint PrsonaServerEntity::get_blinding_generator(
  74. std::vector<Proof>& pi, size_t which) const
  75. {
  76. return servers[which].get_blinding_generator(pi);
  77. }
  78. Curvepoint PrsonaServerEntity::get_fresh_generator() const
  79. {
  80. return get_fresh_generator(0);
  81. }
  82. Curvepoint PrsonaServerEntity::get_fresh_generator(size_t which) const
  83. {
  84. std::vector<Proof> pi;
  85. Curvepoint retval = get_fresh_generator(pi, which);
  86. if (!servers[which].verify_generator_proof(
  87. pi, retval, servers[which].get_num_servers()))
  88. {
  89. std::cerr << "Error making the generator, aborting." << std::endl;
  90. return Curvepoint();
  91. }
  92. return retval;
  93. }
  94. Curvepoint PrsonaServerEntity::get_fresh_generator(
  95. std::vector<Proof>& pi) const
  96. {
  97. return get_fresh_generator(pi, 0);
  98. }
  99. Curvepoint PrsonaServerEntity::get_fresh_generator(
  100. std::vector<Proof>& pi, size_t which) const
  101. {
  102. Curvepoint retval = PrsonaServer::EL_GAMAL_GENERATOR;
  103. pi.clear();
  104. for (size_t j = 0; j < servers[which].get_num_servers(); j++)
  105. {
  106. size_t index = (which + j) % servers[which].get_num_servers();
  107. retval = servers[index].add_curr_seed_to_generator(pi, retval);
  108. }
  109. return retval;
  110. }
  111. size_t PrsonaServerEntity::get_num_clients() const
  112. {
  113. return get_num_clients(0);
  114. }
  115. size_t PrsonaServerEntity::get_num_clients(size_t which) const
  116. {
  117. return servers[which].get_num_clients();
  118. }
  119. size_t PrsonaServerEntity::get_num_servers() const
  120. {
  121. return get_num_servers(0);
  122. }
  123. size_t PrsonaServerEntity::get_num_servers(size_t which) const
  124. {
  125. return servers[which].get_num_servers();
  126. }
  127. /*
  128. * ENCRYPTED DATA GETTERS
  129. */
  130. std::vector<CurveBipoint> PrsonaServerEntity::get_current_votes_by(
  131. Proof& pi, const Curvepoint& shortTermPublicKey) const
  132. {
  133. return get_current_votes_by(pi, shortTermPublicKey, 0);
  134. }
  135. /* Call this in order to get the current encrypted votes cast by a given user
  136. * (who is identified by their short term public key).
  137. * In practice, this is intended for clients,
  138. * who need to know their current votes in order to rerandomize them. */
  139. std::vector<CurveBipoint> PrsonaServerEntity::get_current_votes_by(
  140. Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const
  141. {
  142. return servers[which].get_current_votes_by(pi, shortTermPublicKey);
  143. }
  144. EGCiphertext PrsonaServerEntity::get_current_tally(
  145. Proof& pi, const Curvepoint& shortTermPublicKey) const
  146. {
  147. return get_current_tally(pi, shortTermPublicKey, 0);
  148. }
  149. /* Call this in order to get the current encrypted tally of a given user
  150. * (who is identified by their short term public key).
  151. * In practice, this is intended for clients, so that the servers vouch
  152. * for their ciphertexts being valid as part of their reputation proofs. */
  153. EGCiphertext PrsonaServerEntity::get_current_tally(
  154. Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const
  155. {
  156. return servers[which].get_current_tally(pi, shortTermPublicKey);
  157. }
  158. /*
  159. * CLIENT INTERACTIONS
  160. */
  161. void PrsonaServerEntity::add_new_client(PrsonaClient& newUser)
  162. {
  163. add_new_client(newUser, 0);
  164. }
  165. /* Add a new client (who is identified only by their short term public key)
  166. * One server does the main work, then other servers import their (proven)
  167. * exported data. */
  168. void PrsonaServerEntity::add_new_client(PrsonaClient& newUser, size_t which)
  169. {
  170. Proof proofOfValidSTPK, proofOfCorrectAddition, proofOfValidVotes;
  171. std::vector<Proof> proofOfValidGenerator;
  172. Curvepoint freshGenerator =
  173. get_fresh_generator(proofOfValidGenerator, which);
  174. // Users can't actually announce a short term public key
  175. // if they don't know the fresh generator.
  176. newUser.receive_fresh_generator(proofOfValidGenerator, freshGenerator);
  177. Curvepoint shortTermPublicKey = newUser.get_short_term_public_key(
  178. proofOfValidSTPK);
  179. // Do the actual work of adding the client to the first server
  180. servers[which].add_new_client(
  181. proofOfValidSTPK, proofOfCorrectAddition, shortTermPublicKey);
  182. // Then, export the data to the rest of the servers
  183. std::vector<TwistBipoint> previousVoteTally;
  184. std::vector<Curvepoint> currentPseudonyms;
  185. std::vector<EGCiphertext> currentUserEncryptedTallies;
  186. std::vector<Proof> currentTallyProofs;
  187. std::vector<std::vector<CurveBipoint>> voteMatrix;
  188. servers[which].export_updates(
  189. previousVoteTally,
  190. currentPseudonyms,
  191. currentUserEncryptedTallies,
  192. currentTallyProofs,
  193. voteMatrix);
  194. for (size_t j = 1; j < servers[which].get_num_servers(); j++)
  195. {
  196. size_t index = (which + j) % servers[which].get_num_servers();
  197. servers[index].import_updates(
  198. proofOfCorrectAddition,
  199. previousVoteTally,
  200. currentPseudonyms,
  201. currentUserEncryptedTallies,
  202. currentTallyProofs,
  203. voteMatrix);
  204. }
  205. // Finally, give the user the information it needs
  206. // about its current tally and votes
  207. transmit_updates(newUser, which);
  208. }
  209. // Receive a new vote row from a user (identified by short term public key).
  210. bool PrsonaServerEntity::receive_vote(
  211. const std::vector<Proof>& pi,
  212. const std::vector<CurveBipoint>& newVotes,
  213. const Curvepoint& shortTermPublicKey)
  214. {
  215. return receive_vote(pi, newVotes, shortTermPublicKey, 0);
  216. }
  217. bool PrsonaServerEntity::receive_vote(
  218. const std::vector<Proof>& pi,
  219. const std::vector<CurveBipoint>& newVotes,
  220. const Curvepoint& shortTermPublicKey,
  221. size_t which)
  222. {
  223. bool retval = true;
  224. for (size_t i = 0; i < servers[which].get_num_servers(); i++)
  225. {
  226. size_t index = (i + which) % servers[which].get_num_servers();
  227. retval = retval &&
  228. servers[index].receive_vote(pi, newVotes, shortTermPublicKey);
  229. }
  230. return retval;
  231. }
  232. void PrsonaServerEntity::transmit_updates(PrsonaClient& currUser) const
  233. {
  234. transmit_updates(currUser, 0);
  235. }
  236. // After tallying scores and new vote matrix,
  237. // give those to a user for the new epoch
  238. void PrsonaServerEntity::transmit_updates(
  239. PrsonaClient& currUser, size_t which) const
  240. {
  241. Proof proofOfValidSTPK, proofOfScore, proofOfCorrectVotes;
  242. std::vector<Proof> proofOfValidGenerator;
  243. Curvepoint freshGenerator =
  244. get_fresh_generator(proofOfValidGenerator, which);
  245. // Get users the next fresh generator so they can correctly
  246. // ask for their new scores and vote row
  247. currUser.receive_fresh_generator(proofOfValidGenerator, freshGenerator);
  248. Curvepoint shortTermPublicKey =
  249. currUser.get_short_term_public_key(proofOfValidSTPK);
  250. EGCiphertext score =
  251. get_current_tally(proofOfScore, shortTermPublicKey, which);
  252. currUser.receive_vote_tally(proofOfScore, score);
  253. }
  254. /*
  255. * EPOCH
  256. */
  257. void PrsonaServerEntity::epoch(Proof& pi)
  258. {
  259. epoch(pi, 0);
  260. }
  261. // Do the epoch process
  262. void PrsonaServerEntity::epoch(Proof& pi, size_t which)
  263. {
  264. Curvepoint nextGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
  265. std::vector<TwistBipoint> previousVoteTally;
  266. std::vector<Curvepoint> currentPseudonyms;
  267. std::vector<EGCiphertext> currentUserEncryptedTallies;
  268. std::vector<Proof> currentTallyProofs;
  269. std::vector<std::vector<CurveBipoint>> voteMatrix;
  270. // go from A_0 to A_0.5
  271. for (size_t i = 0; i < servers[which].get_num_servers(); i++)
  272. {
  273. size_t index = (which + i) % servers[which].get_num_servers();
  274. size_t nextIndex = (which + i + 1) % servers[which].get_num_servers();
  275. servers[index].build_up_midway_pseudonyms(pi, nextGenerator);
  276. servers[index].export_updates(
  277. previousVoteTally,
  278. currentPseudonyms,
  279. currentUserEncryptedTallies,
  280. currentTallyProofs,
  281. voteMatrix);
  282. servers[nextIndex].import_updates(
  283. pi,
  284. previousVoteTally,
  285. currentPseudonyms,
  286. currentUserEncryptedTallies,
  287. currentTallyProofs,
  288. voteMatrix);
  289. }
  290. /* Imagine that server 0 is encrypting these, then would do a ZKP that it
  291. * knows a secret mask and encrypted the correct value everyone else already
  292. * knows. Everyone else then adds a mask and proves they added a secret mask
  293. * to the committed values. */
  294. currentUserEncryptedTallies =
  295. tally_scores(currentTallyProofs, nextGenerator, which);
  296. // go from A_0.5 to A_1
  297. for (size_t i = 0; i < servers[which].get_num_servers(); i++)
  298. {
  299. size_t index = (which + i) % servers[which].get_num_servers();
  300. size_t nextIndex = (which + i + 1) % servers[which].get_num_servers();
  301. servers[index].break_down_midway_pseudonyms(pi, nextGenerator);
  302. servers[index].export_updates(
  303. previousVoteTally,
  304. currentPseudonyms,
  305. currentUserEncryptedTallies,
  306. currentTallyProofs,
  307. voteMatrix);
  308. servers[nextIndex].import_updates(
  309. pi,
  310. previousVoteTally,
  311. currentPseudonyms,
  312. currentUserEncryptedTallies,
  313. currentTallyProofs,
  314. voteMatrix);
  315. }
  316. // At the end, make sure all servers have same information
  317. for (size_t i = 1; i < servers[which].get_num_servers() - 1; i++)
  318. {
  319. size_t index = (which + i) % servers[which].get_num_servers();
  320. servers[index].import_updates(
  321. pi,
  322. previousVoteTally,
  323. currentPseudonyms,
  324. currentUserEncryptedTallies,
  325. currentTallyProofs,
  326. voteMatrix);
  327. }
  328. }
  329. /*********************
  330. * PRIVATE FUNCTIONS *
  331. *********************/
  332. /*
  333. * SCORE TALLYING
  334. */
  335. /* Calculate scores, then scale the values appropriately,
  336. * so they are in the correct range to be used as vote weights.
  337. *
  338. * We're treating it as if we are one server, so that server gets the updated
  339. * weights to be sent to all other servers for the next epoch. */
  340. std::vector<EGCiphertext> PrsonaServerEntity::tally_scores(
  341. std::vector<Proof>& tallyProofs,
  342. const Curvepoint& nextGenerator,
  343. size_t which)
  344. {
  345. std::vector<EGCiphertext> retval;
  346. Proof maxScoreProof;
  347. std::vector<Scalar> decryptedTalliedScores = servers[which].tally_scores(
  348. tallyProofs);
  349. mpz_class maxScorePossibleThisRound =
  350. servers[which].get_max_possible_score(maxScoreProof).toInt() *
  351. PrsonaBase::get_max_allowed_vote();
  352. mpz_class topOfScoreRange =
  353. decryptedTalliedScores.size() * PrsonaBase::get_max_allowed_vote();
  354. for (size_t i = 0; i < decryptedTalliedScores.size(); i++)
  355. {
  356. decryptedTalliedScores[i] =
  357. Scalar(
  358. (decryptedTalliedScores[i].toInt() * topOfScoreRange) /
  359. maxScorePossibleThisRound
  360. );
  361. EGCiphertext currCiphertext;
  362. retval.push_back(currCiphertext);
  363. Scalar currMask;
  364. currMask.set_random();
  365. // Give the server the new weights,
  366. // to get passed around to the other servers
  367. servers[which].bgnSystem.encrypt(
  368. servers[which].previousVoteTallies[i], decryptedTalliedScores[i]);
  369. retval[i].mask = servers[which].currentPseudonyms[i] * currMask;
  370. retval[i].encryptedMessage =
  371. (nextGenerator * currMask) +
  372. (servers[which].get_blinding_generator() * decryptedTalliedScores[i]);
  373. }
  374. servers[which].currentUserEncryptedTallies = retval;
  375. servers[which].currentTallyProofs = tallyProofs;
  376. return retval;
  377. }
  378. /*
  379. * BINARY SEARCH
  380. */
  381. // Completely normal binary search
  382. size_t PrsonaServerEntity::binary_search(
  383. const Curvepoint& shortTermPublicKey, size_t which) const
  384. {
  385. return servers[which].binary_search(shortTermPublicKey);
  386. }