Browse Source

I don't know what it is, but approximately 3% of the time, there is a bug that causes proofs to fail. Otherwise, I'm adding networking code now

tristangurtler 3 years ago
parent
commit
373a1adbae

+ 23 - 41
prsona/inc/client.hpp

@@ -12,10 +12,6 @@
 #include "EGCiphertext.hpp"
 #include "proof.hpp"
 
-// Forward declaration to be able to make a pointer to the servers,
-// which is needed in some proofs
-class PrsonaServerEntity;
-
 class PrsonaClient : public PrsonaBase {
     public:
         // CONSTRUCTORS
@@ -23,7 +19,7 @@ class PrsonaClient : public PrsonaBase {
             const std::vector<Proof>& generatorProof,
             const Curvepoint& elGamalBlindGenerator,
             const BGNPublicKey& serverPublicKey,
-            const PrsonaServerEntity* servers);
+            size_t numServers);
 
         // BASIC PUBLIC SYSTEM INFO GETTERS
         Curvepoint get_short_term_public_key() const;
@@ -32,37 +28,48 @@ class PrsonaClient : public PrsonaBase {
         // SERVER INTERACTIONS
         std::vector<CurveBipoint> make_votes(
             std::vector<Proof>& validVoteProof,
-            const Proof& serverProof,
+            const std::vector<Proof>& serverProof,
             const std::vector<CurveBipoint>& oldEncryptedVotes,
             const std::vector<Scalar>& votes,
             const std::vector<bool>& replaces
         ) const;
         bool receive_fresh_generator(
-            const std::vector<Proof>& pi, const Curvepoint& freshGenerator);
-        bool receive_vote_tally();
-        bool receive_new_user_data(const std::vector<Proof>& pi);
+            const std::vector<Proof>& pi,
+            const Curvepoint& freshGenerator);
+        bool receive_vote_tally(
+            const std::vector<Proof>& pi,
+            const EGCiphertext& score);
+        bool receive_new_user_data(
+            const std::vector<Proof>& mainProof,
+            const std::vector<Proof>& serverEncryptedScoreProof,
+            const TwistBipoint& serverEncryptedScore,
+            const std::vector<Proof>& userEncryptedScoreProof,
+            const EGCiphertext& userEncryptedScore,
+            const std::vector<Proof>& voteMatrixProof,
+            const std::vector<std::vector<CurveBipoint>>& encryptedVoteMatrix,
+            const std::vector<Proof>& pseudonymsProof,
+            const std::vector<Curvepoint>& currentPseudonyms);
 
         // REPUTATION PROOFS
         std::vector<Proof> generate_reputation_proof(
-            const Scalar& threshold
+            const Scalar& threshold,
+            size_t numClients
         ) const;
         bool verify_reputation_proof(
             const std::vector<Proof>& pi,
             const Curvepoint& shortTermPublicKey,
-            const Scalar& threshold
+            const Scalar& threshold,
+            const std::vector<Proof>& encryptedScoreProof,
+            const EGCiphertext& encryptedScore
         ) const;
 
         // NEEDED FOR TESTING PROOFS
         Scalar get_score() const;
 
     private:
-        // Constants for clients
-        static bool SERVER_IS_MALICIOUS;
-        static bool CLIENT_IS_MALICIOUS;
-        
         // Things bound to the servers permanently
         const BGNPublicKey serverPublicKey;
-        const PrsonaServerEntity *servers;
+        const size_t numServers;
 
         // Things bound to the servers (but change regularly)
         Curvepoint currentFreshGenerator;
@@ -93,31 +100,6 @@ class PrsonaClient : public PrsonaBase {
             const std::vector<CurveBipoint>& newEncryptedVotes,
             const std::vector<Scalar>& seeds,
             const std::vector<Scalar>& votes
-        ) const;     
-
-        // SERVER AGREEMENT PROOFS
-        bool verify_valid_vote_row_proof(
-            const Proof& pi,
-            const Curvepoint& shortTermPublicKey,
-            const std::vector<CurveBipoint>& commitment
-        ) const;
-        bool verify_valid_vote_matrix_proof(
-            const Proof& pi,
-            const std::vector<std::vector<CurveBipoint>>& commitment
-        ) const;
-        bool verify_valid_user_tally_proof(
-            const Proof& pi,
-            const Curvepoint& shortTermPublicKey,
-            const EGCiphertext& commitment
-        ) const;
-        bool verify_valid_server_tally_proof(
-            const Proof& pi,
-            const Curvepoint& shortTermPublicKey,
-            const TwistBipoint& commitment
-        ) const;
-        bool verify_valid_pseudonyms_proof(
-            const Proof& pi,
-            const std::vector<Curvepoint>& commitment
         ) const;
 }; 
 

