server.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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(1);
  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. Scalar PrsonaServer::get_max_possible_score(Proof& pi)
  124. {
  125. TwistBipoint currEncryptedVal = previousVoteTally[0];
  126. for (size_t i = 1; i < previousVoteTally.size(); i++)
  127. currEncryptedVal = bgn_system.homomorphic_addition_no_rerandomize(currEncryptedVal, previousVoteTally[i]);
  128. Scalar retval = bgn_system.decrypt(currEncryptedVal);
  129. pi = generate_proof_of_correct_sum(currEncryptedVal, retval);
  130. return retval;
  131. }
  132. void PrsonaServer::export_updates(std::vector<TwistBipoint>& otherPreviousVoteTally,
  133. std::vector<Curvepoint>& otherCurrentPseudonyms, std::vector<std::vector<CurveBipoint>>& otherVoteMatrix) const
  134. {
  135. otherPreviousVoteTally = previousVoteTally;
  136. otherCurrentPseudonyms = currentPseudonyms;
  137. otherVoteMatrix = voteMatrix;
  138. }
  139. void PrsonaServer::import_updates(const Proof& pi, const std::vector<TwistBipoint>& otherPreviousVoteTally,
  140. const std::vector<Curvepoint>& otherCurrentPseudonyms, const std::vector<std::vector<CurveBipoint>>& otherVoteMatrix)
  141. {
  142. if (!verify_update_proof(pi, otherPreviousVoteTally, otherCurrentPseudonyms, otherVoteMatrix))
  143. {
  144. std::cerr << "Could not verify valid update." << std::endl;
  145. return;
  146. }
  147. previousVoteTally = otherPreviousVoteTally;
  148. currentPseudonyms = otherCurrentPseudonyms;
  149. voteMatrix = otherVoteMatrix;
  150. }
  151. void PrsonaServer::epoch_part_one(Proof& pi, Curvepoint& nextGenerator, std::vector<Scalar>& decryptedTallies, std::vector<Scalar>& encryptedTallyMasks)
  152. {
  153. nextSeed.set_random();
  154. nextGenerator = nextGenerator * nextSeed;
  155. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  156. {
  157. Scalar currMask;
  158. currMask.set_random();
  159. encryptedTallyMasks[i] = encryptedTallyMasks[i].curveAdd(currMask);
  160. currentPseudonyms[i] = currentPseudonyms[i] * nextSeed;
  161. }
  162. std::vector<size_t> shuffleOrder = order_data();
  163. rerandomize_vote_matrix();
  164. std::vector<Scalar> reorderedTallies;
  165. for (size_t i = 0; i < shuffleOrder.size(); i++)
  166. reorderedTallies.push_back(decryptedTallies[shuffleOrder[i]]);
  167. decryptedTallies = reorderedTallies;
  168. pi = generate_proof_of_shuffle(shuffleOrder);
  169. }
  170. void PrsonaServer::epoch_part_two(Proof& pi, const Curvepoint& nextGenerator, std::vector<EGCiphertext>& encryptedTallies, std::vector<Scalar>& encryptedTallyMasks)
  171. {
  172. Scalar inverseSeed = currentSeed.curveInverse();
  173. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  174. {
  175. Scalar rerandomizer;
  176. rerandomizer.set_random();
  177. currentPseudonyms[i] = currentPseudonyms[i] * inverseSeed;
  178. encryptedTallies[i].mask = encryptedTallies[i].mask * inverseSeed;
  179. encryptedTallies[i].mask = encryptedTallies[i].mask + currentPseudonyms[i] * rerandomizer;
  180. encryptedTallies[i].encryptedMessage = encryptedTallies[i].encryptedMessage + nextGenerator * rerandomizer;
  181. encryptedTallyMasks[i] = encryptedTallyMasks[i].curveAdd(rerandomizer);
  182. }
  183. std::vector<size_t> shuffleOrder = order_data();
  184. rerandomize_vote_matrix();
  185. std::vector<Scalar> reorderedMasks;
  186. std::vector<EGCiphertext> reorderedTallies;
  187. for (size_t i = 0; i < shuffleOrder.size(); i++)
  188. {
  189. reorderedMasks.push_back(encryptedTallyMasks[shuffleOrder[i]]);
  190. reorderedTallies.push_back(encryptedTallies[shuffleOrder[i]]);
  191. }
  192. encryptedTallyMasks = reorderedMasks;
  193. encryptedTallies = reorderedTallies;
  194. pi = generate_proof_of_shuffle(shuffleOrder);
  195. currentSeed = nextSeed;
  196. }
  197. std::vector<size_t> PrsonaServer::order_data()
  198. {
  199. std::vector<size_t> retval;
  200. std::vector<SortingType> sortTracker;
  201. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  202. {
  203. SortingType curr;
  204. curr.pseudonym = currentPseudonyms[i];
  205. curr.index = i;
  206. sortTracker.push_back(curr);
  207. }
  208. std::sort(sortTracker.begin(), sortTracker.end());
  209. std::vector<Curvepoint> newPseudonyms;
  210. std::vector<TwistBipoint> newVoteTallies;
  211. std::vector<std::vector<CurveBipoint>> newVoteMatrix;
  212. for (size_t i = 0; i < sortTracker.size(); i++)
  213. {
  214. newPseudonyms.push_back(sortTracker[i].pseudonym);
  215. newVoteTallies.push_back(previousVoteTally[sortTracker[i].index]);
  216. std::vector<CurveBipoint> currNewRow;
  217. for (size_t j = 0; j < currentPseudonyms.size(); j++)
  218. {
  219. currNewRow.push_back(voteMatrix[sortTracker[i].index][sortTracker[j].index]);
  220. }
  221. newVoteMatrix.push_back(currNewRow);
  222. retval.push_back(sortTracker[i].index);
  223. }
  224. currentPseudonyms = newPseudonyms;
  225. previousVoteTally = newVoteTallies;
  226. voteMatrix = newVoteMatrix;
  227. return retval;
  228. }
  229. void PrsonaServer::rerandomize_vote_matrix()
  230. {
  231. for (size_t i = 0; i < voteMatrix.size(); i++)
  232. {
  233. for (size_t j = 0; j < voteMatrix[0].size(); j++)
  234. {
  235. voteMatrix[i][j] = bgn_system.rerandomize(voteMatrix[i][j]);
  236. }
  237. }
  238. }
  239. size_t PrsonaServer::binary_search(const Curvepoint& index) const
  240. {
  241. size_t lo, hi;
  242. lo = 0;
  243. hi = currentPseudonyms.size() - 1;
  244. while (lo < hi)
  245. {
  246. size_t mid = (lo + hi) / 2;
  247. if (currentPseudonyms[mid] < index)
  248. lo = mid + 1;
  249. else if (index == currentPseudonyms[mid])
  250. return mid;
  251. else hi = mid - 1;
  252. }
  253. return lo;
  254. }
  255. bool PrsonaServer::verify_valid_key_proof(const Proof& pi, const Curvepoint& shortTermPublicKey) const
  256. {
  257. if (!malicious_client)
  258. return pi.basic == "PROOF";
  259. return pi.basic == "PROOF";
  260. }
  261. bool PrsonaServer::verify_vote_proof(const Proof& pi, const std::vector<CurveBipoint>& votes, const Curvepoint& shortTermPublicKey) const
  262. {
  263. if (!malicious_client)
  264. return pi.basic == "PROOF";
  265. return pi.basic == "PROOF";
  266. }
  267. 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
  268. {
  269. if (!malicious_server)
  270. return pi.basic == "PROOF";
  271. return pi.basic == "PROOF";
  272. }
  273. Proof PrsonaServer::generate_valid_fresh_generator_proof(const Proof& oldProof) const
  274. {
  275. Proof retval;
  276. if (!malicious_server)
  277. {
  278. retval.basic = "PROOF";
  279. return retval;
  280. }
  281. retval.basic = "PROOF";
  282. return retval;
  283. }
  284. Proof PrsonaServer::generate_votes_valid_proof(const std::vector<CurveBipoint>& votes, const Curvepoint& voter) const
  285. {
  286. Proof retval;
  287. if (!malicious_server)
  288. {
  289. retval.basic = "PROOF";
  290. return retval;
  291. }
  292. retval.basic = "PROOF";
  293. return retval;
  294. }
  295. Proof PrsonaServer::generate_proof_of_added_user(const Curvepoint& shortTermPublicKey) const
  296. {
  297. Proof retval;
  298. if (!malicious_server)
  299. {
  300. retval.basic = "PROOF";
  301. return retval;
  302. }
  303. retval.basic = "PROOF";
  304. return retval;
  305. }
  306. Proof PrsonaServer::generate_score_proof(const EGCiphertext& score) const
  307. {
  308. Proof retval;
  309. if (!malicious_server)
  310. {
  311. retval.basic = "PROOF";
  312. return retval;
  313. }
  314. retval.basic = "PROOF";
  315. return retval;
  316. }
  317. Proof PrsonaServer::generate_proof_of_correct_tally(const std::vector<Quadripoint>& BGNEncryptedTallies, const std::vector<Scalar>& decryptedTallies) const
  318. {
  319. Proof retval;
  320. if (!malicious_server)
  321. {
  322. retval.basic = "PROOF";
  323. return retval;
  324. }
  325. retval.basic = "PROOF";
  326. return retval;
  327. }
  328. Proof PrsonaServer::generate_proof_of_correct_sum(const TwistBipoint& BGNEncryptedSum, const Scalar& decryptedSum) const
  329. {
  330. Proof retval;
  331. if (!malicious_server)
  332. {
  333. retval.basic = "PROOF";
  334. return retval;
  335. }
  336. retval.basic = "PROOF";
  337. return retval;
  338. }
  339. Proof PrsonaServer::generate_proof_of_shuffle(const std::vector<size_t>& shuffle_order) const
  340. {
  341. Proof retval;
  342. if (!malicious_server)
  343. {
  344. retval.basic = "PROOF";
  345. return retval;
  346. }
  347. retval.basic = "PROOF";
  348. return retval;
  349. }