|
@@ -1,41 +1,193 @@
|
|
|
#include "server.hpp"
|
|
|
|
|
|
+extern const scalar_t bn_n;
|
|
|
+const Scalar PrsonaServer::scalarN(bn_n);
|
|
|
+extern const curvepoint_fp_t bn_curvegen;
|
|
|
+const Curvepoint PrsonaServer::elGamalGenerator(bn_curvegen);
|
|
|
+
|
|
|
PrsonaServer::PrsonaServer()
|
|
|
{
|
|
|
+ Scalar lambda;
|
|
|
+ lambda.set_random();
|
|
|
+
|
|
|
+ elGamalBlindGenerator = elGamalGenerator * lambda;
|
|
|
|
|
|
+ currentSeed.set_random();
|
|
|
}
|
|
|
|
|
|
-void PrsonaServer::add_new_client(PrsonaPublicKey longTermPublicKey)
|
|
|
+Curvepoint PrsonaServer::get_blinding_generator() const
|
|
|
{
|
|
|
-
|
|
|
+ return elGamalBlindGenerator;
|
|
|
}
|
|
|
|
|
|
-void PrsonaServer::epoch()
|
|
|
+Curvepoint PrsonaServer::get_fresh_generator() const
|
|
|
{
|
|
|
-
|
|
|
+ return elGamalGenerator * currentSeed;
|
|
|
}
|
|
|
|
|
|
-void PrsonaServer::receive_vote(vector<CurveBipoint> vote, Proof pi, PrsonaPublicKey shortTermPublicKey)
|
|
|
+Curvepoint PrsonaServer::add_new_client(const Curvepoint& longTermPublicKey)
|
|
|
{
|
|
|
-
|
|
|
+ Curvepoint newPseudonym = longTermPublicKey * currentSeed;
|
|
|
+ currentPseudonyms.push_back(newPseudonym);
|
|
|
+
|
|
|
+ TwistBipoint newTalliedVote;
|
|
|
+ encrypt(newTalliedVote, Scalar(0));
|
|
|
+ previousVoteTally.push_back(newTalliedVote);
|
|
|
+
|
|
|
+ CurveBipoint defaultVote;
|
|
|
+ encrypt(defaultVote, Scalar(0));
|
|
|
+ vector<CurveBipoint> newRow;
|
|
|
+ for (size_t i = 0; i < voteMatrix.size(); i++)
|
|
|
+ {
|
|
|
+ rerandomize(defaultVote);
|
|
|
+ voteMatrix[i].push_back(defaultVote);
|
|
|
+ rerandomize(defaultVote);
|
|
|
+ newRow.push_back(defaultVote);
|
|
|
+ }
|
|
|
+
|
|
|
+ rerandomize(defaultVote);
|
|
|
+ newRow.push_back(defaultVote);
|
|
|
+ voteMatrix.push_back(newRow);
|
|
|
+
|
|
|
+ return newPseudonym;
|
|
|
}
|
|
|
|
|
|
-void PrsonaServer::calculate_vote_tally()
|
|
|
+vector<EGCiphertext> PrsonaServer::epoch()
|
|
|
{
|
|
|
+ Scalar inverseSeed = scalarN - currentSeed;
|
|
|
+ Scalar nextSeed;
|
|
|
+ nextSeed.set_random();
|
|
|
+
|
|
|
+ vector<Quadripoint> BGNEncryptedTallies;
|
|
|
+ vector<Scalar> decryptedTallies;
|
|
|
+ vector<EGCiphertext> EGEncryptedTallies(currentPseudonyms.size());
|
|
|
+ for (size_t i = 0; i < voteMatrix.size(); i++)
|
|
|
+ {
|
|
|
+ vector<Quadripoint> currTally;
|
|
|
+
|
|
|
+ for (size_t j = 0; j < previousVoteTally.size(); j++)
|
|
|
+ {
|
|
|
+ Quadripoint curr;
|
|
|
+ homomorphic_multiplication(curr, voteMatrix[j][i], previousVoteTally[j]);
|
|
|
+ currTally.push_back(curr);
|
|
|
+ }
|
|
|
+
|
|
|
+ BGNEncryptedTallies.push_back(std::accumulate(currTally.begin(), currTally.end(), Quadripoint()));
|
|
|
+ }
|
|
|
+
|
|
|
+ for (size_t i = 0; i < currentPseudonyms.size(); i++)
|
|
|
+ {
|
|
|
+ currentPseudonyms[i] = currentPseudonyms[i] * nextSeed;
|
|
|
+ decryptedTallies.push_back(decrypt(BGNEncryptedTallies[i]));
|
|
|
+ }
|
|
|
+ shuffle_vote_matrix(decryptedTallies);
|
|
|
+
|
|
|
+ Curvepoint nextGenerator = elGamalGenerator * nextSeed;
|
|
|
+ for (size_t i = 0; i < currentPseudonyms.size(); i++)
|
|
|
+ {
|
|
|
+ Scalar currMask;
|
|
|
+ currMask.set_random();
|
|
|
+
|
|
|
+ previousVoteTally[i] = encrypt(decryptedTallies[i]);
|
|
|
+
|
|
|
+ EGEncryptedTallies[i].mask = currentPseudonyms[i] * currMask;
|
|
|
+ EGEncryptedTallies[i].encryptedMessage = (nextGenerator * currMask) + (elGamalBlindGenerator * decryptedTallies[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (size_t i = 0; i < currentPseudonyms.size(); i++)
|
|
|
+ {
|
|
|
+ currentPseudonyms[i] = currentPseudonyms[i] * inverseSeed;
|
|
|
+ EGEncryptedTallies[i].mask = EGEncryptedTallies[i].mask * inverseSeed;
|
|
|
+ }
|
|
|
+ shuffle_vote_matrix(EGEncryptedTallies);
|
|
|
+
|
|
|
+ return EGEncryptedTallies;
|
|
|
+}
|
|
|
|
|
|
+template <typename T>
|
|
|
+void PrsonaServer::shuffle_vote_matrix(vector<T>& otherVector)
|
|
|
+{
|
|
|
+ vector<sorting_t> sortTracker;
|
|
|
+ for (size_t i = 0; i < currentPseudonyms.size(); i++)
|
|
|
+ {
|
|
|
+ sorting_t curr;
|
|
|
+
|
|
|
+ curr.pseudonym = currentPseudonyms[i];
|
|
|
+ curr.index = i;
|
|
|
+
|
|
|
+ sortTracker.push_back(curr);
|
|
|
+ }
|
|
|
+
|
|
|
+ std::sort(sortTracker.begin(), sortTracker.end());
|
|
|
+
|
|
|
+ vector<Curvepoint> newPseudonyms;
|
|
|
+ vector<TwistBipoint> newVoteTallies;
|
|
|
+ vector<vector<CurveBipoint>> newVoteMatrix;
|
|
|
+ vector<T> newOtherVector;
|
|
|
+
|
|
|
+ for (size_t i = 0; i < currentPseudonyms.size(); i++)
|
|
|
+ {
|
|
|
+ newPseudonyms.push_back(sortTracker[i].pseudonym);
|
|
|
+ newVoteTallies.push_back(previousVoteTally[sortTracker[i].index]);
|
|
|
+ newOtherVector.push_back(otherVector[sortTracker[i].index]);
|
|
|
+
|
|
|
+ vector<CurveBipoint> currNewRow;
|
|
|
+ for (size_t j = 0; j < currentPseudonyms.size(); j++)
|
|
|
+ {
|
|
|
+ currNewRow.push_back(voteMatrix[sortTracker[i].index][sortTracker[j].index]);
|
|
|
+ }
|
|
|
+ newVoteMatrix.push_back(currNewRow);
|
|
|
+ }
|
|
|
+
|
|
|
+ currentPseudonyms = newPseudonyms;
|
|
|
+ previousVoteTally = newVoteTallies;
|
|
|
+ voteMatrix = newVoteMatrix;
|
|
|
+ otherVector = newOtherVector;
|
|
|
+
|
|
|
+ rerandomize_vote_matrix();
|
|
|
}
|
|
|
|
|
|
void PrsonaServer::rerandomize_vote_matrix()
|
|
|
{
|
|
|
-
|
|
|
+ for (size_t i = 0; i < voteMatrix.size(); i++)
|
|
|
+ {
|
|
|
+ for (size_t j = 0; j < voteMatrix[0].size(); j++)
|
|
|
+ {
|
|
|
+ voteMatrix[i][j] = rerandomize(voteMatrix[i][j]);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void PrsonaServer::distribute_new_scores()
|
|
|
+void PrsonaServer::receive_vote(const Proof& pi, const vector<CurveBipoint>& votes, const Curvepoint& shortTermPublicKey)
|
|
|
{
|
|
|
+ if (!verify_vote_proof(pi, votes, shortTermPublicKey))
|
|
|
+ return;
|
|
|
|
|
|
+ size_t voteSubmitter = binary_search(shortTermPublicKey);
|
|
|
+ voteMatrix[voteSubmitter] = votes;
|
|
|
+ rerandomize_vote_matrix();
|
|
|
+}
|
|
|
+
|
|
|
+size_t PrsonaServer::binary_search(const Curvepoint& index) const
|
|
|
+{
|
|
|
+ size_t lo, hi;
|
|
|
+ lo = 0;
|
|
|
+ hi = currentPseudonyms.size() - 1;
|
|
|
+
|
|
|
+ while (lo < hi)
|
|
|
+ {
|
|
|
+ size_t mid = (lo + hi) / 2;
|
|
|
+ if (currentPseudonyms[mid] < index)
|
|
|
+ lo = mid + 1;
|
|
|
+ else if (index == currentPseudonyms[mid])
|
|
|
+ return mid;
|
|
|
+ else hi = mid - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return lo;
|
|
|
}
|
|
|
|
|
|
-bool PrsonaServer::verify_vote_proof(CurveBipoint vote, Proof pi, PrsonaPublicKey shortTermPublicKey)
|
|
|
+bool PrsonaServer::verify_vote_proof(const Proof& pi, const vector<CurveBipoint>& votes, const Curvepoint& shortTermPublicKey) const
|
|
|
{
|
|
|
|
|
|
}
|