Browse Source

Added ability for users to verify servers correctly added them

tristangurtler 3 years ago
parent
commit
beb6c7aa14

+ 4 - 2
prsona/Makefile

@@ -81,11 +81,11 @@ $(666_OBJ_PATH)/%_c_with_as.o: $(666_SRC_PATH)/%.c $(666_INC_PATH)/%.h
 $(666_OBJ_PATH)/%_as.o: $(666_SRC_PATH)/%.s
 	$(CC) $(CFLAGS) -fPIC -c -o $@ $^
 
-$(BGN_OBJ_PATH)/bgn.a: $(BGN_OBJ) $(666_AS_OBJ) $(666_C_OBJ)
+$(BGN_OBJ_PATH)/bgn.a: $(666_AS_OBJ) $(666_C_OBJ) $(BGN_OBJ)
 	rm -f $@
 	ar cr $@ $^
 
-$(BGN_OBJ_PATH)/bgn.test.a: $(BGN_TEST_OBJ) $(666_AS_OBJ) $(666_C_OBJ)
+$(BGN_OBJ_PATH)/bgn.test.a: $(666_AS_OBJ) $(666_C_OBJ) $(BGN_TEST_OBJ)
 	rm -f $@
 	ar cr $@ $^
 
@@ -99,6 +99,8 @@ $(PRSONA_BIN_PATH)/test: $(PRSONA_OBJ_PATH)/main.test.o $(PRSONA_TEST_OBJ) $(BGN
 
 clean: prsona_clean bgn_clean 666_clean 
 
+pclean: prsona_clean
+
 prsona_clean: 
 	-rm $(PRSONA_BIN_PATH)/*
 	-rm $(PRSONA_OBJ_PATH)/*

+ 41 - 15
prsona/inc/base.hpp

@@ -13,7 +13,7 @@
 class PrsonaBase {
     public:
         static size_t MAX_ALLOWED_VOTE;
-        
+
         // SETUP FUNCTIONS
         static void init();
         static void set_server_malicious();
@@ -43,6 +43,10 @@ class PrsonaBase {
             const Curvepoint& currGenerator,
             size_t numServers);
 
+        // BINARY SEARCH
+        size_t binary_search(
+            const std::vector<Curvepoint> list, const Curvepoint& index) const;
+
         // SCHNORR PROOFS
         Proof schnorr_generation(
             const Curvepoint& generator,
@@ -122,28 +126,50 @@ class PrsonaBase {
             const Curvepoint& owner
         ) const;
 
-        // EPOCH PROOFS
-        bool verify_update_proof(
-            const Proof& pi
+        // NEW USER PROOFS
+        std::vector<Proof> generate_proof_of_added_user(
+            const Scalar& twistBipointSeed,
+            const Scalar& EGCiphertextSeed,
+            const std::vector<Scalar>& curveBipointSelfSeeds,
+            const std::vector<Scalar>& curveBipointOtherSeeds
         ) const;
 
-        // SERVER AGREEMENT PROOFS
-        Proof generate_valid_default_tally_proof() const;
-        Proof generate_valid_fresh_generator_proof() const;
-        Proof generate_votes_valid_proof() const;
+        bool verify_proof_of_added_user(
+            const std::vector<Proof>& pi,
+            const Curvepoint& currentFreshGenerator,
+            const Curvepoint& shortTermPublicKey,
+            const Curvepoint& elGamalBlindGenerator,
+            const CurveBipoint& curveG,
+            const CurveBipoint& curveH,
+            const TwistBipoint& twistG,
+            const TwistBipoint& twistH,
+            size_t selfIndex,
+            const EGCiphertext& userEncryptedScore,
+            const TwistBipoint& serverEncryptedScore,
+            const std::vector<std::vector<CurveBipoint>> encryptedVoteMatrix
+        ) const;
+
+        // EPOCH PROOFS
         Proof generate_proof_of_added_user() const;
-        Proof generate_score_proof() const;
         Proof generate_proof_of_correct_tally() const;
         Proof generate_proof_of_correct_sum() const;
         Proof generate_proof_of_shuffle() const;
-        Proof generate_valid_pseudonyms_proof() const;
 
-        bool verify_valid_tally_proof(const Proof& pi) const;
-        bool verify_score_proof(const Proof& pi) const;
-        bool verify_default_tally_proof(const Proof& pi) const;
-        bool verify_default_votes_proof(const Proof& pi) const;
-        bool verify_valid_votes_proof(const Proof& pi) const;
+        bool verify_update_proof(const Proof& pi) const;
+
+        // SERVER AGREEMENT PROOFS
+        Proof generate_valid_user_tally_proof() const;
+        Proof generate_valid_server_tally_proof() const;
+        Proof generate_valid_vote_row_proof() const;
+        Proof generate_valid_vote_matrix_proof() const;
+        Proof generate_valid_pseudonyms_proof() const;
+        
+        bool verify_valid_user_tally_proof(const Proof& pi) const;
+        bool verify_valid_server_tally_proof(const Proof& pi) const;
+        bool verify_valid_vote_row_proof(const Proof& pi) const;
+        bool verify_valid_vote_matrix_proof(const Proof& pi) const;
         bool verify_valid_pseudonyms_proof(const Proof& pi) const;
+
 };
 
 #endif

+ 5 - 8
prsona/inc/client.hpp

@@ -20,12 +20,13 @@ class PrsonaClient : public PrsonaBase {
     public:
         // CONSTRUCTORS
         PrsonaClient(
-            const BGNPublicKey& serverPublicKey,
             const std::vector<Proof>& generatorProof,
             const Curvepoint& elGamalBlindGenerator,
+            const BGNPublicKey& serverPublicKey,
             const PrsonaServerEntity* servers);
 
         // BASIC PUBLIC SYSTEM INFO GETTERS
+        Curvepoint get_short_term_public_key() const;
         Curvepoint get_short_term_public_key(Proof &pi) const;
 
         // SERVER INTERACTIONS
@@ -38,7 +39,8 @@ class PrsonaClient : public PrsonaBase {
         ) const;
         bool receive_fresh_generator(
             const std::vector<Proof>& pi, const Curvepoint& freshGenerator);
-        void receive_vote_tally(const Proof& pi, const EGCiphertext& score);
+        bool receive_vote_tally();
+        bool receive_new_user_data(const std::vector<Proof>& pi);
 
         // REPUTATION PROOFS
         std::vector<Proof> generate_reputation_proof(
@@ -53,11 +55,6 @@ class PrsonaClient : public PrsonaBase {
         // NEEDED FOR TESTING PROOFS
         Scalar get_score() const;
 
-    protected:
-        // REQUIRED BY BASE CLASS
-        EGCiphertext get_current_tally(
-            Proof& pi, const Curvepoint& shortTermPublicKey) const;
-
     private:
         // Constants for clients
         static bool SERVER_IS_MALICIOUS;
@@ -84,7 +81,7 @@ class PrsonaClient : public PrsonaBase {
         Scalar max_checked;
 
         // SCORE DECRYPTION
-        void decrypt_score(const EGCiphertext& score);
+        Scalar decrypt_score(const EGCiphertext& score);
 
         // OWNERSHIP OF STPK PROOFS
         Proof generate_ownership_proof() const;

+ 11 - 4
prsona/inc/proof.hpp

@@ -10,14 +10,21 @@
 
 #include "Scalar.hpp"
 #include "Curvepoint.hpp"
+#include "Bipoint.hpp"
 
 class Proof {
     public:
         Proof();
-        Proof(std::string basic);
-        
-        std::string basic;
-        std::vector<Curvepoint> partialUniversals;
+        Proof(std::string hbc);
+    
+        // HBC security
+        std::string hbc;
+
+        // Malicious security
+        std::vector<Curvepoint> curvepointUniversals;
+        std::vector<CurveBipoint> curveBipointUniversals;
+        std::vector<TwistBipoint> twistBipointUniversals;
+
         std::vector<Scalar> challengeParts;
         std::vector<Scalar> responseParts;
 };

+ 7 - 6
prsona/inc/server.hpp

@@ -33,14 +33,18 @@ class PrsonaServer : public PrsonaBase {
         // ENCRYPTED DATA GETTERS
         std::vector<CurveBipoint> get_current_votes_by(
             Proof& pi, const Curvepoint& shortTermPublicKey) const;
-        EGCiphertext get_current_tally(
+        std::vector<std::vector<CurveBipoint>> get_all_current_votes(
+            Proof& pi) const;
+        EGCiphertext get_current_user_encrypted_tally(
+            Proof& pi, const Curvepoint& shortTermPublicKey) const;
+        TwistBipoint get_current_server_encrypted_tally(
             Proof& pi, const Curvepoint& shortTermPublicKey) const;
         std::vector<Curvepoint> get_current_pseudonyms(Proof& pi) const;
 
         // CLIENT INTERACTIONS
         void add_new_client(
+            std::vector<Proof>& proofOfValidAddition,
             const Proof& proofOfValidKey,
-            Proof& proofOfValidAddition,
             const Curvepoint& shortTermPublicKey);
         bool receive_vote(
             const std::vector<Proof>& pi,
@@ -63,7 +67,6 @@ class PrsonaServer : public PrsonaBase {
         std::vector<TwistBipoint> previousVoteTallies;
         std::vector<Curvepoint> currentPseudonyms;
         std::vector<EGCiphertext> currentUserEncryptedTallies;
-        std::vector<Proof> currentTallyProofs;
         std::vector<std::vector<CurveBipoint>> voteMatrix;
 
         /**
@@ -90,7 +93,7 @@ class PrsonaServer : public PrsonaBase {
             const Curvepoint& currGenerator);
         
         // SCORE TALLYING
-        std::vector<Scalar> tally_scores(std::vector<Proof>& tallyProofs);
+        std::vector<Scalar> tally_scores();
         Scalar get_max_possible_score(Proof& pi);
         
         // EPOCH ROUNDS
@@ -105,14 +108,12 @@ class PrsonaServer : public PrsonaBase {
             const std::vector<TwistBipoint>& otherPreviousVoteTally,
             const std::vector<Curvepoint>& otherCurrentPseudonyms,
             const std::vector<EGCiphertext>& otherCurrentUserEncryptedTallies,
-            const std::vector<Proof>& otherCurrentTallyProofs,
             const std::vector<std::vector<CurveBipoint>>& otherVoteMatrix
         );
         void export_updates(
             std::vector<TwistBipoint>& otherPreviousVoteTally,
             std::vector<Curvepoint>& otherCurrentPseudonyms,
             std::vector<EGCiphertext>& otherCurrentUserEncryptedTallies,
-            std::vector<Proof>& otherCurrentTallyProofs,
             std::vector<std::vector<CurveBipoint>>& otherVoteMatrix
         ) const;
 

+ 19 - 3
prsona/inc/serverEntity.hpp

@@ -35,10 +35,22 @@ class PrsonaServerEntity {
             Proof& pi, const Curvepoint& shortTermPublicKey) const;
         std::vector<CurveBipoint> get_current_votes_by(
             Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const;
-        EGCiphertext get_current_tally(
+        std::vector<std::vector<CurveBipoint>> get_all_current_votes(
+            Proof& pi) const;
+        std::vector<std::vector<CurveBipoint>> get_all_current_votes(
+            Proof& pi, size_t which) const;
+        EGCiphertext get_current_user_encrypted_tally(
             Proof& pi, const Curvepoint& shortTermPublicKey) const;
-        EGCiphertext get_current_tally(
+        EGCiphertext get_current_user_encrypted_tally(
             Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const;
+        TwistBipoint get_current_server_encrypted_tally(
+            Proof& pi, const Curvepoint& shortTermPublicKey) const;
+        TwistBipoint get_current_server_encrypted_tally(
+            Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const;
+        std::vector<Curvepoint> get_current_pseudonyms(
+            Proof& pi) const;
+        std::vector<Curvepoint> get_current_pseudonyms(
+            Proof& pi, size_t which) const;
 
         // CLIENT INTERACTIONS
         void add_new_client(PrsonaClient& newUser);
@@ -52,6 +64,8 @@ class PrsonaServerEntity {
             const std::vector<CurveBipoint>& newVotes,
             const Curvepoint& shortTermPublicKey,
             size_t which);
+        void transmit_new_user_data(
+            const std::vector<Proof>& pi, PrsonaClient& newUser) const;
         void transmit_updates(PrsonaClient& currUser) const;
         void transmit_updates(PrsonaClient& currUser, size_t which) const;
 
@@ -59,12 +73,14 @@ class PrsonaServerEntity {
         void epoch(Proof& pi);
         void epoch(Proof& pi, size_t which);
 
+        void print_scores() const;
+        void print_votes() const;
+
     private:
         std::vector<PrsonaServer> servers;
 
         // SCORE TALLYING
         std::vector<EGCiphertext> tally_scores(
-            std::vector<Proof>& tallyProofs,
             const Curvepoint& nextGenerator,
             size_t which);
         

+ 214 - 85
prsona/src/base.cpp

@@ -107,6 +107,33 @@ bool PrsonaBase::set_EG_blind_generator(
     return true;
 }
 
+/*
+ * BINARY SEARCH
+ */
+
+/* Completely normal binary search
+ * There might be a standard function for this in <algorithms>?
+ * But it returns an iterator, not a size_t, so less useful. */
+size_t PrsonaBase::binary_search(
+    const std::vector<Curvepoint> list, const Curvepoint& index) const
+{
+    size_t lo, hi;
+    lo = 0;
+    hi = list.size() - 1;
+
+    while (lo < hi)
+    {
+        size_t mid = (lo + hi) / 2;
+        if (list[mid] < index)
+            lo = mid + 1;
+        else if (index == list[mid])
+            return mid;
+        else hi = mid - 1;
+    }
+
+    return lo;
+}
+
 /*
  * SCHNORR PROOFS
  */
@@ -162,7 +189,7 @@ Proof PrsonaBase::generate_ownership_proof(
     if (!CLIENT_IS_MALICIOUS)
     {
         Proof retval;
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
 
         return retval;
     }
@@ -176,7 +203,7 @@ bool PrsonaBase::verify_ownership_proof(
     const Curvepoint& commitment) const
 {
     if (!CLIENT_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+        return pi.hbc == "PROOF";
 
     Scalar c = pi.challengeParts[0];
     Scalar z = pi.responseParts[0];
@@ -195,14 +222,14 @@ Proof PrsonaBase::add_to_generator_proof(
     Proof retval;
     if (!CLIENT_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
     Curvepoint nextGenerator = currGenerator * seed;
     retval = schnorr_generation(currGenerator, nextGenerator, seed);
 
-    retval.partialUniversals.push_back(currGenerator);
+    retval.curvepointUniversals.push_back(currGenerator);
     return retval;
 }
 
@@ -219,20 +246,20 @@ bool PrsonaBase::verify_generator_proof(
     if (!SERVER_IS_MALICIOUS)
     {
         for (size_t i = 0; i < pi.size(); i++)
-            retval = retval && pi[i].basic == "PROOF";
+            retval = retval && pi[i].hbc == "PROOF";
 
         return retval;
     }
 
-    if (pi[0].partialUniversals[0] != EL_GAMAL_GENERATOR)
+    if (pi[0].curvepointUniversals[0] != EL_GAMAL_GENERATOR)
         return false;
 
     for (size_t i = 0; i < pi.size(); i++)
     {
-        Curvepoint generator = pi[i].partialUniversals[0];
+        Curvepoint generator = pi[i].curvepointUniversals[0];
         Curvepoint commitment = (i == pi.size() - 1 ?
                                     currGenerator :
-                                    pi[i + 1].partialUniversals[0]);
+                                    pi[i + 1].curvepointUniversals[0]);
         Scalar c = pi[i].challengeParts[0];
         Scalar z = pi[i].responseParts[0];
 
@@ -316,7 +343,7 @@ std::vector<Proof> PrsonaBase::generate_reputation_proof(
         r = masksPerBit[i];
         
         c = g * r + h * m;
-        currProof.partialUniversals.push_back(c);
+        currProof.curvepointUniversals.push_back(c);
 
         c_a = g * s + h * a;
 
@@ -374,14 +401,14 @@ bool PrsonaBase::verify_reputation_proof(
     }
 
     if (!CLIENT_IS_MALICIOUS)
-        return pi[0].basic == "PROOF";
+        return pi[0].hbc == "PROOF";
 
-    Scalar c, z;
-    c = pi[0].challengeParts[0];
-    z = pi[0].responseParts[0];
+    Scalar ownerChallenge, ownerResponse;
+    ownerChallenge = pi[0].challengeParts[0];
+    ownerResponse = pi[0].responseParts[0];
 
     // User should be able to prove they are who they say they are
-    if (!schnorr_verification(generator, owner, c, z))
+    if (!schnorr_verification(generator, owner, ownerChallenge, ownerResponse))
     {
         std::cerr << "Schnorr proof failed, aborting." << std::endl;
         return false;
@@ -393,7 +420,7 @@ bool PrsonaBase::verify_reputation_proof(
     for (size_t i = 1; i < pi.size(); i++)
     {
         Curvepoint c, g, h;
-        c = pi[i].partialUniversals[0];
+        c = pi[i].curvepointUniversals[0];
         g = commitment.mask;
         h = elGamalBlindGenerator;
 
@@ -493,8 +520,7 @@ std::vector<Proof> PrsonaBase::generate_vote_proof(
             power =
                 power.curveSub((a.curveAdd(a).curveAdd(a)).curveMult(votes[i]));
             CurveBipoint C_b = g * power + h * t_1;
-            currProof.partialUniversals.push_back(C_b[0]);
-            currProof.partialUniversals.push_back(C_b[1]);
+            currProof.curveBipointUniversals.push_back(C_b);
 
             CurveBipoint C_c = g * a.curveMult(a.curveMult(votes[i])) +
                                 h * t_2;
@@ -544,8 +570,7 @@ std::vector<Proof> PrsonaBase::generate_vote_proof(
                 newEncryptedVotes[i] * c_n;
 
             CurveBipoint C_b = g * commitmentLambda_1 + h * commitmentLambda_2;
-            currProof.partialUniversals.push_back(C_b[0]);
-            currProof.partialUniversals.push_back(C_b[1]);
+            currProof.curveBipointUniversals.push_back(C_b);
 
             Scalar f_c_n = f.curveSub(c_n);
             Scalar c_n2_f = c_n.curveAdd(c_n).curveSub(f);
@@ -592,7 +617,7 @@ bool PrsonaBase::verify_vote_proof(
 
     // Base case
     if (!CLIENT_IS_MALICIOUS)
-        return pi[0].basic == "PROOF";
+        return pi[0].hbc == "PROOF";
 
     // User should be able to prove they are who they say they are
     if (!verify_ownership_proof(pi[0], freshGenerator, owner))
@@ -611,11 +636,8 @@ bool PrsonaBase::verify_vote_proof(
     for (size_t i = 1; i < pi.size(); i++)
     {
         size_t voteIndex = i - 1;
-        Curvepoint C_b_0, C_b_1;
-        C_b_0 = pi[i].partialUniversals[0];
-        C_b_1 = pi[i].partialUniversals[1];
-
-        CurveBipoint C_b(C_b_0, C_b_1);
+        CurveBipoint C_b;
+        C_b = pi[i].curveBipointUniversals[0];
 
         Scalar c_r, c_n, z_r, f, z_na, z_nb;
         c_r = pi[i].challengeParts[0];
@@ -651,131 +673,246 @@ bool PrsonaBase::verify_vote_proof(
 }
 
 /*
- * EPOCH PROOFS
+ * NEW USER PROOFS
  */
 
-bool PrsonaBase::verify_update_proof(
-    const Proof& pi) const
+std::vector<Proof> PrsonaBase::generate_proof_of_added_user(
+    const Scalar& twistBipointSeed,
+    const Scalar& EGCiphertextSeed,
+    const std::vector<Scalar>& curveBipointSelfSeeds,
+    const std::vector<Scalar>& curveBipointOtherSeeds) const
 {
+    std::vector<Proof> retval;
+
     if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+    {
+        retval.push_back(Proof("PROOF"));
+        return retval;
+    }
 
-    return pi.basic == "PROOF";
-}
+    Proof currProof;
+    currProof.responseParts.push_back(twistBipointSeed);
+    retval.push_back(currProof);
 
-/*
- * SERVER AGREEMENT PROOFS
- */
+    currProof.responseParts.clear();
+    currProof.responseParts.push_back(EGCiphertextSeed);
+    retval.push_back(currProof);
+
+    currProof.responseParts.clear();
+    for (size_t i = 0; i < curveBipointSelfSeeds.size(); i++)
+        currProof.responseParts.push_back(curveBipointSelfSeeds[i]);
+    retval.push_back(currProof);
 
-Proof PrsonaBase::generate_valid_default_tally_proof() const
+    currProof.responseParts.clear();
+    for (size_t i = 0; i < curveBipointOtherSeeds.size(); i++)
+        currProof.responseParts.push_back(curveBipointOtherSeeds[i]);
+    retval.push_back(currProof);
+
+    return retval;
+}
+
+bool PrsonaBase::verify_proof_of_added_user(
+    const std::vector<Proof>& pi,
+    const Curvepoint& currentFreshGenerator,
+    const Curvepoint& shortTermPublicKey,
+    const Curvepoint& elGamalBlindGenerator,
+    const CurveBipoint& curveG,
+    const CurveBipoint& curveH,
+    const TwistBipoint& twistG,
+    const TwistBipoint& twistH,
+    size_t selfIndex,
+    const EGCiphertext& userEncryptedScore,
+    const TwistBipoint& serverEncryptedScore,
+    const std::vector<std::vector<CurveBipoint>> encryptedVoteMatrix) const
 {
-    Proof retval;
+    if (pi.empty())
+    {
+        std::cerr << "Proof empty." << std::endl;
+        return false;
+    }
 
     if (!SERVER_IS_MALICIOUS)
+        return pi[0].hbc == "PROOF";
+
+    Scalar currSeed = pi[0].responseParts[0];
+    if (serverEncryptedScore !=
+        twistG * DEFAULT_TALLY + twistH * currSeed)
     {
-        retval.basic = "PROOF";
-        return retval;
+        std::cerr << "Issue in server encrypted score." << std::endl;
+        return false;
     }
 
-    retval.basic = "PROOF";
-    return retval;
+    currSeed = pi[1].responseParts[0];
+    if (userEncryptedScore.mask != shortTermPublicKey * currSeed)
+    {
+        std::cerr << "Issue in user encrypted score: mask." << std::endl;
+        return false;
+    }
+    if (userEncryptedScore.encryptedMessage !=
+        currentFreshGenerator * currSeed + elGamalBlindGenerator * DEFAULT_TALLY)
+    {
+        std::cerr << "Issue in user encrypted score: value." << std::endl;
+        return false;
+    }
+    
+    for (size_t i = 0; i < pi[2].responseParts.size(); i++)
+    {
+        CurveBipoint currVote = encryptedVoteMatrix[selfIndex][i];
+        currSeed = pi[2].responseParts[i];
+
+        if (i == selfIndex)
+        {
+            if (currVote !=
+                curveG * Scalar(MAX_ALLOWED_VOTE) + curveH * currSeed)
+            {
+                std::cerr << "Issue in self vote." << std::endl;
+                return false;
+            }
+        }
+        else
+        {
+            if (currVote !=
+                curveG * DEFAULT_VOTE + curveH * currSeed)
+            {
+                std::cerr << "Issue in vote by verifier for user " << i + 1
+                    << " of " << pi[2].responseParts.size() << "." << std::endl;
+                return false;
+            }
+        }
+    }
+
+    for (size_t i = 0; i < pi[3].responseParts.size(); i++)
+    {
+        CurveBipoint currVote = encryptedVoteMatrix[i][selfIndex];
+        currSeed = pi[3].responseParts[i];
+
+        if (i != selfIndex)
+        {
+            if (currVote !=
+                curveG * DEFAULT_VOTE + curveH * currSeed)
+            {
+                std::cerr << "Issue in vote for verifier by user " << i + 1
+                    << " of " << pi[3].responseParts.size() << "." << std::endl;
+                return false;
+            }
+        }
+    }
+
+    return true;
 }
 
-Proof PrsonaBase::generate_valid_fresh_generator_proof() const
+/*
+ * EPOCH PROOFS
+ */
+
+Proof PrsonaBase::generate_proof_of_correct_tally() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-Proof PrsonaBase::generate_votes_valid_proof() const
+Proof PrsonaBase::generate_proof_of_correct_sum() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-Proof PrsonaBase::generate_proof_of_added_user() const
+Proof PrsonaBase::generate_proof_of_shuffle() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-Proof PrsonaBase::generate_score_proof() const
+bool PrsonaBase::verify_update_proof(
+    const Proof& pi) const
+{
+    if (!SERVER_IS_MALICIOUS)
+        return pi.hbc == "PROOF";
+
+    return pi.hbc == "PROOF";
+}
+
+/*
+ * SERVER AGREEMENT PROOFS
+ */
+
+Proof PrsonaBase::generate_valid_user_tally_proof() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-Proof PrsonaBase::generate_proof_of_correct_tally() const
+Proof PrsonaBase::generate_valid_server_tally_proof() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-Proof PrsonaBase::generate_proof_of_correct_sum() const
+Proof PrsonaBase::generate_valid_vote_row_proof() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-Proof PrsonaBase::generate_proof_of_shuffle() const
+Proof PrsonaBase::generate_valid_vote_matrix_proof() const
 {
     Proof retval;
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
@@ -785,58 +922,50 @@ Proof PrsonaBase::generate_valid_pseudonyms_proof() const
 
     if (!SERVER_IS_MALICIOUS)
     {
-        retval.basic = "PROOF";
+        retval.hbc = "PROOF";
         return retval;
     }
 
-    retval.basic = "PROOF";
+    retval.hbc = "PROOF";
     return retval;
 }
 
-bool PrsonaBase::verify_valid_tally_proof(const Proof& pi) const
-{
-    if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
-
-    return pi.basic == "PROOF";
-}
-
-bool PrsonaBase::verify_score_proof(const Proof& pi) const
+bool PrsonaBase::verify_valid_user_tally_proof(const Proof& pi) const
 {
     if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+        return pi.hbc == "PROOF";
 
-    return pi.basic == "PROOF";
+    return pi.hbc == "PROOF";
 }
 
-bool PrsonaBase::verify_default_tally_proof(const Proof& pi) const
+bool PrsonaBase::verify_valid_server_tally_proof(const Proof& pi) const
 {
     if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+        return pi.hbc == "PROOF";
 
-    return pi.basic == "PROOF";
+    return pi.hbc == "PROOF";
 }
 
-bool PrsonaBase::verify_default_votes_proof(const Proof& pi) const
+bool PrsonaBase::verify_valid_vote_row_proof(const Proof& pi) const
 {
     if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+        return pi.hbc == "PROOF";
 
-    return pi.basic == "PROOF";
+    return pi.hbc == "PROOF";
 }
 
-bool PrsonaBase::verify_valid_votes_proof(const Proof& pi) const
+bool PrsonaBase::verify_valid_vote_matrix_proof(const Proof& pi) const
 {
     if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+        return pi.hbc == "PROOF";
 
-    return pi.basic == "PROOF";
+    return pi.hbc == "PROOF";
 }
 
 bool PrsonaBase::verify_valid_pseudonyms_proof(const Proof& pi) const
 {
     if (!SERVER_IS_MALICIOUS)
-        return pi.basic == "PROOF";
+        return pi.hbc == "PROOF";
 
-    return pi.basic == "PROOF";
+    return pi.hbc == "PROOF";
 }

+ 94 - 17
prsona/src/client.cpp

@@ -12,9 +12,9 @@
  */
 
 PrsonaClient::PrsonaClient(
-    const BGNPublicKey& serverPublicKey,
     const std::vector<Proof>& generatorProof,
     const Curvepoint& elGamalBlindGenerator,
+    const BGNPublicKey& serverPublicKey,
     const PrsonaServerEntity* servers)
     : serverPublicKey(serverPublicKey),
         servers(servers),
@@ -33,6 +33,11 @@ PrsonaClient::PrsonaClient(
  * BASIC PUBLIC SYSTEM INFO GETTERS
  */
 
+Curvepoint PrsonaClient::get_short_term_public_key() const
+{
+    return currentFreshGenerator * longTermPrivateKey;
+}
+
 Curvepoint PrsonaClient::get_short_term_public_key(Proof &pi) const
 {
     pi = generate_ownership_proof();
@@ -58,7 +63,7 @@ std::vector<CurveBipoint> PrsonaClient::make_votes(
     std::vector<Scalar> seeds(oldEncryptedVotes.size());
     std::vector<CurveBipoint> newEncryptedVotes(oldEncryptedVotes.size());
 
-    if (!verify_valid_votes_proof(serverProof))
+    if (!verify_valid_vote_row_proof(serverProof))
     {
         std::cerr << "Could not verify proof of valid votes." << std::endl;
         return newEncryptedVotes;
@@ -68,7 +73,8 @@ std::vector<CurveBipoint> PrsonaClient::make_votes(
     {
         if (replaces[i])
         {
-            newEncryptedVotes[i] = serverPublicKey.encrypt(seeds[i], votes[i]);
+            newEncryptedVotes[i] =
+                serverPublicKey.curveEncrypt(seeds[i], votes[i]);
         }
         else
         {
@@ -94,17 +100,91 @@ bool PrsonaClient::receive_fresh_generator(
 }
 
 // Receive a new encrypted score from the servers (each epoch)
-void PrsonaClient::receive_vote_tally(
-    const Proof& pi, const EGCiphertext& score)
+bool PrsonaClient::receive_vote_tally()
 {
-    if (!verify_valid_tally_proof(pi))
+    Proof pi;
+    Curvepoint shortTermPublicKey = get_short_term_public_key();
+    EGCiphertext score =
+        servers->get_current_user_encrypted_tally(pi, shortTermPublicKey);
+
+    if (!verify_valid_user_tally_proof(pi))
     {
         std::cerr << "Could not verify proof of valid tally." << std::endl;
-        return;
+        return false;
     }
 
     currentEncryptedScore = score;
-    decrypt_score(score);
+    currentScore = decrypt_score(score);
+    return true;
+}
+
+bool PrsonaClient::receive_new_user_data(const std::vector<Proof>& mainProof)
+{
+    Proof currProof;
+    Curvepoint shortTermPublicKey = get_short_term_public_key();
+    
+    EGCiphertext userEncryptedScore =
+        servers->get_current_user_encrypted_tally(currProof, shortTermPublicKey);
+    if (!verify_valid_user_tally_proof(currProof))
+    {
+        std::cerr << "Could not verify preliminary proof of user encrypted tally." << std::endl;
+        return false;
+    }
+
+    TwistBipoint serverEncryptedScore =
+        servers->get_current_server_encrypted_tally(currProof, shortTermPublicKey);
+    if (!verify_valid_server_tally_proof(currProof))
+    {
+        std::cerr << "Could not verify preliminary proof of server encrypted tally." << std::endl;
+        return false;
+    }
+
+    std::vector<std::vector<CurveBipoint>> encryptedVoteMatrix = 
+        servers->get_all_current_votes(currProof);
+    if (!verify_valid_vote_matrix_proof(currProof))
+    {
+        std::cerr << "Could not verify preliminary proof of encrypted votes." << std::endl;
+        return false;
+    }
+
+    std::vector<Curvepoint> currentPseudonyms = 
+        servers->get_current_pseudonyms(currProof);
+    if (!verify_valid_pseudonyms_proof(currProof))
+    {
+        std::cerr << "Could not verify preliminary proof of pseudonyms." << std::endl;
+        return false;
+    }
+
+    size_t selfIndex = binary_search(currentPseudonyms, shortTermPublicKey);
+    if (currentPseudonyms[selfIndex] != shortTermPublicKey)
+    {
+        std::cerr << "Was not added to list of pseudonyms." << std::endl;
+        return false;
+    }
+
+    bool flag = verify_proof_of_added_user(
+        mainProof,
+        currentFreshGenerator,
+        shortTermPublicKey,
+        elGamalBlindGenerator,
+        serverPublicKey.get_bipoint_curvegen(),
+        serverPublicKey.get_bipoint_curve_subgroup_gen(),
+        serverPublicKey.get_bipoint_twistgen(),
+        serverPublicKey.get_bipoint_twist_subgroup_gen(),
+        selfIndex,
+        userEncryptedScore,
+        serverEncryptedScore,
+        encryptedVoteMatrix);
+
+    if (!flag)
+    {
+        std::cerr << "There was an issue verifying the proof; this user was not properly added." << std::endl;
+        return false;
+    }
+
+    currentEncryptedScore = userEncryptedScore;
+    currentScore = decrypt_score(userEncryptedScore);
+    return true;
 }
 
 /*
@@ -133,9 +213,9 @@ bool PrsonaClient::verify_reputation_proof(
 {
     Proof serverProof;
     EGCiphertext encryptedScore =
-        servers->get_current_tally(serverProof, shortTermPublicKey);
+        servers->get_current_user_encrypted_tally(serverProof, shortTermPublicKey);
 
-    if (!verify_valid_tally_proof(serverProof))
+    if (!verify_valid_user_tally_proof(serverProof))
     {
         std::cerr << "Error getting score from server, aborting." << std::endl;
         return false;
@@ -159,7 +239,7 @@ Scalar PrsonaClient::get_score() const
  */
 
 // Basic memoized score decryption
-void PrsonaClient::decrypt_score(const EGCiphertext& score)
+Scalar PrsonaClient::decrypt_score(const EGCiphertext& score)
 {
     Curvepoint s, hashedDecrypted;
 
@@ -170,10 +250,7 @@ void PrsonaClient::decrypt_score(const EGCiphertext& score)
     // Check if it's a value we've already seen
     auto lookup = decryption_memoizer.find(hashedDecrypted);
     if (lookup != decryption_memoizer.end())
-    {
-        currentScore = lookup->second;
-        return;
-    }
+        return lookup->second;
 
     // If not, iterate until we find it (adding everything to the memoization)
     max_checked++;
@@ -187,8 +264,8 @@ void PrsonaClient::decrypt_score(const EGCiphertext& score)
     }
     decryption_memoizer[decryptionCandidate] = max_checked;
 
-    // Set the value we found
-    currentScore = max_checked;
+    // Return the value we found
+    return max_checked;
 }
 
 /*

+ 12 - 1
prsona/src/main.cpp

@@ -23,6 +23,17 @@ double mean(vector<double> xx)
     return accumulate(xx.begin(), xx.end(), 0.0) / xx.size(); 
 }
 
+void print_user_scores(const vector<PrsonaClient>& users)
+{
+    std::cout << "<";
+    for (size_t i = 0; i < users.size(); i++)
+    {
+            std::cout << users[i].get_score()
+                << (i == users.size() - 1 ? ">" : " ");
+    }
+    std::cout << std::endl;
+}
+
 // Time how long it takes to make a proof of valid votes
 vector<double> make_votes(
     default_random_engine& generator,
@@ -311,9 +322,9 @@ int main(int argc, char *argv[])
     for (size_t i = 0; i < numUsers; i++)
     {
         PrsonaClient currUser(
-            bgnPublicKey,
             elGamalBlindGeneratorProof,
             elGamalBlindGenerator,
+            bgnPublicKey,
             &servers);
         servers.add_new_client(currUser);
         users.push_back(currUser);

+ 2 - 2
prsona/src/proof.cpp

@@ -44,6 +44,6 @@ Scalar oracle(const std::string& input)
 Proof::Proof()
 { /* Do nothing */ }
 
-Proof::Proof(std::string basic)
-: basic(basic)
+Proof::Proof(std::string hbc)
+: hbc(hbc)
 { /* Do nothing */ }

+ 76 - 50
prsona/src/server.cpp

@@ -84,22 +84,40 @@ std::vector<CurveBipoint> PrsonaServer::get_current_votes_by(
     size_t voteSubmitter = binary_search(shortTermPublicKey);
     retval = voteMatrix[voteSubmitter];
 
-    pi = generate_votes_valid_proof();
+    pi = generate_valid_vote_row_proof();
     return retval;
 }
 
+std::vector<std::vector<CurveBipoint>> PrsonaServer::get_all_current_votes(
+    Proof& pi) const
+{
+    pi = generate_valid_vote_matrix_proof();
+    return voteMatrix;
+}
+
 /* Call this in order to get the current encrypted tally of a given user
  * (who is identified by their short term public key).
  * In practice, this is intended for clients, so that the servers vouch
  * for their ciphertexts being valid as part of their reputation proofs. */
-EGCiphertext PrsonaServer::get_current_tally(
+EGCiphertext PrsonaServer::get_current_user_encrypted_tally(
     Proof& pi, const Curvepoint& shortTermPublicKey) const
 {
     EGCiphertext retval;
     size_t tallyOwner = binary_search(shortTermPublicKey);
     retval = currentUserEncryptedTallies[tallyOwner];
     
-    pi = currentTallyProofs[tallyOwner];
+    pi = generate_valid_user_tally_proof();
+    return retval;
+}
+
+TwistBipoint PrsonaServer::get_current_server_encrypted_tally(
+    Proof& pi, const Curvepoint& shortTermPublicKey) const
+{
+    TwistBipoint retval;
+    size_t tallyOwner = binary_search(shortTermPublicKey);
+    retval = previousVoteTallies[tallyOwner];
+    
+    pi = generate_valid_server_tally_proof();
     return retval;
 }
 
@@ -117,8 +135,8 @@ std::vector<Curvepoint> PrsonaServer::get_current_pseudonyms(Proof& pi) const
  * One server will do this, then ask all other servers to import their
  * (proven) exported data. */
 void PrsonaServer::add_new_client(
+    std::vector<Proof>& proofOfValidAddition,
     const Proof& proofOfValidKey,
-    Proof& proofOfValidAddition,
     const Curvepoint& shortTermPublicKey)
 {
     if (!verify_ownership_proof(
@@ -132,41 +150,78 @@ void PrsonaServer::add_new_client(
 
     // The first epoch's score for a new user will be low,
     // but will typically converge on an average score quickly
-    TwistBipoint encryptedDefaultTally;
-    bgnSystem.encrypt(encryptedDefaultTally, DEFAULT_TALLY);
+    Scalar tallySeed;
+    TwistBipoint encryptedDefaultTally =
+        bgnSystem.get_public_key().twistEncrypt(tallySeed, DEFAULT_TALLY);
     previousVoteTallies.push_back(encryptedDefaultTally);
 
-    Scalar mask;
-    mask.set_random();
+    Scalar seedForUserTally;
+    seedForUserTally.set_random();
     EGCiphertext newUserEncryptedTally;
-    newUserEncryptedTally.mask = shortTermPublicKey * mask;
+    newUserEncryptedTally.mask = shortTermPublicKey * seedForUserTally;
     newUserEncryptedTally.encryptedMessage =
-        currentFreshGenerator * mask +
-        get_blinding_generator() * DEFAULT_TALLY;
+        currentFreshGenerator * seedForUserTally +
+        elGamalBlindGenerator * DEFAULT_TALLY;
     currentUserEncryptedTallies.push_back(newUserEncryptedTally);
-    currentTallyProofs.push_back(generate_valid_default_tally_proof());
 
     // Users are defaulted to casting a neutral vote for others.
     CurveBipoint encryptedDefaultVote, encryptedSelfVote;
-    bgnSystem.encrypt(encryptedDefaultVote, DEFAULT_VOTE);
-    bgnSystem.encrypt(encryptedSelfVote, Scalar(MAX_ALLOWED_VOTE));
+    Scalar currDefaultSeed, currSelfSeed;
+    encryptedDefaultVote = 
+        bgnSystem.get_public_key().curveEncrypt(currDefaultSeed, DEFAULT_VOTE);
+    encryptedSelfVote =
+        bgnSystem.get_public_key().curveEncrypt(currSelfSeed, Scalar(MAX_ALLOWED_VOTE));
+
     std::vector<CurveBipoint> newRow;
+    std::vector<Scalar> userVoteSeeds;
+    std::vector<Scalar> otherVoteSeeds;
     for (size_t i = 0; i < voteMatrix.size(); i++)
     {
-        encryptedDefaultVote = bgnSystem.rerandomize(encryptedDefaultVote);
+        Scalar addedSeed;
+
+        encryptedDefaultVote = bgnSystem.get_public_key().rerandomize(addedSeed, encryptedDefaultVote);
+        currDefaultSeed = currDefaultSeed.curveAdd(addedSeed);
+
+        otherVoteSeeds.push_back(Scalar());
+        otherVoteSeeds[i] = currDefaultSeed;
+        
         voteMatrix[i].push_back(encryptedDefaultVote);
 
-        encryptedDefaultVote = bgnSystem.rerandomize(encryptedDefaultVote);
+        encryptedDefaultVote = bgnSystem.get_public_key().rerandomize(addedSeed, encryptedDefaultVote);
+        currDefaultSeed = currDefaultSeed.curveAdd(addedSeed);
+
+        userVoteSeeds.push_back(Scalar());
+        userVoteSeeds[i] = currDefaultSeed;
+
         newRow.push_back(encryptedDefaultVote);
     }
+    
     // Because we are adding the new user to the end (and then sorting it),
     // this last element (bottom right corner) is always the self vote.
+    userVoteSeeds.push_back(Scalar());
+    userVoteSeeds[newRow.size()] = currSelfSeed;
+    
+    otherVoteSeeds.push_back(Scalar());
+    otherVoteSeeds[newRow.size()] = currSelfSeed;
+
     newRow.push_back(encryptedSelfVote);
     voteMatrix.push_back(newRow);
 
-    order_data(proofOfValidAddition);
+    Proof unused;
+    std::vector<size_t> sortOrder = order_data(unused);
+    std::vector<Scalar> newUserVoteSeeds;
+    std::vector<Scalar> newOtherVoteSeeds;
+    for (size_t i = 0; i < sortOrder.size(); i++)
+    {
+        newUserVoteSeeds.push_back(userVoteSeeds[sortOrder[i]]);
+        newOtherVoteSeeds.push_back(otherVoteSeeds[sortOrder[i]]);
+    }
 
-    proofOfValidAddition = generate_proof_of_added_user();
+    proofOfValidAddition = generate_proof_of_added_user(
+        tallySeed,
+        seedForUserTally,
+        newUserVoteSeeds,
+        newOtherVoteSeeds);
 }
 
 // Receive a new vote row from a user (identified by short term public key).
@@ -242,7 +297,7 @@ bool PrsonaServer::set_EG_blind_generator(
  *
  * Note that since these calculations are just for us, we don't need to do any
  * expensive rerandomizations of intermediate values. */
-std::vector<Scalar> PrsonaServer::tally_scores(std::vector<Proof>& tallyProofs)
+std::vector<Scalar> PrsonaServer::tally_scores()
 {
     std::vector<Quadripoint> BGNEncryptedTallies;
     std::vector<Scalar> decryptedTallies;
@@ -271,7 +326,6 @@ std::vector<Scalar> PrsonaServer::tally_scores(std::vector<Proof>& tallyProofs)
 
         // DECRYPT
         decryptedTallies.push_back(bgnSystem.decrypt(currEncryptedTally));
-        tallyProofs.push_back(generate_proof_of_correct_tally());
     }
 
     return decryptedTallies;
@@ -312,7 +366,6 @@ void PrsonaServer::build_up_midway_pseudonyms(
     nextGenerator = nextGenerator * nextSeed;
 
     currentUserEncryptedTallies.clear();
-    currentTallyProofs.clear();
 
     for (size_t i = 0; i < currentPseudonyms.size(); i++)
         currentPseudonyms[i] = currentPseudonyms[i] * nextSeed;
@@ -353,7 +406,6 @@ void PrsonaServer::import_updates(
     const std::vector<TwistBipoint>& otherPreviousVoteTallies,
     const std::vector<Curvepoint>& otherCurrentPseudonyms,
     const std::vector<EGCiphertext>& otherCurrentUserEncryptedTallies,
-    const std::vector<Proof>& otherCurrentTallyProofs,
     const std::vector<std::vector<CurveBipoint>>& otherVoteMatrix)
 {
     if (!verify_update_proof(pi))
@@ -365,7 +417,6 @@ void PrsonaServer::import_updates(
     previousVoteTallies = otherPreviousVoteTallies;
     currentPseudonyms = otherCurrentPseudonyms;
     currentUserEncryptedTallies = otherCurrentUserEncryptedTallies;
-    currentTallyProofs = otherCurrentTallyProofs;
     voteMatrix = otherVoteMatrix;
 }
 
@@ -373,13 +424,11 @@ void PrsonaServer::export_updates(
     std::vector<TwistBipoint>& otherPreviousVoteTallies,
     std::vector<Curvepoint>& otherCurrentPseudonyms,
     std::vector<EGCiphertext>& otherCurrentUserEncryptedTallies,
-    std::vector<Proof>& otherCurrentTallyProofs,
     std::vector<std::vector<CurveBipoint>>& otherVoteMatrix) const
 {
     otherPreviousVoteTallies = previousVoteTallies;
     otherCurrentPseudonyms = currentPseudonyms;
     otherCurrentUserEncryptedTallies = currentUserEncryptedTallies;
-    otherCurrentTallyProofs = currentTallyProofs;
     otherVoteMatrix = voteMatrix;
 }
 
@@ -437,7 +486,6 @@ std::vector<size_t> PrsonaServer::order_data(Proof& pi)
     std::vector<Curvepoint> newPseudonyms;
     std::vector<TwistBipoint> newVoteTallies;
     std::vector<EGCiphertext> newUserEncryptedTallies;
-    std::vector<Proof> newTallyProofs;
     std::vector<std::vector<CurveBipoint>> newVoteMatrix;
 
     for (size_t i = 0; i < sortTracker.size(); i++)
@@ -450,11 +498,6 @@ std::vector<size_t> PrsonaServer::order_data(Proof& pi)
             newUserEncryptedTallies.push_back(
                 currentUserEncryptedTallies[sortTracker[i].index]);
         }
-        if (!currentTallyProofs.empty())
-        {
-            newTallyProofs.push_back(
-                currentTallyProofs[sortTracker[i].index]);
-        }
 
         std::vector<CurveBipoint> currNewRow;
         for (size_t j = 0; j < currentPseudonyms.size(); j++)
@@ -470,7 +513,6 @@ std::vector<size_t> PrsonaServer::order_data(Proof& pi)
     previousVoteTallies = newVoteTallies;
     currentPseudonyms = newPseudonyms;
     currentUserEncryptedTallies = newUserEncryptedTallies;
-    currentTallyProofs = newTallyProofs;
     voteMatrix = newVoteMatrix;
 
     pi = generate_proof_of_shuffle();
@@ -481,26 +523,10 @@ std::vector<size_t> PrsonaServer::order_data(Proof& pi)
  * BINARY SEARCH
  */
 
-/* Completely normal binary search
- * There might be a standard function for this in <algorithms>?
- * But it returns an iterator, not a size_t, so less useful. */
+// Completely normal binary search
 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;
+    return PrsonaBase::binary_search(currentPseudonyms, index);
 }
 
 /*

+ 92 - 31
prsona/src/serverEntity.cpp

@@ -175,20 +175,54 @@ std::vector<CurveBipoint> PrsonaServerEntity::get_current_votes_by(
     return servers[which].get_current_votes_by(pi, shortTermPublicKey);
 }
 
-EGCiphertext PrsonaServerEntity::get_current_tally(
+std::vector<std::vector<CurveBipoint>> PrsonaServerEntity::get_all_current_votes(
+    Proof& pi) const
+{
+    return get_all_current_votes(pi, 0);
+}
+
+std::vector<std::vector<CurveBipoint>> PrsonaServerEntity::get_all_current_votes(
+    Proof& pi, size_t which) const
+{
+    return servers[which].get_all_current_votes(pi);
+}
+
+EGCiphertext PrsonaServerEntity::get_current_user_encrypted_tally(
     Proof& pi, const Curvepoint& shortTermPublicKey) const
 {
-    return get_current_tally(pi, shortTermPublicKey, 0);
+    return get_current_user_encrypted_tally(pi, shortTermPublicKey, 0);
 }
 
-/* Call this in order to get the current encrypted tally of a given user
- * (who is identified by their short term public key).
- * In practice, this is intended for clients, so that the servers vouch
- * for their ciphertexts being valid as part of their reputation proofs. */
-EGCiphertext PrsonaServerEntity::get_current_tally(
+EGCiphertext PrsonaServerEntity::get_current_user_encrypted_tally(
+    Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const
+{
+    return servers[which].get_current_user_encrypted_tally(
+        pi, shortTermPublicKey);
+}
+
+TwistBipoint PrsonaServerEntity::get_current_server_encrypted_tally(
+    Proof& pi, const Curvepoint& shortTermPublicKey) const
+{
+    return get_current_server_encrypted_tally(pi, shortTermPublicKey, 0);
+}
+
+TwistBipoint PrsonaServerEntity::get_current_server_encrypted_tally(
     Proof& pi, const Curvepoint& shortTermPublicKey, size_t which) const
 {
-    return servers[which].get_current_tally(pi, shortTermPublicKey);
+    return servers[which].get_current_server_encrypted_tally(
+        pi, shortTermPublicKey);
+}
+
+std::vector<Curvepoint> PrsonaServerEntity::get_current_pseudonyms(
+    Proof& pi) const
+{
+    return get_current_pseudonyms(pi, 0);
+}
+
+std::vector<Curvepoint> PrsonaServerEntity::get_current_pseudonyms(
+    Proof& pi, size_t which) const
+{
+    return servers[which].get_current_pseudonyms(pi);
 }
 
 /*
@@ -205,8 +239,8 @@ void PrsonaServerEntity::add_new_client(PrsonaClient& newUser)
  * exported data. */
 void PrsonaServerEntity::add_new_client(PrsonaClient& newUser, size_t which)
 {
-    Proof proofOfValidSTPK, proofOfCorrectAddition, proofOfValidVotes;
-    std::vector<Proof> proofOfValidGenerator;
+    Proof proofOfValidSTPK, proofOfValidVotes;
+    std::vector<Proof> proofOfValidGenerator, proofOfCorrectAddition;
     Curvepoint freshGenerator =
         get_fresh_generator(proofOfValidGenerator, which);
 
@@ -218,35 +252,36 @@ void PrsonaServerEntity::add_new_client(PrsonaClient& newUser, size_t which)
 
     // Do the actual work of adding the client to the first server
     servers[which].add_new_client(
-        proofOfValidSTPK, proofOfCorrectAddition, shortTermPublicKey);
+        proofOfCorrectAddition, proofOfValidSTPK, shortTermPublicKey);
 
     // Then, export the data to the rest of the servers
     std::vector<TwistBipoint> previousVoteTally;
     std::vector<Curvepoint> currentPseudonyms;
     std::vector<EGCiphertext> currentUserEncryptedTallies;
-    std::vector<Proof> currentTallyProofs;
     std::vector<std::vector<CurveBipoint>> voteMatrix;
     servers[which].export_updates(
         previousVoteTally,
         currentPseudonyms,
         currentUserEncryptedTallies,
-        currentTallyProofs,
         voteMatrix);
+    
+    // FIX ME!!!!!!!
+    Proof unused("PROOF");
+
     for (size_t j = 1; j < servers[which].get_num_servers(); j++)
     {
         size_t index = (which + j) % servers[which].get_num_servers();
         servers[index].import_updates(
-            proofOfCorrectAddition,
+            unused,
             previousVoteTally,
             currentPseudonyms,
             currentUserEncryptedTallies,
-            currentTallyProofs,
             voteMatrix);
     }
 
     // Finally, give the user the information it needs
     // about its current tally and votes
-    transmit_updates(newUser, which);
+    transmit_new_user_data(proofOfCorrectAddition, newUser);
 }
 
 // Receive a new vote row from a user (identified by short term public key).
@@ -277,6 +312,12 @@ bool PrsonaServerEntity::receive_vote(
     return retval;
 }
 
+void PrsonaServerEntity::transmit_new_user_data(
+    const std::vector<Proof>& pi, PrsonaClient& newUser) const
+{
+    newUser.receive_new_user_data(pi);
+}
+
 void PrsonaServerEntity::transmit_updates(PrsonaClient& currUser) const
 {
     transmit_updates(currUser, 0);
@@ -295,12 +336,8 @@ void PrsonaServerEntity::transmit_updates(
     // Get users the next fresh generator so they can correctly
     // ask for their new scores and vote row
     currUser.receive_fresh_generator(proofOfValidGenerator, freshGenerator);
-    Curvepoint shortTermPublicKey =
-        currUser.get_short_term_public_key(proofOfValidSTPK);
 
-    EGCiphertext score =
-        get_current_tally(proofOfScore, shortTermPublicKey, which);
-    currUser.receive_vote_tally(proofOfScore, score);
+    currUser.receive_vote_tally();
 }
 
 /*
@@ -334,14 +371,12 @@ void PrsonaServerEntity::epoch(Proof& pi, size_t which)
             previousVoteTally,
             currentPseudonyms,
             currentUserEncryptedTallies,
-            currentTallyProofs,
             voteMatrix);
         servers[nextIndex].import_updates(
             pi,
             previousVoteTally,
             currentPseudonyms,
             currentUserEncryptedTallies,
-            currentTallyProofs,
             voteMatrix);
     }
 
@@ -350,7 +385,7 @@ void PrsonaServerEntity::epoch(Proof& pi, size_t which)
      * knows. Everyone else then adds a mask and proves they added a secret mask
      * to the committed values. */
     currentUserEncryptedTallies =
-        tally_scores(currentTallyProofs, nextGenerator, which);
+        tally_scores(nextGenerator, which);
     
     // go from A_0.5 to A_1
     for (size_t i = 0; i < servers[which].get_num_servers(); i++)
@@ -363,14 +398,12 @@ void PrsonaServerEntity::epoch(Proof& pi, size_t which)
             previousVoteTally,
             currentPseudonyms,
             currentUserEncryptedTallies,
-            currentTallyProofs,
             voteMatrix);
         servers[nextIndex].import_updates(
             pi,
             previousVoteTally,
             currentPseudonyms,
             currentUserEncryptedTallies,
-            currentTallyProofs,
             voteMatrix);
     }
 
@@ -384,11 +417,42 @@ void PrsonaServerEntity::epoch(Proof& pi, size_t which)
             previousVoteTally,
             currentPseudonyms,
             currentUserEncryptedTallies,
-            currentTallyProofs,
             voteMatrix);
     }
 }
 
+void PrsonaServerEntity::print_scores() const
+{
+    BGN bgnSystem = servers[0].bgnSystem;
+    std::vector<TwistBipoint> scores = servers[0].previousVoteTallies;
+
+    std::cout << "[";
+    for (size_t i = 0; i < scores.size(); i++)
+    {
+            std::cout << bgnSystem.decrypt(scores[i])
+                << (i == scores.size() - 1 ? "]" : " ");
+    }
+    std::cout << std::endl;
+}
+
+void PrsonaServerEntity::print_votes() const
+{
+    BGN bgnSystem = servers[0].bgnSystem;
+    std::vector<std::vector<CurveBipoint>> voteMatrix = servers[0].voteMatrix;
+
+    for (size_t i = 0; i < voteMatrix.size(); i++)
+    {
+        std::cout << (i == 0 ? "[[" : " [");
+        for (size_t j = 0; j < voteMatrix[i].size(); j++)
+        {
+
+            std::cout << bgnSystem.decrypt(voteMatrix[i][j])
+                << (j == voteMatrix[i].size() - 1 ? "]" : " ");
+        }
+        std::cout << (i == voteMatrix.size() - 1 ? "]" : " ") << std::endl;
+    }
+}
+
 /*********************
  * PRIVATE FUNCTIONS *
  *********************/
@@ -403,14 +467,12 @@ void PrsonaServerEntity::epoch(Proof& pi, size_t which)
  * We're treating it as if we are one server, so that server gets the updated
  * weights to be sent to all other servers for the next epoch. */
 std::vector<EGCiphertext> PrsonaServerEntity::tally_scores(
-    std::vector<Proof>& tallyProofs,
     const Curvepoint& nextGenerator,
     size_t which)
 {
     std::vector<EGCiphertext> retval;
     Proof maxScoreProof;
-    std::vector<Scalar> decryptedTalliedScores = servers[which].tally_scores(
-                                                    tallyProofs);
+    std::vector<Scalar> decryptedTalliedScores = servers[which].tally_scores();
     mpz_class maxScorePossibleThisRound =
         servers[which].get_max_possible_score(maxScoreProof).toInt() *
         PrsonaBase::get_max_allowed_vote();
@@ -442,7 +504,6 @@ std::vector<EGCiphertext> PrsonaServerEntity::tally_scores(
     }
 
     servers[which].currentUserEncryptedTallies = retval;
-    servers[which].currentTallyProofs = tallyProofs;
     return retval;
 }