+ 16 - 0
prsona/inc/networkClient.hpp

@@ -0,0 +1,16 @@
+#ifndef __PRSONA_NETWORK_CLIENT_HPP
+#define __PRSONA_NETWORK_CLIENT_HPP
+
+#include "client.hpp"
+
+class PrsonaNetworkClient : public PrsonaClient {
+    public:
+        // CONSTRUCTORS
+        PrsonaNetworkClient(
+            const std::vector<Proof>& generatorProof,
+            const Curvepoint& elGamalBlindGenerator,
+            const BGNPublicKey& serverPublicKey,
+            const size_t numServers);
+}; 
+
+#endif

+ 13 - 0
prsona/inc/networkServer.hpp

@@ -0,0 +1,13 @@
+#ifndef __PRSONA_NETWORK_SERVER_HPP
+#define __PRSONA_NETWORK_SERVER_HPP
+
+#include "server.hpp"
+
+class PrsonaNetworkServer : public PrsonaServer {
+    public:
+        // CONSTRUCTORS
+        PrsonaNetworkServer(size_t numServers);
+        PrsonaNetworkServer(size_t numServers, const BGN& other_bgn);
+}; 
+
+#endif

+ 5 - 2
prsona/inc/proof.hpp

@@ -16,6 +16,8 @@ class Proof {
     public:
         Proof();
         Proof(std::string hbc);
+
+        void clear();
     
         // HBC security
         std::string hbc;
@@ -23,10 +25,11 @@ class Proof {
         // Malicious security
         std::vector<Curvepoint> curvepointUniversals;
         std::vector<CurveBipoint> curveBipointUniversals;
-        std::vector<TwistBipoint> twistBipointUniversals;
-
         std::vector<Scalar> challengeParts;
         std::vector<Scalar> responseParts;
+
+        friend std::ostream& operator<<(std::ostream& os, const Proof& output);
+        friend std::istream& operator>>(std::istream& is, Proof& input);
 };
 
 Scalar oracle(const std::string& input);

+ 2 - 0
prsona/inc/serverEntity.hpp

@@ -97,6 +97,8 @@ class PrsonaServerEntity {
             size_t which);
         void transmit_new_user_data(
             const std::vector<Proof>& pi, PrsonaClient& newUser) const;
+        void transmit_new_user_data(
+            const std::vector<Proof>& pi, PrsonaClient& newUser, size_t which) const;
         void transmit_updates(PrsonaClient& currUser) const;
         void transmit_updates(PrsonaClient& currUser, size_t which) const;
 

+ 33 - 107
prsona/src/client.cpp

@@ -1,7 +1,6 @@
 #include <iostream>
 
 #include "client.hpp"
-#include "serverEntity.hpp"
 
 /********************
  * PUBLIC FUNCTIONS *
@@ -15,13 +14,13 @@ PrsonaClient::PrsonaClient(
     const std::vector<Proof>& generatorProof,
     const Curvepoint& elGamalBlindGenerator,
     const BGNPublicKey& serverPublicKey,
-    const PrsonaServerEntity* servers)
+    size_t numServers)
     : serverPublicKey(serverPublicKey),
-        servers(servers),
+        numServers(numServers),
         max_checked(0)
 {
     set_EG_blind_generator(
-        generatorProof, elGamalBlindGenerator, servers->get_num_servers());
+        generatorProof, elGamalBlindGenerator, numServers);
 
     longTermPrivateKey.set_random();
     inversePrivateKey = longTermPrivateKey.curveMultInverse();
@@ -55,14 +54,12 @@ Curvepoint PrsonaClient::get_short_term_public_key(Proof &pi) const
  * but it doesn't behave correctly when adding new clients after this one. */
 std::vector<CurveBipoint> PrsonaClient::make_votes(
     std::vector<Proof>& validVoteProof,
-    const Proof& serverProof,
+    const std::vector<Proof>& serverProof,
     const std::vector<CurveBipoint>& oldEncryptedVotes,
     const std::vector<Scalar>& votes,
     const std::vector<bool>& replaces) const
 {
-    Curvepoint shortTermPublicKey = get_short_term_public_key();
-
-    if (!verify_valid_vote_row_proof(serverProof, shortTermPublicKey, oldEncryptedVotes))
+    if (!verify_valid_vote_row_proof(serverProof, oldEncryptedVotes))
     {
         std::cerr << "Could not verify proof of valid votes." << std::endl;
         return oldEncryptedVotes;
@@ -92,9 +89,10 @@ std::vector<CurveBipoint> PrsonaClient::make_votes(
 
 // Get a new fresh generator (happens at initialization and during each epoch)
 bool PrsonaClient::receive_fresh_generator(
-    const std::vector<Proof>& pi, const Curvepoint& freshGenerator)
+    const std::vector<Proof>& pi,
+    const Curvepoint& freshGenerator)
 {
-    if (!verify_generator_proof(pi, freshGenerator, servers->get_num_servers()))
+    if (!verify_generator_proof(pi, freshGenerator, numServers))
     {
         std::cerr << "Issue verifying fresh generator proof." << std::endl;
         return false;
@@ -105,15 +103,11 @@ bool PrsonaClient::receive_fresh_generator(
 }
 
 // Receive a new encrypted score from the servers (each epoch)
-bool PrsonaClient::receive_vote_tally()
+bool PrsonaClient::receive_vote_tally(
+    const std::vector<Proof>& pi,
+    const EGCiphertext& score)
 {
-    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, shortTermPublicKey, score))
+    if (!verify_valid_user_tally_proof(pi, score))
     {
         std::cerr << "Could not verify proof of valid tally." << std::endl;
         return false;
@@ -124,38 +118,38 @@ bool PrsonaClient::receive_vote_tally()
     return true;
 }
 
-bool PrsonaClient::receive_new_user_data(const std::vector<Proof>& mainProof)
+bool PrsonaClient::receive_new_user_data(
+    const std::vector<Proof>& mainProof,
+    const std::vector<Proof>& serverEncryptedScoreProof,
+    const TwistBipoint& serverEncryptedScore,
+    const std::vector<Proof>& userEncryptedScoreProof,
+    const EGCiphertext& userEncryptedScore,
+    const std::vector<Proof>& voteMatrixProof,
+    const std::vector<std::vector<CurveBipoint>>& encryptedVoteMatrix,
+    const std::vector<Proof>& pseudonymsProof,
+    const std::vector<Curvepoint>& currentPseudonyms)
 {
-    Proof currProof;
     Curvepoint shortTermPublicKey = get_short_term_public_key();
 
-    TwistBipoint serverEncryptedScore =
-        servers->get_current_server_encrypted_tally(currProof, shortTermPublicKey);
-    if (!verify_valid_server_tally_proof(currProof, shortTermPublicKey, serverEncryptedScore))
+    if (!verify_valid_server_tally_proof(serverEncryptedScoreProof, serverEncryptedScore))
     {
         std::cerr << "Could not verify preliminary proof of server encrypted tally." << std::endl;
         return false;
     }
 
-    EGCiphertext userEncryptedScore =
-        servers->get_current_user_encrypted_tally(currProof, shortTermPublicKey);
-    if (!verify_valid_user_tally_proof(currProof, shortTermPublicKey, userEncryptedScore))
+    if (!verify_valid_user_tally_proof(userEncryptedScoreProof, userEncryptedScore))
     {
         std::cerr << "Could not verify preliminary proof of user 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, encryptedVoteMatrix))
+    if (!verify_valid_vote_matrix_proof(voteMatrixProof, encryptedVoteMatrix))
     {
         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, currentPseudonyms))
+    if (!verify_valid_pseudonyms_proof(pseudonymsProof, currentPseudonyms))
     {
         std::cerr << "Could not verify preliminary proof of pseudonyms." << std::endl;
         return false;
@@ -199,7 +193,8 @@ bool PrsonaClient::receive_new_user_data(const std::vector<Proof>& mainProof)
 
 // A pretty straightforward range proof (generation)
 std::vector<Proof> PrsonaClient::generate_reputation_proof(
-    const Scalar& threshold) const
+    const Scalar& threshold,
+    size_t numClients) const
 {
     Proof ownershipProof = generate_ownership_proof();
     
@@ -209,19 +204,17 @@ std::vector<Proof> PrsonaClient::generate_reputation_proof(
         currentScore,
         threshold,
         inversePrivateKey,
-        servers->get_num_clients());
+        numClients);
 }
 
 bool PrsonaClient::verify_reputation_proof(
     const std::vector<Proof>& pi,
     const Curvepoint& shortTermPublicKey,
-    const Scalar& threshold) const
+    const Scalar& threshold,
+    const std::vector<Proof>& encryptedScoreProof,
+    const EGCiphertext& encryptedScore) const
 {
-    Proof serverProof;
-    EGCiphertext encryptedScore =
-        servers->get_current_user_encrypted_tally(serverProof, shortTermPublicKey);
-
-    if (!verify_valid_user_tally_proof(serverProof, shortTermPublicKey, encryptedScore))
+    if (!verify_valid_user_tally_proof(encryptedScoreProof, encryptedScore))
     {
         std::cerr << "Error getting score from server, aborting." << std::endl;
         return false;
@@ -310,70 +303,3 @@ std::vector<Proof> PrsonaClient::generate_vote_proof(
         seeds,
         votes);
 }
-
-/*
- * SERVER AGREEMENT PROOFS
- */
-
-bool PrsonaClient::verify_valid_vote_row_proof(
-    const Proof& pi,
-    const Curvepoint& shortTermPublicKey,
-    const std::vector<CurveBipoint>& commitment) const
-{
-    std::vector<Proof> fullProof;
-    fullProof.push_back(pi);
-
-    servers->get_other_vote_row_commitments(fullProof, shortTermPublicKey);
-
-    return PrsonaBase::verify_valid_vote_row_proof(fullProof, commitment);
-}
-
-bool PrsonaClient::verify_valid_vote_matrix_proof(
-    const Proof& pi,
-    const std::vector<std::vector<CurveBipoint>>& commitment) const
-{
-    std::vector<Proof> fullProof;
-    fullProof.push_back(pi);
-
-    servers->get_other_vote_matrix_commitments(fullProof);
-
-    return PrsonaBase::verify_valid_vote_matrix_proof(fullProof, commitment);
-}
-
-bool PrsonaClient::verify_valid_user_tally_proof(
-    const Proof& pi,
-    const Curvepoint& shortTermPublicKey,
-    const EGCiphertext& commitment) const
-{
-    std::vector<Proof> fullProof;
-    fullProof.push_back(pi);
-
-    servers->get_other_user_tally_commitments(fullProof, shortTermPublicKey);
-
-    return PrsonaBase::verify_valid_user_tally_proof(fullProof, commitment);
-}
-
-bool PrsonaClient::verify_valid_server_tally_proof(
-    const Proof& pi,
-    const Curvepoint& shortTermPublicKey,
-    const TwistBipoint& commitment) const
-{
-    std::vector<Proof> fullProof;
-    fullProof.push_back(pi);
-
-    servers->get_other_server_tally_commitments(fullProof, shortTermPublicKey);
-
-    return PrsonaBase::verify_valid_server_tally_proof(fullProof, commitment);
-}
-
-bool PrsonaClient::verify_valid_pseudonyms_proof(
-    const Proof& pi,
-    const std::vector<Curvepoint>& commitment) const
-{
-    std::vector<Proof> fullProof;
-    fullProof.push_back(pi);
-
-    servers->get_other_pseudonyms_commitments(fullProof);
-
-    return PrsonaBase::verify_valid_pseudonyms_proof(fullProof, commitment);
-}

+ 104 - 39
prsona/src/main.cpp

@@ -62,18 +62,21 @@ vector<double> make_votes(
         shuffle(replaces.begin(), replaces.end(), generator);
 
         
-        Proof ownerProof;
+        Proof baseProof;
+        vector<Proof> fullProof;
         Curvepoint shortTermPublicKey =
-            users[i].get_short_term_public_key(ownerProof);
+            users[i].get_short_term_public_key();
         vector<CurveBipoint> currEncryptedVotes =
-            servers.get_current_votes_by(ownerProof, shortTermPublicKey);
-        vector<Proof> currVoteProof;
+            servers.get_current_votes_by(baseProof, shortTermPublicKey);
+        fullProof.push_back(baseProof);
+        servers.get_other_vote_row_commitments(fullProof, shortTermPublicKey);
         
+        vector<Proof> currVoteProof;
         chrono::high_resolution_clock::time_point t0 =
             chrono::high_resolution_clock::now();
         currEncryptedVotes = users[i].make_votes(
                                 currVoteProof,
-                                ownerProof,
+                                fullProof,
                                 currEncryptedVotes,
                                 votes,
                                 replaces);
@@ -172,6 +175,7 @@ vector<double> transmit_epoch_updates(
 // Test if the proof of reputation level is working as expected
 void test_reputation_proof(
     default_random_engine& generator,
+    const PrsonaServerEntity& servers,
     const PrsonaClient& a,
     const PrsonaClient& b)
 {
@@ -185,18 +189,43 @@ void test_reputation_proof(
     Scalar goodThreshold(thresholdDistribution(generator));
     Scalar badThreshold(aScore + 1);
 
-    Proof pi;
-    Curvepoint shortTermPublicKey = a.get_short_term_public_key(pi);
-    vector<Proof> goodRepProof = a.generate_reputation_proof(goodThreshold);
+    Curvepoint shortTermPublicKey = a.get_short_term_public_key();
+    vector<Proof> goodRepProof =
+        a.generate_reputation_proof(goodThreshold, servers.get_num_clients());
+
+    Proof baseProof;
+    vector<Proof> fullProof;
+    EGCiphertext currEncryptedScore =
+        servers.get_current_user_encrypted_tally(baseProof, shortTermPublicKey);
+    fullProof.push_back(baseProof);
+    servers.get_other_user_tally_commitments(fullProof, shortTermPublicKey);
+
     flag = b.verify_reputation_proof(
-                goodRepProof, shortTermPublicKey, goodThreshold);
+                goodRepProof,
+                shortTermPublicKey,
+                goodThreshold,
+                fullProof,
+                currEncryptedScore);
     cout << "TEST VALID REPUTATION PROOF:     "
         << (flag ? "PASSED (Proof verified)" : "FAILED (Proof not verified)" )
         << endl;
     
-    vector<Proof> badRepProof = a.generate_reputation_proof(badThreshold);
+    vector<Proof> badRepProof =
+        a.generate_reputation_proof(badThreshold, servers.get_num_clients());
+
+    baseProof.clear();
+    fullProof.clear();
+    currEncryptedScore =
+        servers.get_current_user_encrypted_tally(baseProof, shortTermPublicKey);
+    fullProof.push_back(baseProof);
+    servers.get_other_user_tally_commitments(fullProof, shortTermPublicKey);
+
     flag = b.verify_reputation_proof(
-                badRepProof, shortTermPublicKey, badThreshold);
+                badRepProof,
+                shortTermPublicKey,
+                goodThreshold,
+                fullProof,
+                currEncryptedScore);
     cout << "TEST INVALID REPUTATION PROOF:   "
         << (flag ? "FAILED (Proof verified)" : "PASSED (Proof not verified)" )
         << endl << endl;
@@ -220,14 +249,22 @@ void test_vote_proof(
     }
 
     vector<Proof> validVoteProof;
-    Proof ownerProof;
+
+    Proof baseProof;
+    vector<Proof> fullProof;
     Curvepoint shortTermPublicKey =
-        user.get_short_term_public_key(ownerProof);
+        user.get_short_term_public_key();
     vector<CurveBipoint> encryptedVotes =
-        servers.get_current_votes_by(ownerProof, shortTermPublicKey);
-    encryptedVotes =
-        user.make_votes(
-            validVoteProof, ownerProof, encryptedVotes, votes, replaces);
+        servers.get_current_votes_by(baseProof, shortTermPublicKey);
+    fullProof.push_back(baseProof);
+    servers.get_other_vote_row_commitments(fullProof, shortTermPublicKey);
+
+    encryptedVotes = user.make_votes(
+        validVoteProof,
+        fullProof,
+        encryptedVotes,
+        votes,
+        replaces);
 
     flag = servers.receive_vote(
                 validVoteProof, encryptedVotes, shortTermPublicKey);
@@ -236,16 +273,20 @@ void test_vote_proof(
         << endl;
 
     for (size_t i = 0; i < numUsers; i++)
-    {
         replaces[i] = false;
-    }
 
-    shortTermPublicKey = user.get_short_term_public_key(ownerProof);
-    encryptedVotes = 
-        servers.get_current_votes_by(ownerProof, shortTermPublicKey);
+    baseProof.clear();
+    fullProof.clear();
     encryptedVotes =
-        user.make_votes(
-            validVoteProof, ownerProof, encryptedVotes, votes, replaces);
+        servers.get_current_votes_by(baseProof, shortTermPublicKey);
+    fullProof.push_back(baseProof);
+    servers.get_other_vote_row_commitments(fullProof, shortTermPublicKey);
+    encryptedVotes = user.make_votes(
+        validVoteProof,
+        fullProof,
+        encryptedVotes,
+        votes,
+        replaces);
 
     flag = servers.receive_vote(
                 validVoteProof, encryptedVotes, shortTermPublicKey);
@@ -259,12 +300,18 @@ void test_vote_proof(
         replaces[i] = true;
     }
 
-    shortTermPublicKey = user.get_short_term_public_key(ownerProof);
-    encryptedVotes = 
-        servers.get_current_votes_by(ownerProof, shortTermPublicKey);
+    baseProof.clear();
+    fullProof.clear();
     encryptedVotes =
-        user.make_votes(
-            validVoteProof, ownerProof, encryptedVotes, votes, replaces);
+        servers.get_current_votes_by(baseProof, shortTermPublicKey);
+    fullProof.push_back(baseProof);
+    servers.get_other_vote_row_commitments(fullProof, shortTermPublicKey);
+    encryptedVotes = user.make_votes(
+        validVoteProof,
+        fullProof,
+        encryptedVotes,
+        votes,
+        replaces);
 
     flag = servers.receive_vote(
                 validVoteProof, encryptedVotes, shortTermPublicKey);
@@ -296,7 +343,7 @@ void check_vote_matrix_updates()
             elGamalBlindGeneratorProof,
             elGamalBlindGenerator,
             bgnPublicKey,
-            &servers);
+            numServers);
         users.push_back(currUser);
         servers.add_new_client(users[i]);
     }
@@ -309,9 +356,8 @@ void check_vote_matrix_updates()
 
     for (size_t i = 0; i < numUsers; i++)
     {   
-        Proof ownerProof;
         Curvepoint shortTermPublicKey =
-            users[i].get_short_term_public_key(ownerProof);
+            users[i].get_short_term_public_key();
 
         size_t myIndex =
             users[i].binary_search(currentPseudonyms, shortTermPublicKey);
@@ -331,13 +377,17 @@ void check_vote_matrix_updates()
             replaces.push_back(true);
         }
 
+        Proof baseProof;
+        vector<Proof> fullProof;
         vector<CurveBipoint> currEncryptedVotes =
-            servers.get_current_votes_by(ownerProof, shortTermPublicKey);
+            servers.get_current_votes_by(baseProof, shortTermPublicKey);
+        fullProof.push_back(baseProof);
+        servers.get_other_vote_row_commitments(fullProof, shortTermPublicKey);
+
         vector<Proof> currVoteProof;
-    
         currEncryptedVotes = users[i].make_votes(
                                 currVoteProof,
-                                ownerProof,
+                                fullProof,
                                 currEncryptedVotes,
                                 votes,
                                 replaces);
@@ -395,13 +445,28 @@ int main(int argc, char *argv[])
         numRounds = atoi(argv[3]);
     if (argc > 4)
         numVotesPerRound = atoi(argv[4]);
+    if (argc > 5)
+    {
+        bool setting = argv[5][0] == 't' || argv[5][0] == 'T';
+        maliciousServers = setting;
+    }
+    if (argc > 6)
+    {
+        bool setting = argv[6][0] == 't' || argv[6][0] == 'T';
+        maliciousClients = setting;
+    }
+    if (argc > 7)
+        seedStr = argv[7];
 
     cout << "Running the protocol with the following parameters: " << endl;
     cout << numServers << " PRSONA servers" << endl;
     cout << numUsers << " participants (voters/votees)" << endl;
     cout << numRounds << " epochs" << endl;
-    cout << numVotesPerRound << " new (random) votes by each user per epoch"
-        << endl << endl;
+    cout << numVotesPerRound << " new (random) votes by each user per epoch" << endl;
+    cout << "Servers are set to " << (maliciousServers ? "MALICIOUS" : "HBC") << " security" << endl;
+    cout << "Clients are set to " << (maliciousClients ? "MALICIOUS" : "HBC") << " security" << endl;
+    cout << "Current randomness seed: \"" << seedStr << "\"" << endl;
+    cout << endl;
 
     // Set malicious flags where necessary
     if (maliciousServers)
@@ -424,7 +489,7 @@ int main(int argc, char *argv[])
             elGamalBlindGeneratorProof,
             elGamalBlindGenerator,
             bgnPublicKey,
-            &servers);
+            numServers);
         users.push_back(currUser);
         servers.add_new_client(users[i]);
     }
@@ -479,7 +544,7 @@ int main(int argc, char *argv[])
     while (user_b == user_a)
         user_b = userDistribution(generator);
 
-    test_reputation_proof(generator, users[user_a], users[user_b]);
+    test_reputation_proof(generator, servers, users[user_a], users[user_b]);
     test_vote_proof(generator, users[user_a], servers);
 
     return 0;

+ 9 - 0
prsona/src/networkClient.cpp

@@ -0,0 +1,9 @@
+#include "networkClient.hpp"
+
+PrsonaNetworkClient::PrsonaNetworkClient(
+    const std::vector<Proof>& generatorProof,
+    const Curvepoint& elGamalBlindGenerator,
+    const BGNPublicKey& serverPublicKey,
+    size_t numServers)
+: PrsonaClient(generatorProof, elGamalBlindGenerator, serverPublicKey, numServers)
+{ /* */ }

+ 15 - 0
prsona/src/networkServer.cpp

@@ -0,0 +1,15 @@
+#include "networkServer.hpp"
+
+/*
+ * CONSTRUCTORS
+ */
+
+// Used to generate the first server; instantiates BGN for the first time
+PrsonaNetworkServer::PrsonaNetworkServer(size_t numServers)
+: PrsonaServer(numServers)
+{ /* Do nothing */ }
+
+// Used for all other servers, so they have the same BGN parameters
+PrsonaNetworkServer::PrsonaNetworkServer(size_t numServers, const BGN& otherBgn)
+: PrsonaServer(numServers, otherBgn)
+{ /* Do nothing */ }

+ 93 - 0
prsona/src/proof.cpp

@@ -47,3 +47,96 @@ Proof::Proof()
 Proof::Proof(std::string hbc)
 : hbc(hbc)
 { /* Do nothing */ }
+
+void Proof::clear()
+{
+    hbc.clear();
+    curvepointUniversals.clear();
+    curveBipointUniversals.clear();
+    challengeParts.clear();
+    responseParts.clear();
+}
+
+std::ostream& operator<<(std::ostream& os, const Proof& output)
+{
+    if (!output.hbc.empty())
+    {
+        os << true;
+        os << output.hbc.size();
+        os << output.hbc;
+        return os;
+    }
+
+    os << false;
+
+    os << output.curvepointUniversals.size();
+    for (size_t i = 0; i < output.curvepointUniversals.size(); i++)
+        os << output.curvepointUniversals[i];
+
+    os << output.curveBipointUniversals.size();
+    for (size_t i = 0; i < output.curveBipointUniversals.size(); i++)
+        os << output.curveBipointUniversals[i];
+
+    os << output.challengeParts.size();
+    for (size_t i = 0; i < output.challengeParts.size(); i++)
+        os << output.challengeParts[i];
+
+    os << output.responseParts.size();
+    for (size_t i = 0; i < output.responseParts.size(); i++)
+        os << output.responseParts[i];
+
+    return os;
+}
+
+std::istream& operator>>(std::istream& is, Proof& input)
+{
+    bool hbc;
+    is >> hbc;
+    if (hbc)
+    {
+        size_t numBytes;
+        is >> numBytes;
+        
+        char* buffer = new char[numBytes + 1];
+        is.read(buffer, numBytes);
+        input.hbc = buffer;
+        delete buffer;
+
+        return is;
+    }
+
+    size_t numElements;
+    is >> numElements;
+    for (size_t i = 0; i < numElements; i++)
+    {
+        Curvepoint x;
+        is >> x;
+        input.curvepointUniversals.push_back(x);
+    }
+
+    is >> numElements;
+    for (size_t i = 0; i < numElements; i++)
+    {
+        CurveBipoint x;
+        is >> x;
+        input.curveBipointUniversals.push_back(x);
+    }
+
+    is >> numElements;
+    for (size_t i = 0; i < numElements; i++)
+    {
+        Scalar x;
+        is >> x;
+        input.challengeParts.push_back(x);
+    }
+
+    is >> numElements;
+    for (size_t i = 0; i < numElements; i++)
+    {
+        Scalar x;
+        is >> x;
+        input.responseParts.push_back(x);
+    }
+
+    return is;
+}

+ 8 - 0
prsona/src/server.cpp

@@ -809,6 +809,14 @@ std::vector<std::vector<Scalar>> PrsonaServer::generate_permutation_matrix(
     for (size_t i = 0; i < order.size(); i++)
         retval[order[i]][i] = Scalar(1);
 
+    for (size_t i = 0; i < retval.size(); i++)
+    {
+        std::cout << (i == 0 ? "[[" : " [");
+        for (size_t j = 0; j < retval[i].size(); j++)
+            std::cout << retval[i][j] << (j == retval[i].size() - 1 ? "]" : " ");
+        std::cout << (i == retval.size() - 1 ? "]" : "") << std::endl;
+    }
+
     return retval;
 }
 

+ 57 - 2
prsona/src/serverEntity.cpp

@@ -406,7 +406,53 @@ bool PrsonaServerEntity::receive_vote(
 void PrsonaServerEntity::transmit_new_user_data(
     const std::vector<Proof>& pi, PrsonaClient& newUser) const
 {
-    newUser.receive_new_user_data(pi);
+    transmit_new_user_data(pi, newUser, 0);
+}
+
+void PrsonaServerEntity::transmit_new_user_data(
+    const std::vector<Proof>& pi, PrsonaClient& newUser, size_t which) const
+{
+    Curvepoint shortTermPublicKey =
+        newUser.get_short_term_public_key();
+
+    Proof baseProof;
+    std::vector<Proof> serverEncryptedScoreProof;
+    TwistBipoint serverEncryptedScore =
+        get_current_server_encrypted_tally(baseProof, shortTermPublicKey, which);
+    serverEncryptedScoreProof.push_back(baseProof);
+    get_other_server_tally_commitments(serverEncryptedScoreProof, shortTermPublicKey, which);
+
+    baseProof.clear();
+    std::vector<Proof> userEncryptedScoreProof;
+    EGCiphertext userEncryptedScore =
+        get_current_user_encrypted_tally(baseProof, shortTermPublicKey, which);
+    userEncryptedScoreProof.push_back(baseProof);
+    get_other_user_tally_commitments(userEncryptedScoreProof, shortTermPublicKey, which);
+
+    baseProof.clear();
+    std::vector<Proof> voteMatrixProof;
+    std::vector<std::vector<CurveBipoint>> voteMatrix =
+        get_all_current_votes(baseProof, which);
+    voteMatrixProof.push_back(baseProof);
+    get_other_vote_matrix_commitments(voteMatrixProof, which);
+
+    baseProof.clear();
+    std::vector<Proof> pseudonymsProof;
+    std::vector<Curvepoint> currentPseudonyms =
+        get_current_pseudonyms(baseProof, which);
+    pseudonymsProof.push_back(baseProof);
+    get_other_pseudonyms_commitments(pseudonymsProof, which);
+
+    newUser.receive_new_user_data(
+        pi,
+        serverEncryptedScoreProof,
+        serverEncryptedScore,
+        userEncryptedScoreProof,
+        userEncryptedScore,
+        voteMatrixProof,
+        voteMatrix,
+        pseudonymsProof,
+        currentPseudonyms);
 }
 
 void PrsonaServerEntity::transmit_updates(PrsonaClient& currUser) const
@@ -428,7 +474,16 @@ void PrsonaServerEntity::transmit_updates(
     // ask for their new scores and vote row
     currUser.receive_fresh_generator(proofOfValidGenerator, freshGenerator);
 
-    currUser.receive_vote_tally();
+    Proof baseProof;
+    std::vector<Proof> fullProof;
+    Curvepoint shortTermPublicKey =
+        currUser.get_short_term_public_key();
+    EGCiphertext encryptedScore =
+        get_current_user_encrypted_tally(baseProof, shortTermPublicKey, which);
+    fullProof.push_back(baseProof);
+    get_other_user_tally_commitments(fullProof, shortTermPublicKey, which);
+
+    currUser.receive_vote_tally(fullProof, encryptedScore);
 }
 
 /*