server.cpp 46 KB

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