server.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #include <iostream>
  2. #include "server.hpp"
  3. extern const curvepoint_fp_t bn_curvegen;
  4. extern const scalar_t bn_n;
  5. // This needs to be here so it's "defined", but it doesn't always seem to actually, uh, execute, so you do it over in the constructor
  6. Curvepoint PrsonaServer::elGamalGenerator = Curvepoint();
  7. Scalar PrsonaServer::scalarN = Scalar();
  8. Scalar PrsonaServer::defaultTally = Scalar();
  9. Scalar PrsonaServer::defaultVote = Scalar();
  10. bool PrsonaServer::malicious_server = false;
  11. bool PrsonaServer::malicious_client = false;
  12. PrsonaServer::PrsonaServer()
  13. {
  14. elGamalGenerator = Curvepoint(bn_curvegen);
  15. scalarN = Scalar(bn_n);
  16. defaultTally = Scalar(0);
  17. defaultVote = Scalar(0);
  18. Scalar lambda;
  19. lambda.set_random();
  20. elGamalBlindGenerator = elGamalGenerator * lambda;
  21. currentSeed.set_random();
  22. }
  23. PrsonaServer::PrsonaServer(const BGN& other_bgn, const Curvepoint& other_blind_gen)
  24. : bgn_system(other_bgn), elGamalBlindGenerator(other_blind_gen)
  25. {
  26. currentSeed.set_random();
  27. }
  28. void PrsonaServer::set_malicious_server()
  29. {
  30. malicious_server = true;
  31. }
  32. void PrsonaServer::set_malicious_client()
  33. {
  34. malicious_client = true;
  35. }
  36. BGNPublicKey PrsonaServer::get_bgn_public_key() const
  37. {
  38. return bgn_system.get_public_key();
  39. }
  40. Curvepoint PrsonaServer::get_blinding_generator() const
  41. {
  42. return elGamalBlindGenerator;
  43. }
  44. Curvepoint PrsonaServer::add_seed_to_generator(Proof& pi, const Curvepoint& currGenerator) const
  45. {
  46. pi = generate_valid_fresh_generator_proof(pi);
  47. return currGenerator * currentSeed;
  48. }
  49. Curvepoint PrsonaServer::add_next_seed_to_generator(Proof& pi, const Curvepoint& currGenerator) const
  50. {
  51. pi = generate_valid_fresh_generator_proof(pi);
  52. return currGenerator * nextSeed;
  53. }
  54. std::vector<CurveBipoint> PrsonaServer::get_current_votes_by(Proof& pi, const Curvepoint& shortTermPublicKey) const
  55. {
  56. std::vector<CurveBipoint> retval;
  57. size_t voteSubmitter = binary_search(shortTermPublicKey);
  58. retval = voteMatrix[voteSubmitter];
  59. pi = generate_votes_valid_proof(retval, shortTermPublicKey);
  60. return retval;
  61. }
  62. void PrsonaServer::add_new_client(const Proof& proofOfValidKey, Proof& proofOfValidAddition, const Curvepoint& shortTermPublicKey)
  63. {
  64. if (!verify_valid_key_proof(proofOfValidKey, shortTermPublicKey))
  65. {
  66. std::cerr << "Could not verify proof of valid key." << std::endl;
  67. return;
  68. }
  69. currentPseudonyms.push_back(shortTermPublicKey);
  70. TwistBipoint newTalliedVote;
  71. bgn_system.encrypt(newTalliedVote, defaultTally);
  72. previousVoteTally.push_back(newTalliedVote);
  73. CurveBipoint encryptedDefaultVote;
  74. bgn_system.encrypt(encryptedDefaultVote, defaultVote);
  75. std::vector<CurveBipoint> newRow;
  76. for (size_t i = 0; i < voteMatrix.size(); i++)
  77. {
  78. encryptedDefaultVote = bgn_system.rerandomize(encryptedDefaultVote);
  79. voteMatrix[i].push_back(encryptedDefaultVote);
  80. encryptedDefaultVote = bgn_system.rerandomize(encryptedDefaultVote);
  81. newRow.push_back(encryptedDefaultVote);
  82. }
  83. encryptedDefaultVote = bgn_system.rerandomize(encryptedDefaultVote);
  84. newRow.push_back(encryptedDefaultVote);
  85. voteMatrix.push_back(newRow);
  86. order_data();
  87. proofOfValidAddition = generate_proof_of_added_user(shortTermPublicKey);
  88. }
  89. void PrsonaServer::receive_vote(const Proof& pi, const std::vector<CurveBipoint>& votes, const Curvepoint& shortTermPublicKey)
  90. {
  91. if (!verify_vote_proof(pi, votes, shortTermPublicKey))
  92. {
  93. std::cerr << "Could not verify votes." << std::endl;
  94. return;
  95. }
  96. size_t voteSubmitter = binary_search(shortTermPublicKey);
  97. voteMatrix[voteSubmitter] = votes;
  98. }
  99. const BGN& PrsonaServer::get_bgn_details() const
  100. {
  101. return bgn_system;
  102. }
  103. std::vector<Scalar> PrsonaServer::tally_scores(Proof& pi)
  104. {
  105. std::vector<Quadripoint> BGNEncryptedTallies;
  106. std::vector<Scalar> decryptedTallies;
  107. for (size_t i = 0; i < voteMatrix.size(); i++)
  108. {
  109. std::vector<Quadripoint> weightedVotes;
  110. for (size_t j = 0; j < previousVoteTally.size(); j++)
  111. {
  112. Quadripoint curr = bgn_system.homomorphic_multiplication_no_rerandomize(voteMatrix[j][i], previousVoteTally[j]);
  113. weightedVotes.push_back(curr);
  114. }
  115. Quadripoint currEncryptedTally = weightedVotes[0];
  116. for (size_t j = 1; j < weightedVotes.size(); j++)
  117. currEncryptedTally = bgn_system.homomorphic_addition_no_rerandomize(currEncryptedTally, weightedVotes[j]);
  118. decryptedTallies.push_back(bgn_system.decrypt(currEncryptedTally));
  119. }
  120. pi = generate_proof_of_correct_tally(BGNEncryptedTallies, decryptedTallies);
  121. return decryptedTallies;
  122. }
  123. void PrsonaServer::export_updates(std::vector<TwistBipoint>& otherPreviousVoteTally,
  124. std::vector<Curvepoint>& otherCurrentPseudonyms, std::vector<std::vector<CurveBipoint>>& otherVoteMatrix) const
  125. {
  126. otherPreviousVoteTally = previousVoteTally;
  127. otherCurrentPseudonyms = currentPseudonyms;
  128. otherVoteMatrix = voteMatrix;
  129. }
  130. void PrsonaServer::import_updates(const Proof& pi, const std::vector<TwistBipoint>& otherPreviousVoteTally,
  131. const std::vector<Curvepoint>& otherCurrentPseudonyms, const std::vector<std::vector<CurveBipoint>>& otherVoteMatrix)
  132. {
  133. if (!verify_update_proof(pi, otherPreviousVoteTally, otherCurrentPseudonyms, otherVoteMatrix))
  134. {
  135. std::cerr << "Could not verify valid update." << std::endl;
  136. return;
  137. }
  138. previousVoteTally = otherPreviousVoteTally;
  139. currentPseudonyms = otherCurrentPseudonyms;
  140. voteMatrix = otherVoteMatrix;
  141. }
  142. void PrsonaServer::epoch_part_one(Proof& pi, Curvepoint& nextGenerator, std::vector<Scalar>& decryptedTallies)
  143. {
  144. nextSeed.set_random();
  145. nextGenerator = nextGenerator * nextSeed;
  146. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  147. currentPseudonyms[i] = currentPseudonyms[i] * nextSeed;
  148. std::vector<size_t> shuffleOrder = order_data();
  149. rerandomize_vote_matrix();
  150. std::vector<Scalar> reorderedTallies;
  151. for (size_t i = 0; i < shuffleOrder.size(); i++)
  152. reorderedTallies.push_back(decryptedTallies[shuffleOrder[i]]);
  153. decryptedTallies = reorderedTallies;
  154. pi = generate_proof_of_shuffle(shuffleOrder);
  155. }
  156. void PrsonaServer::epoch_part_two(Proof& pi, std::vector<EGCiphertext>& encryptedTallies)
  157. {
  158. Scalar inverseSeed = currentSeed.curveInverse();
  159. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  160. {
  161. currentPseudonyms[i] = currentPseudonyms[i] * inverseSeed;
  162. encryptedTallies[i].mask = encryptedTallies[i].mask * inverseSeed;
  163. }
  164. std::vector<size_t> shuffleOrder = order_data();
  165. rerandomize_vote_matrix();
  166. std::vector<EGCiphertext> reorderedTallies;
  167. for (size_t i = 0; i < shuffleOrder.size(); i++)
  168. reorderedTallies.push_back(encryptedTallies[shuffleOrder[i]]);
  169. encryptedTallies = reorderedTallies;
  170. pi = generate_proof_of_shuffle(shuffleOrder);
  171. currentSeed = nextSeed;
  172. }
  173. std::vector<size_t> PrsonaServer::order_data()
  174. {
  175. std::vector<size_t> retval;
  176. std::vector<SortingType> sortTracker;
  177. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  178. {
  179. SortingType curr;
  180. curr.pseudonym = currentPseudonyms[i];
  181. curr.index = i;
  182. sortTracker.push_back(curr);
  183. }
  184. std::sort(sortTracker.begin(), sortTracker.end());
  185. std::vector<Curvepoint> newPseudonyms;
  186. std::vector<TwistBipoint> newVoteTallies;
  187. std::vector<std::vector<CurveBipoint>> newVoteMatrix;
  188. for (size_t i = 0; i < sortTracker.size(); i++)
  189. {
  190. newPseudonyms.push_back(sortTracker[i].pseudonym);
  191. newVoteTallies.push_back(previousVoteTally[sortTracker[i].index]);
  192. std::vector<CurveBipoint> currNewRow;
  193. for (size_t j = 0; j < currentPseudonyms.size(); j++)
  194. {
  195. currNewRow.push_back(voteMatrix[sortTracker[i].index][sortTracker[j].index]);
  196. }
  197. newVoteMatrix.push_back(currNewRow);
  198. retval.push_back(sortTracker[i].index);
  199. }
  200. currentPseudonyms = newPseudonyms;
  201. previousVoteTally = newVoteTallies;
  202. voteMatrix = newVoteMatrix;
  203. return retval;
  204. }
  205. void PrsonaServer::rerandomize_vote_matrix()
  206. {
  207. for (size_t i = 0; i < voteMatrix.size(); i++)
  208. {
  209. for (size_t j = 0; j < voteMatrix[0].size(); j++)
  210. {
  211. voteMatrix[i][j] = bgn_system.rerandomize(voteMatrix[i][j]);
  212. }
  213. }
  214. }
  215. size_t PrsonaServer::binary_search(const Curvepoint& index) const
  216. {
  217. size_t lo, hi;
  218. lo = 0;
  219. hi = currentPseudonyms.size() - 1;
  220. while (lo < hi)
  221. {
  222. size_t mid = (lo + hi) / 2;
  223. if (currentPseudonyms[mid] < index)
  224. lo = mid + 1;
  225. else if (index == currentPseudonyms[mid])
  226. return mid;
  227. else hi = mid - 1;
  228. }
  229. return lo;
  230. }
  231. bool PrsonaServer::verify_valid_key_proof(const Proof& pi, const Curvepoint& shortTermPublicKey) const
  232. {
  233. if (!malicious_client)
  234. return pi == "PROOF";
  235. return pi == "PROOF";
  236. }
  237. bool PrsonaServer::verify_vote_proof(const Proof& pi, const std::vector<CurveBipoint>& votes, const Curvepoint& shortTermPublicKey) const
  238. {
  239. if (!malicious_client)
  240. return pi == "PROOF";
  241. return pi == "PROOF";
  242. }
  243. bool PrsonaServer::verify_update_proof(const Proof& pi, const std::vector<TwistBipoint>& otherPreviousVoteTally, const std::vector<Curvepoint>& otherCurrentPseudonyms, const std::vector<std::vector<CurveBipoint>>& otherVoteMatrix) const
  244. {
  245. if (!malicious_server)
  246. return pi == "PROOF";
  247. return pi == "PROOF";
  248. }
  249. Proof PrsonaServer::generate_valid_fresh_generator_proof(const Proof& oldProof) const
  250. {
  251. if (!malicious_server)
  252. return "PROOF";
  253. return "PROOF";
  254. }
  255. Proof PrsonaServer::generate_votes_valid_proof(const std::vector<CurveBipoint>& votes, const Curvepoint& voter) const
  256. {
  257. if (!malicious_server)
  258. return "PROOF";
  259. return "PROOF";
  260. }
  261. Proof PrsonaServer::generate_proof_of_added_user(const Curvepoint& shortTermPublicKey) const
  262. {
  263. if (!malicious_server)
  264. return "PROOF";
  265. return "PROOF";
  266. }
  267. Proof PrsonaServer::generate_score_proof(const EGCiphertext& score) const
  268. {
  269. if (!malicious_server)
  270. return "PROOF";
  271. return "PROOF";
  272. }
  273. Proof PrsonaServer::generate_proof_of_correct_tally(const std::vector<Quadripoint>& BGNEncryptedTallies, const std::vector<Scalar>& decryptedTallies) const
  274. {
  275. if (!malicious_server)
  276. return "PROOF";
  277. return "PROOF";
  278. }
  279. Proof PrsonaServer::generate_proof_of_shuffle(const std::vector<size_t>& shuffle_order) const
  280. {
  281. if (!malicious_server)
  282. return "PROOF";
  283. return "PROOF";
  284. }