client.cpp 9.2 KB

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