client.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 BGNPublicKey& serverPublicKey,
  12. const std::vector<Proof>& generatorProof,
  13. const Curvepoint& elGamalBlindGenerator,
  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(Proof &pi) const
  29. {
  30. pi = generate_ownership_proof();
  31. return currentFreshGenerator * longTermPrivateKey;
  32. }
  33. /*
  34. * SERVER INTERACTIONS
  35. */
  36. /* Generate a new vote vector to give to the servers
  37. * @replaces controls which votes are actually being updated and which are not
  38. *
  39. * You may really want to make currentEncryptedVotes a member variable,
  40. * but it doesn't behave correctly when adding new clients after this one. */
  41. std::vector<CurveBipoint> PrsonaClient::make_votes(
  42. std::vector<Proof>& validVoteProof,
  43. const Proof& serverProof,
  44. const std::vector<CurveBipoint>& oldEncryptedVotes,
  45. const std::vector<Scalar>& votes,
  46. const std::vector<bool>& replaces) const
  47. {
  48. std::vector<Scalar> seeds(oldEncryptedVotes.size());
  49. std::vector<CurveBipoint> newEncryptedVotes(oldEncryptedVotes.size());
  50. if (!verify_valid_votes_proof(serverProof))
  51. {
  52. std::cerr << "Could not verify proof of valid votes." << std::endl;
  53. return newEncryptedVotes;
  54. }
  55. for (size_t i = 0; i < votes.size(); i++)
  56. {
  57. if (replaces[i])
  58. {
  59. newEncryptedVotes[i] = serverPublicKey.encrypt(seeds[i], votes[i]);
  60. }
  61. else
  62. {
  63. newEncryptedVotes[i] =
  64. serverPublicKey.rerandomize(seeds[i], oldEncryptedVotes[i]);
  65. }
  66. }
  67. validVoteProof = generate_vote_proof(
  68. replaces, oldEncryptedVotes, newEncryptedVotes, seeds, votes);
  69. return newEncryptedVotes;
  70. }
  71. // Get a new fresh generator (happens at initialization and during each epoch)
  72. bool PrsonaClient::receive_fresh_generator(
  73. const std::vector<Proof>& pi, const Curvepoint& freshGenerator)
  74. {
  75. if (!verify_generator_proof(pi, freshGenerator, servers->get_num_servers()))
  76. return false;
  77. currentFreshGenerator = freshGenerator;
  78. return true;
  79. }
  80. // Receive a new encrypted score from the servers (each epoch)
  81. void PrsonaClient::receive_vote_tally(
  82. const Proof& pi, const EGCiphertext& score)
  83. {
  84. if (!verify_valid_tally_proof(pi))
  85. {
  86. std::cerr << "Could not verify proof of valid tally." << std::endl;
  87. return;
  88. }
  89. currentEncryptedScore = score;
  90. decrypt_score(score);
  91. }
  92. /*
  93. * REPUTATION PROOFS
  94. */
  95. // A pretty straightforward range proof (generation)
  96. std::vector<Proof> PrsonaClient::generate_reputation_proof(
  97. const Scalar& threshold) const
  98. {
  99. Proof ownershipProof = generate_ownership_proof();
  100. return PrsonaBase::generate_reputation_proof(
  101. ownershipProof,
  102. currentEncryptedScore,
  103. currentScore,
  104. threshold,
  105. inversePrivateKey,
  106. servers->get_num_clients());
  107. }
  108. bool PrsonaClient::verify_reputation_proof(
  109. const std::vector<Proof>& pi,
  110. const Curvepoint& shortTermPublicKey,
  111. const Scalar& threshold) const
  112. {
  113. Proof serverProof;
  114. EGCiphertext encryptedScore =
  115. servers->get_current_tally(serverProof, shortTermPublicKey);
  116. if (!verify_valid_tally_proof(serverProof))
  117. {
  118. std::cerr << "Error getting score from server, aborting." << std::endl;
  119. return false;
  120. }
  121. return PrsonaBase::verify_reputation_proof(
  122. pi, currentFreshGenerator, shortTermPublicKey, encryptedScore, threshold);
  123. }
  124. Scalar PrsonaClient::get_score() const
  125. {
  126. return currentScore;
  127. }
  128. /*********************
  129. * PRIVATE FUNCTIONS *
  130. *********************/
  131. /*
  132. * SCORE DECRYPTION
  133. */
  134. // Basic memoized score decryption
  135. void PrsonaClient::decrypt_score(const EGCiphertext& score)
  136. {
  137. Curvepoint s, hashedDecrypted;
  138. // Remove the mask portion of the ciphertext
  139. s = score.mask * inversePrivateKey;
  140. hashedDecrypted = score.encryptedMessage - s;
  141. // Check if it's a value we've already seen
  142. auto lookup = decryption_memoizer.find(hashedDecrypted);
  143. if (lookup != decryption_memoizer.end())
  144. {
  145. currentScore = lookup->second;
  146. return;
  147. }
  148. // If not, iterate until we find it (adding everything to the memoization)
  149. max_checked++;
  150. Curvepoint decryptionCandidate = elGamalBlindGenerator * max_checked;
  151. while (decryptionCandidate != hashedDecrypted)
  152. {
  153. decryption_memoizer[decryptionCandidate] = max_checked;
  154. decryptionCandidate = decryptionCandidate + elGamalBlindGenerator;
  155. max_checked++;
  156. }
  157. decryption_memoizer[decryptionCandidate] = max_checked;
  158. // Set the value we found
  159. currentScore = max_checked;
  160. }
  161. /*
  162. * OWNERSHIP PROOFS
  163. */
  164. // Prove ownership of the short term public key
  165. Proof PrsonaClient::generate_ownership_proof() const
  166. {
  167. Curvepoint shortTermPublicKey = currentFreshGenerator * longTermPrivateKey;
  168. return PrsonaBase::generate_ownership_proof(
  169. currentFreshGenerator, shortTermPublicKey, longTermPrivateKey);
  170. }
  171. /*
  172. * VALID VOTE PROOFS
  173. */
  174. std::vector<Proof> PrsonaClient::generate_vote_proof(
  175. const std::vector<bool>& replaces,
  176. const std::vector<CurveBipoint>& oldEncryptedVotes,
  177. const std::vector<CurveBipoint>& newEncryptedVotes,
  178. const std::vector<Scalar>& seeds,
  179. const std::vector<Scalar>& votes) const
  180. {
  181. Proof pi = generate_ownership_proof();
  182. return PrsonaBase::generate_vote_proof(
  183. pi,
  184. serverPublicKey.get_bipoint_curvegen(),
  185. serverPublicKey.get_bipoint_curve_subgroup_gen(),
  186. replaces,
  187. oldEncryptedVotes,
  188. newEncryptedVotes,
  189. seeds,
  190. votes);
  191. }