client.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include <iostream>
  2. #include "client.hpp"
  3. #include "serverEntity.hpp"
  4. /********************
  5. * PUBLIC FUNCTIONS *
  6. ********************/
  7. /*
  8. * CONSTRUCTORS
  9. */
  10. PrsonaClient::PrsonaClient(
  11. const std::vector<Proof>& generatorProof,
  12. const Curvepoint& elGamalBlindGenerator,
  13. const BGNPublicKey& serverPublicKey,
  14. const PrsonaServerEntity* servers)
  15. : serverPublicKey(serverPublicKey),
  16. servers(servers),
  17. max_checked(0)
  18. {
  19. set_EG_blind_generator(
  20. generatorProof, elGamalBlindGenerator, servers->get_num_servers());
  21. longTermPrivateKey.set_random();
  22. inversePrivateKey = longTermPrivateKey.curveInverse();
  23. decryption_memoizer[elGamalBlindGenerator * max_checked] = max_checked;
  24. }
  25. /*
  26. * BASIC PUBLIC SYSTEM INFO GETTERS
  27. */
  28. Curvepoint PrsonaClient::get_short_term_public_key() const
  29. {
  30. return currentFreshGenerator * longTermPrivateKey;
  31. }
  32. Curvepoint PrsonaClient::get_short_term_public_key(Proof &pi) const
  33. {
  34. pi = generate_ownership_proof();
  35. return currentFreshGenerator * longTermPrivateKey;
  36. }
  37. /*
  38. * SERVER INTERACTIONS
  39. */
  40. /* Generate a new vote vector to give to the servers
  41. * @replaces controls which votes are actually being updated and which are not
  42. *
  43. * You may really want to make currentEncryptedVotes a member variable,
  44. * but it doesn't behave correctly when adding new clients after this one. */
  45. std::vector<CurveBipoint> PrsonaClient::make_votes(
  46. std::vector<Proof>& validVoteProof,
  47. const Proof& serverProof,
  48. const std::vector<CurveBipoint>& oldEncryptedVotes,
  49. const std::vector<Scalar>& votes,
  50. const std::vector<bool>& replaces) const
  51. {
  52. std::vector<Scalar> seeds(oldEncryptedVotes.size());
  53. std::vector<CurveBipoint> newEncryptedVotes(oldEncryptedVotes.size());
  54. if (!verify_valid_vote_row_proof(serverProof))
  55. {
  56. std::cerr << "Could not verify proof of valid votes." << std::endl;
  57. return newEncryptedVotes;
  58. }
  59. for (size_t i = 0; i < votes.size(); i++)
  60. {
  61. if (replaces[i])
  62. {
  63. newEncryptedVotes[i] =
  64. serverPublicKey.curveEncrypt(seeds[i], votes[i]);
  65. }
  66. else
  67. {
  68. newEncryptedVotes[i] =
  69. serverPublicKey.rerandomize(seeds[i], oldEncryptedVotes[i]);
  70. }
  71. }
  72. validVoteProof = generate_vote_proof(
  73. replaces, oldEncryptedVotes, newEncryptedVotes, seeds, votes);
  74. return newEncryptedVotes;
  75. }
  76. // Get a new fresh generator (happens at initialization and during each epoch)
  77. bool PrsonaClient::receive_fresh_generator(
  78. const std::vector<Proof>& pi, const Curvepoint& freshGenerator)
  79. {
  80. if (!verify_generator_proof(pi, freshGenerator, servers->get_num_servers()))
  81. return false;
  82. currentFreshGenerator = freshGenerator;
  83. return true;
  84. }
  85. // Receive a new encrypted score from the servers (each epoch)
  86. bool PrsonaClient::receive_vote_tally()
  87. {
  88. Proof pi;
  89. Curvepoint shortTermPublicKey = get_short_term_public_key();
  90. EGCiphertext score =
  91. servers->get_current_user_encrypted_tally(pi, shortTermPublicKey);
  92. if (!verify_valid_user_tally_proof(pi))
  93. {
  94. std::cerr << "Could not verify proof of valid tally." << std::endl;
  95. return false;
  96. }
  97. currentEncryptedScore = score;
  98. currentScore = decrypt_score(score);
  99. return true;
  100. }
  101. bool PrsonaClient::receive_new_user_data(const std::vector<Proof>& mainProof)
  102. {
  103. Proof currProof;
  104. Curvepoint shortTermPublicKey = get_short_term_public_key();
  105. EGCiphertext userEncryptedScore =
  106. servers->get_current_user_encrypted_tally(currProof, shortTermPublicKey);
  107. if (!verify_valid_user_tally_proof(currProof))
  108. {
  109. std::cerr << "Could not verify preliminary proof of user encrypted tally." << std::endl;
  110. return false;
  111. }
  112. TwistBipoint serverEncryptedScore =
  113. servers->get_current_server_encrypted_tally(currProof, shortTermPublicKey);
  114. if (!verify_valid_server_tally_proof(currProof))
  115. {
  116. std::cerr << "Could not verify preliminary proof of server encrypted tally." << std::endl;
  117. return false;
  118. }
  119. std::vector<std::vector<CurveBipoint>> encryptedVoteMatrix =
  120. servers->get_all_current_votes(currProof);
  121. if (!verify_valid_vote_matrix_proof(currProof))
  122. {
  123. std::cerr << "Could not verify preliminary proof of encrypted votes." << std::endl;
  124. return false;
  125. }
  126. std::vector<Curvepoint> currentPseudonyms =
  127. servers->get_current_pseudonyms(currProof);
  128. if (!verify_valid_pseudonyms_proof(currProof))
  129. {
  130. std::cerr << "Could not verify preliminary proof of pseudonyms." << std::endl;
  131. return false;
  132. }
  133. size_t selfIndex = binary_search(currentPseudonyms, shortTermPublicKey);
  134. if (currentPseudonyms[selfIndex] != shortTermPublicKey)
  135. {
  136. std::cerr << "Was not added to list of pseudonyms." << std::endl;
  137. return false;
  138. }
  139. bool flag = verify_proof_of_added_user(
  140. mainProof,
  141. currentFreshGenerator,
  142. shortTermPublicKey,
  143. elGamalBlindGenerator,
  144. serverPublicKey.get_bipoint_curvegen(),
  145. serverPublicKey.get_bipoint_curve_subgroup_gen(),
  146. serverPublicKey.get_bipoint_twistgen(),
  147. serverPublicKey.get_bipoint_twist_subgroup_gen(),
  148. selfIndex,
  149. userEncryptedScore,
  150. serverEncryptedScore,
  151. encryptedVoteMatrix);
  152. if (!flag)
  153. {
  154. std::cerr << "There was an issue verifying the proof; this user was not properly added." << std::endl;
  155. return false;
  156. }
  157. currentEncryptedScore = userEncryptedScore;
  158. currentScore = decrypt_score(userEncryptedScore);
  159. return true;
  160. }
  161. /*
  162. * REPUTATION PROOFS
  163. */
  164. // A pretty straightforward range proof (generation)
  165. std::vector<Proof> PrsonaClient::generate_reputation_proof(
  166. const Scalar& threshold) const
  167. {
  168. Proof ownershipProof = generate_ownership_proof();
  169. return PrsonaBase::generate_reputation_proof(
  170. ownershipProof,
  171. currentEncryptedScore,
  172. currentScore,
  173. threshold,
  174. inversePrivateKey,
  175. servers->get_num_clients());
  176. }
  177. bool PrsonaClient::verify_reputation_proof(
  178. const std::vector<Proof>& pi,
  179. const Curvepoint& shortTermPublicKey,
  180. const Scalar& threshold) const
  181. {
  182. Proof serverProof;
  183. EGCiphertext encryptedScore =
  184. servers->get_current_user_encrypted_tally(serverProof, shortTermPublicKey);
  185. if (!verify_valid_user_tally_proof(serverProof))
  186. {
  187. std::cerr << "Error getting score from server, aborting." << std::endl;
  188. return false;
  189. }
  190. return PrsonaBase::verify_reputation_proof(
  191. pi, currentFreshGenerator, shortTermPublicKey, encryptedScore, threshold);
  192. }
  193. Scalar PrsonaClient::get_score() const
  194. {
  195. return currentScore;
  196. }
  197. /*********************
  198. * PRIVATE FUNCTIONS *
  199. *********************/
  200. /*
  201. * SCORE DECRYPTION
  202. */
  203. // Basic memoized score decryption
  204. Scalar PrsonaClient::decrypt_score(const EGCiphertext& score)
  205. {
  206. Curvepoint s, hashedDecrypted;
  207. // Remove the mask portion of the ciphertext
  208. s = score.mask * inversePrivateKey;
  209. hashedDecrypted = score.encryptedMessage - s;
  210. // Check if it's a value we've already seen
  211. auto lookup = decryption_memoizer.find(hashedDecrypted);
  212. if (lookup != decryption_memoizer.end())
  213. return lookup->second;
  214. // If not, iterate until we find it (adding everything to the memoization)
  215. max_checked++;
  216. Curvepoint decryptionCandidate = elGamalBlindGenerator * max_checked;
  217. while (decryptionCandidate != hashedDecrypted)
  218. {
  219. decryption_memoizer[decryptionCandidate] = max_checked;
  220. decryptionCandidate = decryptionCandidate + elGamalBlindGenerator;
  221. max_checked++;
  222. }
  223. decryption_memoizer[decryptionCandidate] = max_checked;
  224. // Return the value we found
  225. return max_checked;
  226. }
  227. /*
  228. * OWNERSHIP PROOFS
  229. */
  230. // Prove ownership of the short term public key
  231. Proof PrsonaClient::generate_ownership_proof() const
  232. {
  233. Curvepoint shortTermPublicKey = currentFreshGenerator * longTermPrivateKey;
  234. return PrsonaBase::generate_ownership_proof(
  235. currentFreshGenerator, shortTermPublicKey, longTermPrivateKey);
  236. }
  237. /*
  238. * VALID VOTE PROOFS
  239. */
  240. std::vector<Proof> PrsonaClient::generate_vote_proof(
  241. const std::vector<bool>& replaces,
  242. const std::vector<CurveBipoint>& oldEncryptedVotes,
  243. const std::vector<CurveBipoint>& newEncryptedVotes,
  244. const std::vector<Scalar>& seeds,
  245. const std::vector<Scalar>& votes) const
  246. {
  247. Proof pi = generate_ownership_proof();
  248. return PrsonaBase::generate_vote_proof(
  249. pi,
  250. serverPublicKey.get_bipoint_curvegen(),
  251. serverPublicKey.get_bipoint_curve_subgroup_gen(),
  252. replaces,
  253. oldEncryptedVotes,
  254. newEncryptedVotes,
  255. seeds,
  256. votes);
  257. }