server.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436
  1. #include <iostream>
  2. #include "server.hpp"
  3. /********************
  4. * PUBLIC FUNCTIONS *
  5. ********************/
  6. /*
  7. * CONSTRUCTORS
  8. */
  9. // Used to generate the first server; instantiates BGN for the first time
  10. PrsonaServer::PrsonaServer(size_t numServers)
  11. : numServers(numServers)
  12. {
  13. currentSeed.set_random();
  14. }
  15. // Used for all other servers, so they have the same BGN parameters
  16. PrsonaServer::PrsonaServer(size_t numServers, const BGN& otherBgn)
  17. : numServers(numServers), bgnSystem(otherBgn)
  18. {
  19. currentSeed.set_random();
  20. }
  21. /*
  22. * BASIC PUBLIC SYSTEM INFO GETTERS
  23. */
  24. BGNPublicKey PrsonaServer::get_bgn_public_key() const
  25. {
  26. return bgnSystem.get_public_key();
  27. }
  28. size_t PrsonaServer::get_num_clients() const
  29. {
  30. return currentPseudonyms.size();
  31. }
  32. size_t PrsonaServer::get_num_servers() const
  33. {
  34. return numServers;
  35. }
  36. /*
  37. * FRESH GENERATOR CALCULATION
  38. */
  39. // To calculate the current epoch's generator, start from the base generator,
  40. // then have every server call this function on it iteratively (in any order).
  41. Twistpoint PrsonaServer::add_curr_seed_to_generator(
  42. std::vector<Proof>& pi,
  43. const Twistpoint& currGenerator) const
  44. {
  45. pi.push_back(add_to_generator_proof(currGenerator, currentSeed));
  46. return currGenerator * currentSeed;
  47. }
  48. // To calculate the next epoch's generator, start from the base generator,
  49. // then have every server call this function on it iteratively (in any order).
  50. Twistpoint PrsonaServer::add_next_seed_to_generator(
  51. std::vector<Proof>& pi,
  52. const Twistpoint& currGenerator) const
  53. {
  54. pi.push_back(add_to_generator_proof(currGenerator, nextSeed));
  55. return currGenerator * nextSeed;
  56. }
  57. /*
  58. * ENCRYPTED DATA GETTERS
  59. */
  60. /* Call this in order to get the current encrypted votes cast by a given user
  61. * (who is identified by their short term public key).
  62. * In practice, this is intended for clients,
  63. * who need to know their current votes in order to rerandomize them. */
  64. std::vector<TwistBipoint> PrsonaServer::get_current_votes_by(
  65. Proof& pi, const Twistpoint& shortTermPublicKey) const
  66. {
  67. std::vector<TwistBipoint> retval;
  68. size_t voteSubmitter = binary_search(shortTermPublicKey);
  69. retval = voteMatrix[voteSubmitter];
  70. pi = generate_valid_vote_row_proof(retval);
  71. return retval;
  72. }
  73. std::vector<std::vector<TwistBipoint>> PrsonaServer::get_all_current_votes(
  74. Proof& pi) const
  75. {
  76. pi = generate_valid_vote_matrix_proof(voteMatrix);
  77. return voteMatrix;
  78. }
  79. /* Call this in order to get the current encrypted tally of a given user
  80. * (who is identified by their short term public key).
  81. * In practice, this is intended for clients, so that the servers vouch
  82. * for their ciphertexts being valid as part of their reputation proofs. */
  83. EGCiphertext PrsonaServer::get_current_user_encrypted_tally(
  84. Proof& pi, const Twistpoint& shortTermPublicKey) const
  85. {
  86. EGCiphertext retval;
  87. size_t tallyOwner = binary_search(shortTermPublicKey);
  88. retval = currentUserEncryptedTallies[tallyOwner];
  89. pi = generate_valid_user_tally_proof(retval);
  90. return retval;
  91. }
  92. CurveBipoint PrsonaServer::get_current_server_encrypted_tally(
  93. Proof& pi, const Twistpoint& shortTermPublicKey) const
  94. {
  95. CurveBipoint retval;
  96. size_t tallyOwner = binary_search(shortTermPublicKey);
  97. retval = previousVoteTallies[tallyOwner];
  98. pi = generate_valid_server_tally_proof(retval);
  99. return retval;
  100. }
  101. std::vector<Twistpoint> PrsonaServer::get_current_pseudonyms(Proof& pi) const
  102. {
  103. pi = generate_valid_pseudonyms_proof(currentPseudonyms);
  104. return currentPseudonyms;
  105. }
  106. /*
  107. * PROOF COMMITMENT GETTERS
  108. */
  109. Proof PrsonaServer::get_vote_row_commitment(const Twistpoint& request) const
  110. {
  111. size_t requestID = binary_search(request);
  112. return generate_valid_vote_row_proof(voteMatrix[requestID]);
  113. }
  114. Proof PrsonaServer::get_vote_matrix_commitment() const
  115. {
  116. return generate_valid_vote_matrix_proof(voteMatrix);
  117. }
  118. Proof PrsonaServer::get_user_tally_commitment(const Twistpoint& request) const
  119. {
  120. size_t requestID = binary_search(request);
  121. return generate_valid_user_tally_proof(currentUserEncryptedTallies[requestID]);
  122. }
  123. Proof PrsonaServer::get_server_tally_commitment(const Twistpoint& request) const
  124. {
  125. size_t requestID = binary_search(request);
  126. return generate_valid_server_tally_proof(previousVoteTallies[requestID]);
  127. }
  128. Proof PrsonaServer::get_pseudonyms_commitment() const
  129. {
  130. return generate_valid_pseudonyms_proof(currentPseudonyms);
  131. }
  132. /*
  133. * CLIENT INTERACTIONS
  134. */
  135. /* Add a new client (who is identified only by their short term public key)
  136. * One server will do this, then ask all other servers to import their
  137. * (proven) exported data. */
  138. void PrsonaServer::add_new_client(
  139. std::vector<Proof>& proofOfValidAddition,
  140. const Proof& proofOfValidKey,
  141. const Twistpoint& shortTermPublicKey)
  142. {
  143. if (!verify_ownership_proof(
  144. proofOfValidKey, currentFreshGenerator, shortTermPublicKey))
  145. {
  146. std::cerr << "Could not verify proof of valid key." << std::endl;
  147. return;
  148. }
  149. currentPseudonyms.push_back(shortTermPublicKey);
  150. // The first epoch's score for a new user will be low,
  151. // but will typically converge on an average score quickly
  152. Scalar tallySeed;
  153. CurveBipoint encryptedDefaultTally =
  154. bgnSystem.get_public_key().curveEncrypt(tallySeed, DEFAULT_TALLY);
  155. previousVoteTallies.push_back(encryptedDefaultTally);
  156. Scalar seedForUserTally;
  157. seedForUserTally.set_random();
  158. EGCiphertext newUserEncryptedTally;
  159. newUserEncryptedTally.mask = shortTermPublicKey * seedForUserTally;
  160. newUserEncryptedTally.encryptedMessage =
  161. currentFreshGenerator * seedForUserTally +
  162. elGamalBlindGenerator * DEFAULT_TALLY;
  163. currentUserEncryptedTallies.push_back(newUserEncryptedTally);
  164. // Users are defaulted to casting a neutral vote for others.
  165. TwistBipoint encryptedDefaultVote, encryptedSelfVote;
  166. Scalar currDefaultSeed, currSelfSeed;
  167. encryptedDefaultVote =
  168. bgnSystem.get_public_key().twistEncrypt(currDefaultSeed, DEFAULT_VOTE);
  169. encryptedSelfVote =
  170. bgnSystem.get_public_key().twistEncrypt(currSelfSeed, Scalar(MAX_ALLOWED_VOTE));
  171. std::vector<TwistBipoint> newRow;
  172. std::vector<Scalar> userVoteSeeds;
  173. std::vector<Scalar> otherVoteSeeds;
  174. for (size_t i = 0; i < voteMatrix.size(); i++)
  175. {
  176. Scalar addedSeed;
  177. encryptedDefaultVote = bgnSystem.get_public_key().rerandomize(addedSeed, encryptedDefaultVote);
  178. currDefaultSeed = currDefaultSeed + addedSeed;
  179. otherVoteSeeds.push_back(Scalar());
  180. otherVoteSeeds[i] = currDefaultSeed;
  181. voteMatrix[i].push_back(encryptedDefaultVote);
  182. encryptedDefaultVote = bgnSystem.get_public_key().rerandomize(addedSeed, encryptedDefaultVote);
  183. currDefaultSeed = currDefaultSeed + addedSeed;
  184. userVoteSeeds.push_back(Scalar());
  185. userVoteSeeds[i] = currDefaultSeed;
  186. newRow.push_back(encryptedDefaultVote);
  187. }
  188. // Because we are adding the new user to the end (and then sorting it),
  189. // this last element (bottom right corner) is always the self vote.
  190. userVoteSeeds.push_back(Scalar());
  191. userVoteSeeds[newRow.size()] = currSelfSeed;
  192. otherVoteSeeds.push_back(Scalar());
  193. otherVoteSeeds[newRow.size()] = currSelfSeed;
  194. newRow.push_back(encryptedSelfVote);
  195. voteMatrix.push_back(newRow);
  196. std::vector<size_t> sortOrder = order_data();
  197. std::vector<Scalar> newUserVoteSeeds;
  198. std::vector<Scalar> newOtherVoteSeeds;
  199. for (size_t i = 0; i < sortOrder.size(); i++)
  200. {
  201. newUserVoteSeeds.push_back(userVoteSeeds[sortOrder[i]]);
  202. newOtherVoteSeeds.push_back(otherVoteSeeds[sortOrder[i]]);
  203. }
  204. proofOfValidAddition = generate_proof_of_added_user(
  205. tallySeed,
  206. seedForUserTally,
  207. newUserVoteSeeds,
  208. newOtherVoteSeeds);
  209. }
  210. // Receive a new vote row from a user (identified by short term public key).
  211. bool PrsonaServer::receive_vote(
  212. const std::vector<Proof>& pi,
  213. const std::vector<TwistBipoint>& newVotes,
  214. const Twistpoint& shortTermPublicKey)
  215. {
  216. size_t voteSubmitter = binary_search(shortTermPublicKey);
  217. std::vector<TwistBipoint> oldVotes = voteMatrix[voteSubmitter];
  218. if (!verify_vote_proof(pi, oldVotes, newVotes, shortTermPublicKey))
  219. return false;
  220. voteMatrix[voteSubmitter] = newVotes;
  221. return true;
  222. }
  223. /*********************
  224. * PRIVATE FUNCTIONS *
  225. *********************/
  226. /*
  227. * CONSTRUCTOR HELPERS
  228. */
  229. const BGN& PrsonaServer::get_bgn_details() const
  230. {
  231. return bgnSystem;
  232. }
  233. bool PrsonaServer::initialize_fresh_generator(
  234. const std::vector<Proof>& pi,
  235. const Twistpoint& firstGenerator)
  236. {
  237. if (!verify_generator_proof(pi, firstGenerator, numServers))
  238. {
  239. std::cerr << "Could not verify generator proof, aborting." << std::endl;
  240. return false;
  241. }
  242. currentFreshGenerator = firstGenerator;
  243. return true;
  244. }
  245. // To calculate the blind generator for ElGamal, start from the base generator,
  246. // then have every server call this function on it iteratively (in any order).
  247. Twistpoint PrsonaServer::add_rand_seed_to_generator(
  248. std::vector<Proof>& pi,
  249. const Twistpoint& currGenerator) const
  250. {
  251. Scalar lambda;
  252. lambda.set_random();
  253. pi.push_back(add_to_generator_proof(currGenerator, lambda));
  254. return currGenerator * lambda;
  255. }
  256. bool PrsonaServer::set_EG_blind_generator(
  257. const std::vector<Proof>& pi,
  258. const Twistpoint& currGenerator)
  259. {
  260. return PrsonaBase::set_EG_blind_generator(pi, currGenerator, numServers);
  261. }
  262. /*
  263. * SCORE TALLYING
  264. */
  265. /* Calculate scores homomorphically (as an individual server would normally)
  266. * and then decrypt them (which the servers would normally work together to do).
  267. *
  268. * Note that since these calculations are just for us, we don't need to do any
  269. * expensive rerandomizations of intermediate values. */
  270. std::vector<Scalar> PrsonaServer::tally_scores()
  271. {
  272. std::vector<Quadripoint> BGNEncryptedTallies;
  273. std::vector<Scalar> decryptedTallies;
  274. for (size_t i = 0; i < voteMatrix.size(); i++)
  275. {
  276. std::vector<Quadripoint> weightedVotes;
  277. // ZIP
  278. for (size_t j = 0; j < previousVoteTallies.size(); j++)
  279. {
  280. Quadripoint curr =
  281. bgnSystem.homomorphic_multiplication_no_rerandomize(
  282. previousVoteTallies[j], voteMatrix[j][i]);
  283. weightedVotes.push_back(curr);
  284. }
  285. // FOLDL
  286. Quadripoint currEncryptedTally = weightedVotes[0];
  287. for (size_t j = 1; j < weightedVotes.size(); j++)
  288. {
  289. currEncryptedTally =
  290. bgnSystem.homomorphic_addition_no_rerandomize(
  291. currEncryptedTally, weightedVotes[j]);
  292. }
  293. // DECRYPT
  294. decryptedTallies.push_back(bgnSystem.decrypt(currEncryptedTally));
  295. }
  296. return decryptedTallies;
  297. }
  298. /* Calculate what the maximum possible score this round was (that is,
  299. * given the current user weights, what was the highest possible score?).
  300. *
  301. * As with individual scores, this also does the decryption that servers
  302. * would ordinarily work together to form. */
  303. Scalar PrsonaServer::get_max_possible_score()
  304. {
  305. // FOLDL
  306. CurveBipoint currEncryptedVal = previousVoteTallies[0];
  307. for (size_t i = 1; i < previousVoteTallies.size(); i++)
  308. {
  309. currEncryptedVal =
  310. bgnSystem.homomorphic_addition_no_rerandomize(
  311. currEncryptedVal, previousVoteTallies[i]);
  312. }
  313. // DECRYPT
  314. Scalar retval = bgnSystem.decrypt(currEncryptedVal);
  315. return retval;
  316. }
  317. /*
  318. * EPOCH ROUNDS
  319. */
  320. // The first round, going from A_0 to A_0.5
  321. void PrsonaServer::build_up_midway_pseudonyms(
  322. std::vector<std::vector<std::vector<Proof>>>& pi,
  323. std::vector<std::vector<std::vector<Twistpoint>>>& permutationCommits,
  324. std::vector<std::vector<std::vector<Twistpoint>>>& freshPseudonymCommits,
  325. std::vector<std::vector<std::vector<Twistpoint>>>& freshPseudonymSeedCommits,
  326. std::vector<std::vector<std::vector<CurveBipoint>>>& serverTallyCommits,
  327. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>>& partwayVoteMatrixCommits,
  328. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>>& finalVoteMatrixCommits,
  329. Twistpoint& nextGenerator)
  330. {
  331. nextSeed.set_random();
  332. std::vector<std::vector<Twistpoint>> currPermutationCommits;
  333. std::vector<std::vector<Twistpoint>> currFreshPseudonymCommits;
  334. std::vector<std::vector<Twistpoint>> currFreshPseudonymSeedCommits;
  335. std::vector<std::vector<CurveBipoint>> currServerTallyCommits;
  336. std::vector<std::vector<std::vector<TwistBipoint>>> currPartwayVoteMatrixCommits;
  337. std::vector<std::vector<std::vector<TwistBipoint>>> currFinalVoteMatrixCommits;
  338. std::vector<std::vector<Twistpoint>> currUserTallyMaskCommits;
  339. std::vector<std::vector<Twistpoint>> currUserTallyMessageCommits;
  340. std::vector<std::vector<Twistpoint>> currUserTallySeedCommits;
  341. pi.push_back(epoch_calculations(
  342. currPermutationCommits,
  343. currFreshPseudonymCommits,
  344. currFreshPseudonymSeedCommits,
  345. currServerTallyCommits,
  346. currPartwayVoteMatrixCommits,
  347. currFinalVoteMatrixCommits,
  348. currUserTallyMaskCommits,
  349. currUserTallyMessageCommits,
  350. currUserTallySeedCommits,
  351. nextSeed,
  352. nextGenerator,
  353. false));
  354. permutationCommits.push_back(currPermutationCommits);
  355. freshPseudonymCommits.push_back(currFreshPseudonymCommits);
  356. freshPseudonymSeedCommits.push_back(currFreshPseudonymSeedCommits);
  357. serverTallyCommits.push_back(currServerTallyCommits);
  358. partwayVoteMatrixCommits.push_back(currPartwayVoteMatrixCommits);
  359. finalVoteMatrixCommits.push_back(currFinalVoteMatrixCommits);
  360. pi[0][0].push_back(
  361. add_to_generator_proof(nextGenerator, nextSeed));
  362. nextGenerator = nextGenerator * nextSeed;
  363. }
  364. // In between these rounds, scores are tallied, decrypted,
  365. // and encrypted to fresh user pseudonyms (possible through weird math)
  366. // The second round, going from A_0.5 to A_1
  367. void PrsonaServer::break_down_midway_pseudonyms(
  368. std::vector<Proof>& generatorProof,
  369. std::vector<std::vector<std::vector<Proof>>>& pi,
  370. std::vector<std::vector<std::vector<Twistpoint>>>& permutationCommits,
  371. std::vector<std::vector<std::vector<Twistpoint>>>& freshPseudonymCommits,
  372. std::vector<std::vector<std::vector<Twistpoint>>>& freshPseudonymSeedCommits,
  373. std::vector<std::vector<std::vector<CurveBipoint>>>& serverTallyCommits,
  374. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>>& partwayVoteMatrixCommits,
  375. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>>& finalVoteMatrixCommits,
  376. std::vector<std::vector<std::vector<Twistpoint>>>& userTallyMaskCommits,
  377. std::vector<std::vector<std::vector<Twistpoint>>>& userTallyMessageCommits,
  378. std::vector<std::vector<std::vector<Twistpoint>>>& userTallySeedCommits,
  379. const Twistpoint& nextGenerator)
  380. {
  381. if (!initialize_fresh_generator(generatorProof, nextGenerator))
  382. {
  383. std::cerr << "New fresh generator could not be verified." << std::endl;
  384. return;
  385. }
  386. Scalar inverseSeed = currentSeed.curveMultInverse();
  387. std::vector<std::vector<Twistpoint>> currPermutationCommits;
  388. std::vector<std::vector<Twistpoint>> currFreshPseudonymCommits;
  389. std::vector<std::vector<Twistpoint>> currFreshPseudonymSeedCommits;
  390. std::vector<std::vector<CurveBipoint>> currServerTallyCommits;
  391. std::vector<std::vector<std::vector<TwistBipoint>>> currPartwayVoteMatrixCommits;
  392. std::vector<std::vector<std::vector<TwistBipoint>>> currFinalVoteMatrixCommits;
  393. std::vector<std::vector<Twistpoint>> currUserTallyMaskCommits;
  394. std::vector<std::vector<Twistpoint>> currUserTallyMessageCommits;
  395. std::vector<std::vector<Twistpoint>> currUserTallySeedCommits;
  396. pi.push_back(epoch_calculations(
  397. currPermutationCommits,
  398. currFreshPseudonymCommits,
  399. currFreshPseudonymSeedCommits,
  400. currServerTallyCommits,
  401. currPartwayVoteMatrixCommits,
  402. currFinalVoteMatrixCommits,
  403. currUserTallyMaskCommits,
  404. currUserTallyMessageCommits,
  405. currUserTallySeedCommits,
  406. inverseSeed,
  407. nextGenerator,
  408. true));
  409. permutationCommits.push_back(currPermutationCommits);
  410. freshPseudonymCommits.push_back(currFreshPseudonymCommits);
  411. freshPseudonymSeedCommits.push_back(currFreshPseudonymSeedCommits);
  412. serverTallyCommits.push_back(currServerTallyCommits);
  413. partwayVoteMatrixCommits.push_back(currPartwayVoteMatrixCommits);
  414. finalVoteMatrixCommits.push_back(currFinalVoteMatrixCommits);
  415. userTallyMaskCommits.push_back(currUserTallyMaskCommits);
  416. userTallyMessageCommits.push_back(currUserTallyMessageCommits);
  417. userTallySeedCommits.push_back(currUserTallySeedCommits);
  418. currentSeed = nextSeed;
  419. }
  420. /*
  421. * EPOCH HELPERS
  422. */
  423. std::vector<std::vector<Proof>> PrsonaServer::epoch_calculations(
  424. std::vector<std::vector<Twistpoint>>& permutationCommits,
  425. std::vector<std::vector<Twistpoint>>& freshPseudonymCommits,
  426. std::vector<std::vector<Twistpoint>>& freshPseudonymSeedCommits,
  427. std::vector<std::vector<CurveBipoint>>& serverTallyCommits,
  428. std::vector<std::vector<std::vector<TwistBipoint>>>& partwayVoteMatrixCommits,
  429. std::vector<std::vector<std::vector<TwistBipoint>>>& finalVoteMatrixCommits,
  430. std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  431. std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  432. std::vector<std::vector<Twistpoint>>& userTallySeedCommits,
  433. const Scalar& power,
  434. const Twistpoint& nextGenerator,
  435. bool doUserTallies)
  436. {
  437. std::vector<std::vector<Proof>> retval;
  438. std::vector<std::vector<Scalar>> permutations =
  439. generate_permutation_matrix(power);
  440. std::vector<std::vector<Scalar>> permutationSeeds;
  441. permutationCommits.clear();
  442. permutationCommits =
  443. generate_commitment_matrix(permutations, permutationSeeds);
  444. retval.push_back(generate_valid_permutation_proof(
  445. permutations, permutationSeeds, permutationCommits));
  446. std::vector<std::vector<Scalar>> freshPseudonymSeeds;
  447. freshPseudonymSeedCommits.clear();
  448. freshPseudonymCommits.clear();
  449. freshPseudonymCommits =
  450. generate_pseudonym_matrix(
  451. permutations,
  452. power,
  453. freshPseudonymSeeds,
  454. freshPseudonymSeedCommits);
  455. retval.push_back(
  456. generate_proof_of_reordering_plus_power(
  457. permutations,
  458. power,
  459. permutationSeeds,
  460. freshPseudonymSeeds,
  461. currentPseudonyms,
  462. permutationCommits,
  463. freshPseudonymCommits,
  464. freshPseudonymSeedCommits));
  465. std::vector<std::vector<Scalar>> serverTallySeeds;
  466. serverTallyCommits.clear();
  467. serverTallyCommits =
  468. generate_server_tally_matrix(
  469. permutations,
  470. serverTallySeeds);
  471. retval.push_back(
  472. generate_proof_of_reordering<CurveBipoint>(
  473. permutations,
  474. permutationSeeds,
  475. serverTallySeeds,
  476. previousVoteTallies,
  477. permutationCommits,
  478. serverTallyCommits,
  479. bgnSystem.get_public_key().get_bipoint_curvegen(),
  480. bgnSystem.get_public_key().get_bipoint_curve_subgroup_gen()));
  481. std::vector<std::vector<std::vector<Scalar>>> partwayVoteMatrixSeeds;
  482. std::vector<std::vector<std::vector<Scalar>>> finalVoteMatrixSeeds;
  483. partwayVoteMatrixCommits.clear();
  484. partwayVoteMatrixCommits = generate_vote_tensor(
  485. permutations,
  486. voteMatrix,
  487. partwayVoteMatrixSeeds,
  488. false);
  489. std::vector<std::vector<TwistBipoint>> partialVoteMatrix =
  490. calculate_next_vote_matrix(partwayVoteMatrixCommits);
  491. finalVoteMatrixCommits.clear();
  492. finalVoteMatrixCommits = generate_vote_tensor(
  493. permutations,
  494. partialVoteMatrix,
  495. finalVoteMatrixSeeds,
  496. true);
  497. generate_vote_tensor_proofs(
  498. retval,
  499. permutations,
  500. permutationSeeds,
  501. partwayVoteMatrixSeeds,
  502. voteMatrix,
  503. permutationCommits,
  504. partwayVoteMatrixCommits,
  505. false);
  506. generate_vote_tensor_proofs(
  507. retval,
  508. permutations,
  509. permutationSeeds,
  510. finalVoteMatrixSeeds,
  511. partialVoteMatrix,
  512. permutationCommits,
  513. finalVoteMatrixCommits,
  514. true);
  515. if (doUserTallies)
  516. {
  517. std::vector<Twistpoint> userTallyMasks;
  518. std::vector<Twistpoint> userTallyMessages;
  519. std::vector<std::vector<Scalar>> userTallySeeds;
  520. userTallyMaskCommits.clear();
  521. userTallyMessageCommits.clear();
  522. userTallySeedCommits.clear();
  523. generate_user_tally_matrix(
  524. permutations,
  525. power,
  526. nextGenerator,
  527. currentPseudonyms,
  528. userTallyMasks,
  529. userTallyMaskCommits,
  530. userTallyMessages,
  531. userTallyMessageCommits,
  532. userTallySeeds,
  533. userTallySeedCommits);
  534. retval.push_back(
  535. generate_user_tally_proofs(
  536. permutations,
  537. power,
  538. nextGenerator,
  539. permutationSeeds,
  540. userTallySeeds,
  541. currentPseudonyms,
  542. userTallyMasks,
  543. userTallyMessages,
  544. permutationCommits,
  545. userTallyMaskCommits,
  546. userTallyMessageCommits,
  547. userTallySeedCommits));
  548. }
  549. // Replace internal values
  550. update_data(
  551. freshPseudonymCommits,
  552. serverTallyCommits,
  553. finalVoteMatrixCommits,
  554. userTallyMaskCommits,
  555. userTallyMessageCommits);
  556. return retval;
  557. }
  558. bool PrsonaServer::accept_epoch_updates(
  559. const std::vector<std::vector<Proof>>& pi,
  560. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  561. const std::vector<std::vector<Twistpoint>>& freshPseudonymCommits,
  562. const std::vector<std::vector<Twistpoint>>& freshPseudonymSeedCommits,
  563. const std::vector<std::vector<CurveBipoint>>& serverTallyCommits,
  564. const std::vector<std::vector<std::vector<TwistBipoint>>>& partwayVoteMatrixCommits,
  565. const std::vector<std::vector<std::vector<TwistBipoint>>>& finalVoteMatrixCommits,
  566. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  567. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
  568. const std::vector<std::vector<Twistpoint>>& userTallySeedCommits,
  569. const Twistpoint& nextGenerator,
  570. bool doUserTallies)
  571. {
  572. bool verification;
  573. if ((userTallyMaskCommits.empty() && doUserTallies) || (!userTallyMaskCommits.empty() && !doUserTallies))
  574. {
  575. std::cerr << "user tallies are not in expected state." << std::endl;
  576. return false;
  577. }
  578. if (pi.empty())
  579. return false;
  580. size_t currOffset = 0;
  581. verification =
  582. verify_valid_permutation_proof(pi[currOffset], permutationCommits);
  583. currOffset++;
  584. if (!verification)
  585. {
  586. std::cerr << "Could not verify valid permutation matrix." << std::endl;
  587. return false;
  588. }
  589. verification =
  590. verify_proof_of_reordering_plus_power(
  591. pi[currOffset],
  592. currentPseudonyms,
  593. permutationCommits,
  594. freshPseudonymCommits,
  595. freshPseudonymSeedCommits);
  596. currOffset++;
  597. if (!verification)
  598. {
  599. std::cerr << "Could not verify valid pseudonym vector." << std::endl;
  600. return false;
  601. }
  602. verification =
  603. verify_proof_of_reordering<CurveBipoint>(
  604. pi[currOffset],
  605. previousVoteTallies,
  606. permutationCommits,
  607. serverTallyCommits,
  608. bgnSystem.get_public_key().get_bipoint_curvegen(),
  609. bgnSystem.get_public_key().get_bipoint_curve_subgroup_gen());
  610. currOffset++;
  611. if (!verification)
  612. {
  613. std::cerr << "Could not verify valid server tally vector." << std::endl;
  614. return false;
  615. }
  616. verification = verify_vote_tensor_proofs(
  617. pi,
  618. currOffset,
  619. voteMatrix,
  620. permutationCommits,
  621. partwayVoteMatrixCommits,
  622. false);
  623. currOffset += voteMatrix.size();
  624. if (!verification)
  625. {
  626. std::cerr << "Could not verify first half vote matrix." << std::endl;
  627. return false;
  628. }
  629. std::vector<std::vector<TwistBipoint>> partialVoteMatrix =
  630. calculate_next_vote_matrix(partwayVoteMatrixCommits);
  631. verification = verify_vote_tensor_proofs(
  632. pi,
  633. currOffset,
  634. partialVoteMatrix,
  635. permutationCommits,
  636. finalVoteMatrixCommits,
  637. true);
  638. currOffset += voteMatrix.size();
  639. if (!verification)
  640. {
  641. std::cerr << "Could not verify second half vote matrix." << std::endl;
  642. return false;
  643. }
  644. if (doUserTallies)
  645. {
  646. std::vector<Twistpoint> userTallyMasks;
  647. std::vector<Twistpoint> userTallyMessages;
  648. for (size_t i = 0; i < currentUserEncryptedTallies.size(); i++)
  649. {
  650. userTallyMasks.push_back(currentUserEncryptedTallies[i].mask);
  651. userTallyMessages.push_back(currentUserEncryptedTallies[i].encryptedMessage);
  652. }
  653. verification = verify_user_tally_proofs(
  654. pi[currOffset],
  655. nextGenerator,
  656. currentPseudonyms,
  657. userTallyMasks,
  658. userTallyMessages,
  659. permutationCommits,
  660. userTallyMaskCommits,
  661. userTallyMessageCommits,
  662. userTallySeedCommits);
  663. currOffset++;
  664. if (!verification)
  665. {
  666. std::cerr << "Could not verify user tallies." << std::endl;
  667. return false;
  668. }
  669. }
  670. verification = update_data(
  671. freshPseudonymCommits,
  672. serverTallyCommits,
  673. finalVoteMatrixCommits,
  674. userTallyMaskCommits,
  675. userTallyMessageCommits);
  676. return verification;
  677. }
  678. std::vector<std::vector<Scalar>> PrsonaServer::generate_permutation_matrix(
  679. const Scalar& reorderSeed) const
  680. {
  681. std::vector<std::vector<Scalar>> retval;
  682. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  683. {
  684. std::vector<Scalar> currRow;
  685. for (size_t j = 0; j < currentPseudonyms.size(); j++)
  686. currRow.push_back(Scalar(0));
  687. retval.push_back(currRow);
  688. }
  689. std::vector<Twistpoint> nextPseudonyms;
  690. for (size_t i = 0; i < currentPseudonyms.size(); i++)
  691. nextPseudonyms.push_back(currentPseudonyms[i] * reorderSeed);
  692. std::vector<size_t> order = sort_data(nextPseudonyms);
  693. for (size_t i = 0; i < order.size(); i++)
  694. retval[order[i]][i] = Scalar(1);
  695. for (size_t i = 0; i < retval.size(); i++)
  696. {
  697. std::cout << (i == 0 ? "[[" : " [");
  698. for (size_t j = 0; j < retval[i].size(); j++)
  699. std::cout << retval[i][j] << (j == retval[i].size() - 1 ? "]" : " ");
  700. std::cout << (i == retval.size() - 1 ? "]" : "") << std::endl;
  701. }
  702. return retval;
  703. }
  704. std::vector<std::vector<Twistpoint>> PrsonaServer::generate_commitment_matrix(
  705. const std::vector<std::vector<Scalar>>& permutations,
  706. std::vector<std::vector<Scalar>>& seeds) const
  707. {
  708. std::vector<std::vector<Twistpoint>> retval;
  709. Twistpoint g = EL_GAMAL_GENERATOR;
  710. Twistpoint h = elGamalBlindGenerator;
  711. seeds.clear();
  712. for (size_t i = 0; i < permutations.size(); i++)
  713. {
  714. std::vector<Scalar> currSeeds;
  715. for (size_t j = 0; j < permutations[i].size(); j++)
  716. currSeeds.push_back(Scalar(0));
  717. seeds.push_back(currSeeds);
  718. }
  719. for (size_t i = 0; i < permutations.size(); i++)
  720. {
  721. std::vector<Twistpoint> currRow;
  722. size_t last = permutations[i].size() - 1;
  723. for (size_t j = 0; j < permutations[i].size(); j++)
  724. {
  725. Twistpoint element;
  726. if (j != last)
  727. {
  728. seeds[i][j].set_random();
  729. seeds[i][last] = seeds[i][last] - seeds[i][j];
  730. }
  731. element = g * permutations[i][j] + h * seeds[i][j];
  732. currRow.push_back(element);
  733. }
  734. retval.push_back(currRow);
  735. }
  736. return retval;
  737. }
  738. std::vector<std::vector<Twistpoint>> PrsonaServer::generate_pseudonym_matrix(
  739. const std::vector<std::vector<Scalar>>& permutations,
  740. const Scalar& power,
  741. std::vector<std::vector<Scalar>>& seeds,
  742. std::vector<std::vector<Twistpoint>>& seedCommits) const
  743. {
  744. return generate_reordered_plus_power_matrix<Twistpoint>(
  745. permutations,
  746. power,
  747. currentPseudonyms,
  748. seeds,
  749. seedCommits,
  750. elGamalBlindGenerator);
  751. }
  752. std::vector<std::vector<CurveBipoint>> PrsonaServer::generate_server_tally_matrix(
  753. const std::vector<std::vector<Scalar>>& permutations,
  754. std::vector<std::vector<Scalar>>& seeds) const
  755. {
  756. return generate_reordered_matrix<CurveBipoint>(
  757. permutations,
  758. previousVoteTallies,
  759. seeds,
  760. bgnSystem.get_public_key().get_bipoint_curve_subgroup_gen(),
  761. false);
  762. }
  763. std::vector<std::vector<std::vector<TwistBipoint>>> PrsonaServer::generate_vote_tensor(
  764. const std::vector<std::vector<Scalar>>& permutations,
  765. const std::vector<std::vector<TwistBipoint>>& currVoteMatrix,
  766. std::vector<std::vector<std::vector<Scalar>>>& seeds,
  767. bool inverted) const
  768. {
  769. std::vector<std::vector<std::vector<TwistBipoint>>> retval;
  770. for (size_t i = 0; i < currVoteMatrix.size(); i++)
  771. {
  772. std::vector<std::vector<Scalar>> currSeeds;
  773. std::vector<TwistBipoint> inputRow;
  774. if (inverted)
  775. {
  776. for (size_t j = 0; j < currVoteMatrix.size(); j++)
  777. inputRow.push_back(currVoteMatrix[j][i]);
  778. }
  779. else
  780. {
  781. inputRow = currVoteMatrix[i];
  782. }
  783. retval.push_back(generate_reordered_matrix<TwistBipoint>(
  784. permutations,
  785. inputRow,
  786. currSeeds,
  787. bgnSystem.get_public_key().get_bipoint_twist_subgroup_gen(),
  788. false));
  789. seeds.push_back(currSeeds);
  790. }
  791. return retval;
  792. }
  793. std::vector<std::vector<TwistBipoint>> PrsonaServer::calculate_next_vote_matrix(
  794. const std::vector<std::vector<std::vector<TwistBipoint>>>& voteTensor) const
  795. {
  796. std::vector<std::vector<TwistBipoint>> retval;
  797. for (size_t i = 0; i < voteTensor.size(); i++)
  798. {
  799. std::vector<TwistBipoint> currRow;
  800. for (size_t j = 0; j < voteTensor[i].size(); j++)
  801. {
  802. TwistBipoint sum = voteTensor[i][j][0];
  803. for (size_t k = 1; k < voteTensor[i][j].size(); k++)
  804. sum = sum + voteTensor[i][j][k];
  805. currRow.push_back(sum);
  806. }
  807. retval.push_back(currRow);
  808. }
  809. return retval;
  810. }
  811. void PrsonaServer::generate_vote_tensor_proofs(
  812. std::vector<std::vector<Proof>>& pi,
  813. const std::vector<std::vector<Scalar>>& permutations,
  814. const std::vector<std::vector<Scalar>>& permutationSeeds,
  815. const std::vector<std::vector<std::vector<Scalar>>>& matrixSeeds,
  816. const std::vector<std::vector<TwistBipoint>>& currMatrix,
  817. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  818. const std::vector<std::vector<std::vector<TwistBipoint>>>& matrixCommits,
  819. bool inverted) const
  820. {
  821. for (size_t i = 0; i < currMatrix.size(); i++)
  822. {
  823. std::vector<TwistBipoint> inputRow;
  824. if (inverted)
  825. {
  826. for (size_t j = 0; j < currMatrix.size(); j++)
  827. inputRow.push_back(currMatrix[j][i]);
  828. }
  829. else
  830. {
  831. inputRow = currMatrix[i];
  832. }
  833. pi.push_back(generate_proof_of_reordering<TwistBipoint>(
  834. permutations,
  835. permutationSeeds,
  836. matrixSeeds[i],
  837. inputRow,
  838. permutationCommits,
  839. matrixCommits[i],
  840. bgnSystem.get_public_key().get_bipoint_twistgen(),
  841. bgnSystem.get_public_key().get_bipoint_twist_subgroup_gen()));
  842. }
  843. }
  844. bool PrsonaServer::verify_vote_tensor_proofs(
  845. const std::vector<std::vector<Proof>>& pi,
  846. size_t start_offset,
  847. const std::vector<std::vector<TwistBipoint>>& currMatrix,
  848. const std::vector<std::vector<Twistpoint>>& permutationCommits,
  849. const std::vector<std::vector<std::vector<TwistBipoint>>>& matrixCommits,
  850. bool inverted) const
  851. {
  852. bool retval = true;
  853. for (size_t i = 0; i < currMatrix.size(); i++)
  854. {
  855. std::vector<TwistBipoint> inputRow;
  856. if (inverted)
  857. {
  858. for (size_t j = 0; j < currMatrix.size(); j++)
  859. inputRow.push_back(currMatrix[j][i]);
  860. }
  861. else
  862. {
  863. inputRow = currMatrix[i];
  864. }
  865. size_t whichProof = i + start_offset;
  866. retval = retval && verify_proof_of_reordering<TwistBipoint>(
  867. pi[whichProof],
  868. inputRow,
  869. permutationCommits,
  870. matrixCommits[i],
  871. bgnSystem.get_public_key().get_bipoint_twistgen(),
  872. bgnSystem.get_public_key().get_bipoint_twist_subgroup_gen());
  873. }
  874. return retval;
  875. }
  876. void PrsonaServer::generate_user_tally_matrix(
  877. const std::vector<std::vector<Scalar>>& permutations,
  878. const Scalar& power,
  879. const Twistpoint& nextGenerator,
  880. const std::vector<Twistpoint>& currPseudonyms,
  881. std::vector<Twistpoint>& masks,
  882. std::vector<std::vector<Twistpoint>>& maskCommits,
  883. std::vector<Twistpoint>& messages,
  884. std::vector<std::vector<Twistpoint>>& messageCommits,
  885. std::vector<std::vector<Scalar>>& userTallySeeds,
  886. std::vector<std::vector<Twistpoint>>& userTallySeedCommits) const
  887. {
  888. masks.clear();
  889. messages.clear();
  890. for (size_t i = 0; i < currentUserEncryptedTallies.size(); i++)
  891. {
  892. masks.push_back(currentUserEncryptedTallies[i].mask);
  893. messages.push_back(currentUserEncryptedTallies[i].encryptedMessage);
  894. }
  895. maskCommits.clear();
  896. messageCommits.clear();
  897. userTallySeeds.clear();
  898. userTallySeedCommits.clear();
  899. for (size_t i = 0; i < permutations.size(); i++)
  900. {
  901. std::vector<Scalar> currSeeds;
  902. std::vector<Twistpoint> currRow;
  903. for (size_t j = 0; j < permutations[i].size(); j++)
  904. {
  905. currSeeds.push_back(Scalar(0));
  906. currRow.push_back(Twistpoint());
  907. }
  908. userTallySeeds.push_back(currSeeds);
  909. maskCommits.push_back(currRow);
  910. messageCommits.push_back(currRow);
  911. userTallySeedCommits.push_back(currRow);
  912. }
  913. for (size_t i = 0; i < permutations.size(); i++)
  914. {
  915. size_t last = permutations[i].size() - 1;
  916. for (size_t j = 0; j < permutations[i].size(); j++)
  917. {
  918. if (j != last)
  919. {
  920. userTallySeeds[i][j].set_random();
  921. userTallySeeds[i][last] =
  922. userTallySeeds[i][last] -
  923. userTallySeeds[i][j];
  924. }
  925. maskCommits[i][j] =
  926. masks[j] * permutations[j][i] * power +
  927. currPseudonyms[j] * power * permutations[j][i] * userTallySeeds[i][j] +
  928. elGamalBlindGenerator * userTallySeeds[i][j];
  929. messageCommits[i][j] =
  930. messages[j] * permutations[j][i] +
  931. nextGenerator * permutations[j][i] * userTallySeeds[i][j] +
  932. elGamalBlindGenerator * userTallySeeds[i][j];
  933. userTallySeedCommits[i][j] =
  934. EL_GAMAL_GENERATOR * userTallySeeds[i][j];
  935. }
  936. }
  937. }
  938. template <typename T>
  939. std::vector<std::vector<T>> PrsonaServer::generate_reordered_plus_power_matrix(
  940. const std::vector<std::vector<Scalar>>& permutations,
  941. const Scalar& power,
  942. const std::vector<T>& oldValues,
  943. std::vector<std::vector<Scalar>>& seeds,
  944. std::vector<std::vector<Twistpoint>>& seedCommits,
  945. const T& h) const
  946. {
  947. std::vector<std::vector<Scalar>> permutation_plus_power;
  948. seedCommits.clear();
  949. for (size_t i = 0; i < permutations.size(); i++)
  950. {
  951. std::vector<Scalar> currPermutations;
  952. std::vector<Twistpoint> currSeedCommits;
  953. for (size_t j = 0; j < permutations[i].size(); j++)
  954. {
  955. currPermutations.push_back(permutations[i][j] * power);
  956. currSeedCommits.push_back(Twistpoint());
  957. }
  958. permutation_plus_power.push_back(currPermutations);
  959. seedCommits.push_back(currSeedCommits);
  960. }
  961. std::vector<std::vector<T>> retval =
  962. generate_reordered_matrix<T>(
  963. permutation_plus_power,
  964. oldValues,
  965. seeds,
  966. h,
  967. true);
  968. for (size_t i = 0; i < permutations.size(); i++)
  969. for (size_t j = 0; j < permutations[i].size(); j++)
  970. seedCommits[i][j] = EL_GAMAL_GENERATOR * seeds[i][j];
  971. return retval;
  972. }
  973. template <typename T>
  974. std::vector<std::vector<T>> PrsonaServer::generate_reordered_matrix(
  975. const std::vector<std::vector<Scalar>>& permutations,
  976. const std::vector<T>& oldValues,
  977. std::vector<std::vector<Scalar>>& seeds,
  978. const T& h,
  979. bool cancelOut) const
  980. {
  981. std::vector<std::vector<T>> retval;
  982. seeds.clear();
  983. for (size_t i = 0; i < permutations.size(); i++)
  984. {
  985. std::vector<Scalar> currSeeds;
  986. std::vector<T> currRow;
  987. for (size_t j = 0; j < permutations[i].size(); j++)\
  988. {
  989. currSeeds.push_back(Scalar(0));
  990. currRow.push_back(T());
  991. }
  992. seeds.push_back(currSeeds);
  993. retval.push_back(currRow);
  994. }
  995. for (size_t i = 0; i < permutations.size(); i++)
  996. {
  997. size_t last = permutations[i].size() - 1;
  998. for (size_t j = 0; j < permutations[i].size(); j++)
  999. {
  1000. if (!cancelOut)
  1001. {
  1002. seeds[i][j].set_random();
  1003. }
  1004. else if (j != last)
  1005. {
  1006. seeds[i][j].set_random();
  1007. seeds[i][last] = seeds[i][last] - seeds[i][j];
  1008. }
  1009. retval[i][j] = oldValues[j] * permutations[j][i] + h * seeds[i][j];
  1010. }
  1011. }
  1012. return retval;
  1013. }
  1014. std::vector<size_t> PrsonaServer::sort_data(const std::vector<Twistpoint>& inputs) const
  1015. {
  1016. std::vector<size_t> retval;
  1017. // SortingType's index member allows us to replicate the "sort" across
  1018. std::vector<SortingType> sortTracker;
  1019. for (size_t i = 0; i < inputs.size(); i++)
  1020. {
  1021. SortingType curr;
  1022. curr.pseudonym = inputs[i];
  1023. curr.index = i;
  1024. sortTracker.push_back(curr);
  1025. }
  1026. std::sort(sortTracker.begin(), sortTracker.end());
  1027. for (size_t i = 0; i < inputs.size(); i++)
  1028. retval.push_back(sortTracker[i].index);
  1029. return retval;
  1030. }
  1031. bool PrsonaServer::update_data(
  1032. const std::vector<std::vector<Twistpoint>>& freshPseudonymCommits,
  1033. const std::vector<std::vector<CurveBipoint>>& serverTallyCommits,
  1034. const std::vector<std::vector<std::vector<TwistBipoint>>>& voteMatrixCommits,
  1035. const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
  1036. const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits)
  1037. {
  1038. std::vector<Twistpoint> newPseudonyms;
  1039. std::vector<CurveBipoint> newVoteTallies;
  1040. std::vector<EGCiphertext> newUserTallies;
  1041. for (size_t i = 0; i < freshPseudonymCommits.size(); i++)
  1042. {
  1043. Twistpoint pseudonymSum = freshPseudonymCommits[i][0];
  1044. CurveBipoint voteTallySum = serverTallyCommits[i][0];
  1045. Twistpoint userTallyMask, userTallyMessage;
  1046. if (!userTallyMaskCommits.empty())
  1047. {
  1048. userTallyMask = userTallyMaskCommits[i][0];
  1049. userTallyMessage = userTallyMessageCommits[i][0];
  1050. }
  1051. for (size_t j = 1; j < freshPseudonymCommits[i].size(); j++)
  1052. {
  1053. pseudonymSum = pseudonymSum + freshPseudonymCommits[i][j];
  1054. voteTallySum = voteTallySum + serverTallyCommits[i][j];
  1055. if (!userTallyMaskCommits.empty())
  1056. {
  1057. userTallyMask = userTallyMask +
  1058. userTallyMaskCommits[i][j];
  1059. userTallyMessage = userTallyMessage +
  1060. userTallyMessageCommits[i][j];
  1061. }
  1062. }
  1063. newPseudonyms.push_back(pseudonymSum);
  1064. newVoteTallies.push_back(voteTallySum);
  1065. if (!userTallyMaskCommits.empty())
  1066. {
  1067. newUserTallies.push_back(
  1068. EGCiphertext(userTallyMask, userTallyMessage));
  1069. }
  1070. }
  1071. if (!pseudonyms_sorted(newPseudonyms))
  1072. {
  1073. std::cerr << "Pseudonyms not sorted correctly." << std::endl;
  1074. return false;
  1075. }
  1076. currentPseudonyms = newPseudonyms;
  1077. previousVoteTallies = newVoteTallies;
  1078. voteMatrix = calculate_next_vote_matrix(voteMatrixCommits);
  1079. currentUserEncryptedTallies = newUserTallies;
  1080. return true;
  1081. }
  1082. bool PrsonaServer::pseudonyms_sorted(
  1083. const std::vector<Twistpoint> newPseudonyms) const
  1084. {
  1085. bool retval = true;
  1086. for (size_t i = 0; i < newPseudonyms.size() - 1; i++)
  1087. retval = retval && (newPseudonyms[i] < newPseudonyms[i + 1]);
  1088. return retval;
  1089. }
  1090. /*
  1091. * DATA MAINTENANCE
  1092. */
  1093. bool PrsonaServer::import_new_user_update(
  1094. const std::vector<Proof>& pi,
  1095. const std::vector<CurveBipoint>& otherPreviousVoteTallies,
  1096. const std::vector<Twistpoint>& otherCurrentPseudonyms,
  1097. const std::vector<EGCiphertext>& otherCurrentUserEncryptedTallies,
  1098. const std::vector<std::vector<TwistBipoint>>& otherVoteMatrix)
  1099. {
  1100. size_t newIndex = 0;
  1101. if (!currentPseudonyms.empty())
  1102. while (otherCurrentPseudonyms[newIndex] == currentPseudonyms[newIndex])
  1103. newIndex++;
  1104. Twistpoint shortTermPublicKey = otherCurrentPseudonyms[newIndex];
  1105. bool flag = verify_proof_of_added_user(
  1106. pi,
  1107. currentFreshGenerator,
  1108. shortTermPublicKey,
  1109. bgnSystem.get_public_key().get_bipoint_twistgen(),
  1110. bgnSystem.get_public_key().get_bipoint_twist_subgroup_gen(),
  1111. bgnSystem.get_public_key().get_bipoint_curvegen(),
  1112. bgnSystem.get_public_key().get_bipoint_curve_subgroup_gen(),
  1113. newIndex,
  1114. otherCurrentUserEncryptedTallies[newIndex],
  1115. otherPreviousVoteTallies[newIndex],
  1116. otherVoteMatrix);
  1117. if (!flag)
  1118. {
  1119. std::cerr << "Other server added new user invalidly, aborting." << std::endl;
  1120. return false;
  1121. }
  1122. for (size_t i = 0; i < otherCurrentPseudonyms.size(); i++)
  1123. {
  1124. if (i == newIndex)
  1125. continue;
  1126. size_t otherI = (i > newIndex ? i - 1 : i);
  1127. flag = flag && otherCurrentPseudonyms[i] ==
  1128. currentPseudonyms[otherI];
  1129. flag = flag && otherCurrentUserEncryptedTallies[i] ==
  1130. currentUserEncryptedTallies[otherI];
  1131. flag = flag && otherPreviousVoteTallies[i] ==
  1132. previousVoteTallies[otherI];
  1133. for (size_t j = 0; j < otherCurrentPseudonyms.size(); j++)
  1134. {
  1135. if (j == newIndex)
  1136. continue;
  1137. size_t otherJ = (j > newIndex ? j - 1 : j);
  1138. flag = flag && otherVoteMatrix[i][j] ==
  1139. voteMatrix[otherI][otherJ];
  1140. }
  1141. }
  1142. if (!flag)
  1143. {
  1144. std::cerr << "Other server illicitly changed other value during new user add." << std::endl;
  1145. return false;
  1146. }
  1147. previousVoteTallies = otherPreviousVoteTallies;
  1148. currentPseudonyms = otherCurrentPseudonyms;
  1149. currentUserEncryptedTallies = otherCurrentUserEncryptedTallies;
  1150. voteMatrix = otherVoteMatrix;
  1151. return true;
  1152. }
  1153. /*
  1154. * DATA SAFEKEEPING
  1155. */
  1156. /* This is what powers the "shuffle"; really, as pseudonyms get updated,
  1157. * the pseudonyms are no longer in the order prescribed by operator<().
  1158. * So, we put them (and everything else) back into that order,
  1159. * effectively shuffling them (and making lookups easier later on). */
  1160. std::vector<size_t> PrsonaServer::order_data()
  1161. {
  1162. std::vector<size_t> retval = sort_data(currentPseudonyms);
  1163. // Order all other data in the same way, for consistency
  1164. std::vector<Twistpoint> newPseudonyms;
  1165. std::vector<CurveBipoint> newVoteTallies;
  1166. std::vector<EGCiphertext> newUserEncryptedTallies;
  1167. std::vector<std::vector<TwistBipoint>> newVoteMatrix;
  1168. for (size_t i = 0; i < retval.size(); i++)
  1169. {
  1170. newPseudonyms.push_back(currentPseudonyms[retval[i]]);
  1171. newVoteTallies.push_back(previousVoteTallies[retval[i]]);
  1172. if (!currentUserEncryptedTallies.empty())
  1173. {
  1174. newUserEncryptedTallies.push_back(
  1175. currentUserEncryptedTallies[retval[i]]);
  1176. }
  1177. std::vector<TwistBipoint> currNewRow;
  1178. for (size_t j = 0; j < currentPseudonyms.size(); j++)
  1179. {
  1180. currNewRow.push_back(
  1181. voteMatrix[retval[i]][retval[j]]);
  1182. }
  1183. newVoteMatrix.push_back(currNewRow);
  1184. }
  1185. previousVoteTallies = newVoteTallies;
  1186. currentPseudonyms = newPseudonyms;
  1187. currentUserEncryptedTallies = newUserEncryptedTallies;
  1188. voteMatrix = newVoteMatrix;
  1189. return retval;
  1190. }
  1191. /*
  1192. * BINARY SEARCH
  1193. */
  1194. // Completely normal binary search
  1195. size_t PrsonaServer::binary_search(const Twistpoint& index) const
  1196. {
  1197. return PrsonaBase::binary_search(currentPseudonyms, index);
  1198. }
  1199. /*
  1200. * VALID VOTE PROOFS
  1201. */
  1202. bool PrsonaServer::verify_vote_proof(
  1203. const std::vector<Proof>& pi,
  1204. const std::vector<TwistBipoint>& oldVotes,
  1205. const std::vector<TwistBipoint>& newVotes,
  1206. const Twistpoint& shortTermPublicKey) const
  1207. {
  1208. const BGNPublicKey& pubKey = bgnSystem.get_public_key();
  1209. return PrsonaBase::verify_vote_proof(
  1210. pubKey.get_bipoint_twistgen(),
  1211. pubKey.get_bipoint_twist_subgroup_gen(),
  1212. pi,
  1213. oldVotes,
  1214. newVotes,
  1215. currentFreshGenerator,
  1216. shortTermPublicKey);
  1217. }
  1218. void PrsonaServer::print_scores(const std::vector<CurveBipoint>& scores)
  1219. {
  1220. std::cout << "[";
  1221. for (size_t i = 0; i < scores.size(); i++)
  1222. {
  1223. std::cout << bgnSystem.decrypt(scores[i])
  1224. << (i == scores.size() - 1 ? "]" : " ");
  1225. }
  1226. std::cout << std::endl;
  1227. }