123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116 |
- #include <iostream>
- #include <fstream>
- #include <sstream>
- #include "networkClient.hpp"
- /********************************************************
- ********* *********
- ********* client networking public functions *********
- ********* *********
- ********************************************************/
- /*
- * CREATOR FOR A NEW CLIENT
- */
- PrsonaClient *create_client(
- std::default_random_engine& rng,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- size_t numServers)
- {
- std::vector<size_t> bandwidthData(2);
- // Get the servers' public BGN key
- BGNPublicKey publicKey = get_bgn_public_key(rng, serverIPs, serverPorts);
- // Get the H point used in ElGamal operations
- std::vector<Proof> generatorProof;
- Twistpoint blindGenerator = get_generator(rng, serverIPs, serverPorts, false, generatorProof, bandwidthData);
- // Make the actual client object
- PrsonaClient *retval = new PrsonaClient(generatorProof, blindGenerator, publicKey, numServers);
- // Get the current fresh generator
- generatorProof.clear();
- Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
- // Load this fresh generator into the client object
- retval->receive_fresh_generator(generatorProof, freshGenerator);
- // Make the client's current short term public key
- Proof proofOfValidSTPK;
- Twistpoint shortTermPublicKey = retval->get_short_term_public_key(proofOfValidSTPK);
- // Register this client with the servers
- register_new_client(rng, retval, serverIPs, serverPorts, proofOfValidSTPK, shortTermPublicKey);
- return retval;
- }
- /*
- * FUNCTIONS TO PERFORM OPERATIONS FOR EXPERIMENT
- */
- void make_vote(
- std::default_random_engine& rng,
- PrsonaClient* prsonaClient,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& target,
- int targetPort,
- size_t numClients,
- const CivetServer& civetServer,
- std::mutex& outputMtx,
- const std::string& outputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename)
- {
- std::uniform_int_distribution<int> voteDistribution(0, PrsonaBase::get_max_allowed_vote());
- std::uniform_int_distribution<int> numVoteDistribution(0, numClients);
- size_t numVotes = numVoteDistribution(rng);
- std::vector<size_t> bandwidthData(2);
- // Make the correct number of new votes, but shuffle where they go
- std::vector<Scalar> votes;
- std::vector<bool> replaces;
- for (size_t j = 0; j < numClients; j++)
- {
- votes.push_back(Scalar(voteDistribution(rng)));
- replaces.push_back(j < numVotes);
- }
- shuffle(replaces.begin(), replaces.end(), rng);
- std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer.getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Get current fresh generator (it's not guaranteed we've done this in the current epoch)
- std::vector<Proof> generatorProof;
- Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
- // Load fresh generator into client object
- prsonaClient->receive_fresh_generator(generatorProof, freshGenerator);
-
- // Make current short term public key
- Twistpoint shortTermPublicKey = prsonaClient->get_short_term_public_key();
- // Get this client's current encrypted votes
- std::vector<Proof> fullProof;
- std::vector<TwistBipoint> encryptedVotes = get_server_committed_val<std::vector<TwistBipoint>>(rng, serverIPs, serverPorts, REQUEST_VOTE_ROW_URI, REQUEST_VOTE_ROW_COMMITMENT_URI, fullProof, shortTermPublicKey, bandwidthData);
- // Use the client's method to make valid new votes (and their proof)
- std::vector<Proof> voteProof;
- encryptedVotes = prsonaClient->make_votes(voteProof, fullProof, encryptedVotes, votes, replaces);
- // Serialize this data
- std::string data = make_vote_string(voteProof, encryptedVotes, shortTermPublicKey);
- // Send the new votes (and their proof) to the chosen server
- send_item(rng, target, targetPort, SUBMIT_VOTE_URI, data, false, bandwidthData);
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer.getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- }
- bool make_reputation_proof(
- std::default_random_engine& rng,
- PrsonaClient* prsonaClient,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& target,
- int targetPort,
- size_t numClients,
- const CivetServer& civetServer,
- std::mutex& outputMtx,
- const std::string& outputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename)
- {
- std::vector<size_t> bandwidthData(2);
- std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer.getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Get current fresh generator (it's not guaranteed we've done this in the current epoch)
- std::vector<Proof> generatorProof;
- Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
- // Load fresh generator into client object
- prsonaClient->receive_fresh_generator(generatorProof, freshGenerator);
- // Make current short term public key
- Twistpoint shortTermPublicKey = prsonaClient->get_short_term_public_key();
- // Get this client's current encrypted score
- std::vector<Proof> encryptedScoreProof;
- EGCiphertext encryptedScore = get_server_committed_val<EGCiphertext>(rng, serverIPs, serverPorts, REQUEST_CLIENT_TALLY_URI, REQUEST_CLIENT_TALLY_COMMITMENT_URI, encryptedScoreProof, shortTermPublicKey, bandwidthData);
- // Load this current encrypted score into client object
- prsonaClient->receive_vote_tally(encryptedScoreProof, encryptedScore);
- // Zero will always be a valid threshold
- Scalar threshold(0);
- // Use client object to generate a correct reputation proof with the chosen parameters
- std::vector<Proof> repProof = prsonaClient->generate_reputation_proof(threshold, numClients);
- // Serialize that proof
- std::string data = make_rep_proof_string(repProof, shortTermPublicKey, threshold);
- // Send that proof to a chosen client (and set up a file to receive whether or not the client accepted the proof)
- char *responseFile = send_item(rng, target, targetPort, VERIFY_REPUTATION_PROOF_URI, data, true, bandwidthData);
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer.getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- // The other client will give one byte back, containing whether or not it accepted the proof
- std::ifstream response(responseFile);
- char passed = response.get();
- // Delete the temp file
- remove(responseFile);
- delete [] responseFile;
- return passed == '\x01';
- }
- /*********************************************************
- ********* *********
- ********* client networking private functions *********
- ********* *********
- *********************************************************/
- /*
- * HELPERS TO ADD THIS CLIENT TO SERVERS
- */
- void register_new_client(
- std::default_random_engine& rng,
- PrsonaClient *newUser,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const Proof& proofOfValidSTPK,
- const Twistpoint& shortTermPublicKey)
- {
- struct synchronization_tool sync;
- char *filename = NULL;
- struct mg_connection *conn = NULL;
- // Serialize the relevant data that needs to be sent
- std::stringstream buffer;
- std::string data;
- buffer << proofOfValidSTPK;
- buffer << shortTermPublicKey;
- data = buffer.str();
- // Set up connection to a server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!conn)
- {
- // Pick a (pseudo-)random server to register this client with
- std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
- size_t whichServer = distribution(rng);
- conn = mg_connect_websocket_client(serverIPs[whichServer].c_str(), serverPorts[whichServer], USE_SSL, NULL, 0, SUBMIT_NEW_CLIENT_URI, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't register new client" << std::endl;
- }
- // Establish a file to receive proof of addition to system at
- filename = set_temp_filename(rng, conn);
- // Send client data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for response
- while (!sync.val)
- sync.cv.wait(lck);
- // Close connection
- mg_close_connection(conn);
- // Un-serialize proof of addition to system
- std::vector<Proof> proofOfValidAddition = get_valid_addition_proof_from_file(filename);
- // Remove temp file used to receive serialized data
- remove(filename);
- delete [] filename;
- // Verify that the client was correctly added to the server
- verify_valid_addition(rng, newUser, serverIPs, serverPorts, proofOfValidAddition, shortTermPublicKey);
- }
- void verify_valid_addition(
- std::default_random_engine& rng,
- PrsonaClient *newUser,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::vector<Proof>& proofOfValidAddition,
- const Twistpoint& shortTermPublicKey)
- {
- std::vector<size_t> bandwidthData(2);
- // Get general information on state of system from servers
- std::vector<Proof> serverEncryptedScoreProof;
- CurveBipoint serverEncryptedScore = get_server_committed_val<CurveBipoint>(rng, serverIPs, serverPorts, REQUEST_SERVER_TALLY_URI, REQUEST_SERVER_TALLY_COMMITMENT_URI, serverEncryptedScoreProof, shortTermPublicKey, bandwidthData);
- std::vector<Proof> userEncryptedScoreProof;
- EGCiphertext userEncryptedScore = get_server_committed_val<EGCiphertext>(rng, serverIPs, serverPorts, REQUEST_CLIENT_TALLY_URI, REQUEST_CLIENT_TALLY_COMMITMENT_URI, userEncryptedScoreProof, shortTermPublicKey, bandwidthData);
- std::vector<Proof> voteMatrixProof;
- std::vector<std::vector<TwistBipoint>> voteMatrix = get_server_committed_val<std::vector<std::vector<TwistBipoint>>>(rng, serverIPs, serverPorts, REQUEST_VOTE_MATRIX_URI, REQUEST_VOTE_MATRIX_COMMITMENT_URI, voteMatrixProof, shortTermPublicKey, bandwidthData);
- std::vector<Proof> pseudonymsProof;
- std::vector<Twistpoint> currentPseudonyms = get_server_committed_val<std::vector<Twistpoint>>(rng, serverIPs, serverPorts, REQUEST_PSEUDONYMS_URI, REQUEST_PSEUDONYMS_COMMITMENT_URI, pseudonymsProof, shortTermPublicKey, bandwidthData);
- // Use client's normal verification method
- newUser->receive_new_user_data(proofOfValidAddition, serverEncryptedScoreProof, serverEncryptedScore, userEncryptedScoreProof, userEncryptedScore, voteMatrixProof, voteMatrix, pseudonymsProof, currentPseudonyms);
- }
- /*
- * GETTERS FOR VARIOUS SERVER VALUES
- */
- Twistpoint get_generator(
- std::default_random_engine& rng,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- bool fresh,
- std::vector<Proof>& pi,
- std::vector<size_t>& bandwidthData)
- {
- pi.clear();
- struct synchronization_tool sync;
- char *filename = NULL;
- struct mg_connection *conn = NULL;
- const char* whichUri = (fresh ? REQUEST_FRESH_GENERATOR_URI : REQUEST_EG_BLIND_GENERATOR_URI);
- // Set up connection to a server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!conn)
- {
- // Pick a (pseudo-)random server to get the generator from
- std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
- size_t whichServer = distribution(rng);
- conn = mg_connect_websocket_client(serverIPs[whichServer].c_str(), serverPorts[whichServer], USE_SSL, NULL, 0, whichUri, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't connect to servers to get generator" << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
- // Establish a file to receive generator at
- filename = set_temp_filename(rng, conn);
- // Tell server to go ahead with data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for data
- while (!sync.val)
- sync.cv.wait(lck);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- // Un-serialize generator
- Twistpoint retval = get_generator_from_file(filename, pi);
- // Remove temp file used to receive serialized data
- remove(filename);
- delete [] filename;
- return retval;
- }
- BGNPublicKey get_bgn_public_key(
- std::default_random_engine& rng,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts)
- {
- struct synchronization_tool sync;
- char *filename = NULL;
- struct mg_connection *conn = NULL;
- // Set up connection to a server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!conn)
- {
- // Pick a (pseudo-)random server to get bgn data from
- std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
- size_t whichServer = distribution(rng);
- conn = mg_connect_websocket_client(serverIPs[whichServer].c_str(), serverPorts[whichServer], USE_SSL, NULL, 0, REQUEST_BGN_PUBKEY_URI, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't connect to servers to obtain BGN details" << std::endl;
- }
- // Establish a file to receive BGN public key at
- filename = set_temp_filename(rng, conn);
-
- // Tell server to go ahead with data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for data
- while (!sync.val)
- sync.cv.wait(lck);
- // Close connection
- mg_close_connection(conn);
- // Un-serialize BGN public key
- BGNPublicKey retval = get_bgn_public_key_from_file(filename);
- // Remove temp file used to receive serialized data
- remove(filename);
- delete [] filename;
- return retval;
- }
- template <typename T>
- T get_server_committed_val(
- std::default_random_engine& rng,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const char *firstUri,
- const char *commitUri,
- std::vector<Proof>& pi,
- const Twistpoint& shortTermPublicKey,
- std::vector<size_t>& bandwidthData)
- {
- pi.clear();
- // Pick a (pseudo-)random server to get a committed-to value from
- std::uniform_int_distribution<size_t> distribution(0, serverIPs.size() - 1);
- size_t whichServer = distribution(rng);
- // Get the value itself
- Proof firstProof;
- T retval = get_first_committed_val<T>(rng, serverIPs[whichServer], serverPorts[whichServer], firstUri, firstProof, shortTermPublicKey, bandwidthData);
- // Get all the other server's hashes of the value (to confirm they all agree on it)
- pi.push_back(firstProof);
- get_additional_commitment(rng, serverIPs, serverPorts, serverIPs[whichServer], serverPorts[whichServer], commitUri, pi, shortTermPublicKey, bandwidthData);
- return retval;
- }
- template EGCiphertext get_server_committed_val<EGCiphertext>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
- template CurveBipoint get_server_committed_val<CurveBipoint>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
- template std::vector<Twistpoint> get_server_committed_val<std::vector<Twistpoint>>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
- template std::vector<TwistBipoint> get_server_committed_val<std::vector<TwistBipoint>>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
- template std::vector<std::vector<TwistBipoint>> get_server_committed_val<std::vector<std::vector<TwistBipoint>>>(std::default_random_engine &, const std::vector<std::string> &, const std::vector<int> &, const char *, const char *, std::vector<Proof> &, const Twistpoint &, std::vector<size_t>&);
- /*
- * HELPERS FOR GENERALIZED GETTER FUNCTION
- */
- template <typename T>
- T get_first_committed_val(
- std::default_random_engine& rng,
- const std::string& serverIP,
- int serverPort,
- const char *firstUri,
- Proof& pi,
- const Twistpoint& shortTermPublicKey,
- std::vector<size_t>& bandwidthData)
- {
- struct synchronization_tool sync;
- char *filename = NULL;
- struct mg_connection *conn = NULL;
- // Serialize the relevant data that needs to be sent
- std::stringstream buffer;
- std::string data;
- buffer << shortTermPublicKey;
- data = buffer.str();
- // Set up connection to a server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIP.c_str(), serverPort, USE_SSL, NULL, 0, firstUri, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Trouble getting encrypted score from server at " << serverIP << ":" << serverPort << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
- // Establish a file to receive committed-to value at
- filename = set_temp_filename(rng, conn);
- // Send request data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for response
- while (!sync.val)
- sync.cv.wait(lck);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- // Un-serialize committed-to value
- T retval = get_committed_val_from_file<T>(filename, pi);
- // Remove temp file used to receive serialized data
- remove(filename);
- delete [] filename;
- return retval;
- }
- void get_additional_commitment(
- std::default_random_engine& rng,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& skipIP,
- int skipPort,
- const char *commitUri,
- std::vector<Proof>& pi,
- const Twistpoint& shortTermPublicKey,
- std::vector<size_t>& bandwidthData)
- {
- std::vector<char *> commitmentFilenames;
- std::vector<struct synchronization_tool *> commitmentSyncs;
- // Serialize the relevant data that needs to be sent
- std::stringstream buffer;
- std::string data;
- buffer << shortTermPublicKey;
- data = buffer.str();
- // Ask each server (besides the one we got the value from) what the hash of it is
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- if (serverIPs[i] == skipIP && serverPorts[i] == skipPort)
- continue;
- struct synchronization_tool *currSync = new struct synchronization_tool;
- commitmentSyncs.push_back(currSync);
- struct mg_connection *conn = NULL;
- // Set up connection to a server
- std::unique_lock<std::mutex> lck(currSync->mtx);
- currSync->val = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, commitUri, "null", file_websocket_data_handler, file_websocket_close_handler, currSync);
- if (!conn)
- std::cerr << "Trouble getting commitment from server at " << serverIPs[i] << ":" << serverPorts[i] << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
- // Establish a file to receive hash at
- commitmentFilenames.push_back(set_temp_filename(rng, conn));
- // Send request data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for response
- while (!currSync->val)
- currSync->cv.wait(lck);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- }
-
- for (size_t i = 0; i < commitmentFilenames.size(); i++)
- {
- // Un-serialize hash
- pi.push_back(get_commitment_from_file(commitmentSyncs[i], commitmentFilenames[i]));
- // Clean up the std::mutex used for this hash
- delete commitmentSyncs[i];
- // Delete temp file used to receive serialized data
- remove(commitmentFilenames[i]);
- delete [] commitmentFilenames[i];
- }
- }
- /*
- * FILE I/O HELPERS FOR ALL GETTERS
- */
- std::vector<Proof> get_valid_addition_proof_from_file(
- const char *filename)
- {
- std::ifstream additionFile(filename);
- std::vector<Proof> retval;
- BinarySizeT sizeOfVector;
- additionFile >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- additionFile >> currProof;
- retval.push_back(currProof);
- }
- return retval;
- }
- Twistpoint get_generator_from_file(
- const char *filename,
- std::vector<Proof>& pi)
- {
- std::ifstream genFile(filename);
- BinarySizeT sizeOfVector;
- genFile >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- genFile >> currProof;
- pi.push_back(currProof);
- }
- Twistpoint retval;
- genFile >> retval;
- return retval;
- }
- BGNPublicKey get_bgn_public_key_from_file(
- const char *filename)
- {
- std::ifstream bgnFile(filename);
- BGNPublicKey publicKey;
- bgnFile >> publicKey;
- return publicKey;
- }
- // User-encrytped score
- template <>
- EGCiphertext get_committed_val_from_file<EGCiphertext>(
- const char *filename,
- Proof& pi)
- {
- std::ifstream valFile(filename);
- EGCiphertext retval;
- valFile >> pi;
- valFile >> retval;
- return retval;
- }
- // Server-encrytped score
- template <>
- CurveBipoint get_committed_val_from_file<CurveBipoint>(
- const char *filename,
- Proof& pi)
- {
- std::ifstream valFile(filename);
- CurveBipoint retval;
- valFile >> pi;
- valFile >> retval;
- return retval;
- }
- // Current pseudonyms
- template <>
- std::vector<Twistpoint> get_committed_val_from_file<std::vector<Twistpoint>>(
- const char *filename,
- Proof& pi)
- {
- std::ifstream valFile(filename);
- valFile >> pi;
- std::vector<Twistpoint> retval;
- BinarySizeT sizeOfVector;
- valFile >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Twistpoint currVote;
- valFile >> currVote;
- retval.push_back(currVote);
- }
- return retval;
- }
- // Vote row
- template <>
- std::vector<TwistBipoint> get_committed_val_from_file<std::vector<TwistBipoint>>(
- const char *filename,
- Proof& pi)
- {
- std::ifstream valFile(filename);
- valFile >> pi;
- std::vector<TwistBipoint> retval;
- BinarySizeT sizeOfVector;
- valFile >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- TwistBipoint currVote;
- valFile >> currVote;
- retval.push_back(currVote);
- }
- return retval;
- }
- // Full vote matrix
- template <>
- std::vector<std::vector<TwistBipoint>> get_committed_val_from_file<std::vector<std::vector<TwistBipoint>>>(
- const char *filename,
- Proof& pi)
- {
- std::ifstream valFile(filename);
- valFile >> pi;
- std::vector<std::vector<TwistBipoint>> retval;
- BinarySizeT sizeOfVector;
- valFile >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- std::vector<TwistBipoint> currRow;
- for (size_t j = 0; j < sizeOfVector.val(); j++)
- {
- TwistBipoint currVote;
- valFile >> currVote;
- currRow.push_back(currVote);
- }
- retval.push_back(currRow);
- }
- return retval;
- }
- // NOTE: this function is the weird only case in which its usage will not assume you already have possession of the file lock to read from
- Proof get_commitment_from_file(
- struct synchronization_tool *sync,
- const char *filename)
- {
- std::unique_lock<std::mutex> lck(sync->mtx);
- std::ifstream scoreFile(filename);
- Proof retval;
- scoreFile >> retval;
- return retval;
- }
- /*
- * GENERALIZED SENDER FOR ORCHESTRATOR-SIGNALED OPERATIONS
- */
- char *send_item(
- std::default_random_engine& rng,
- const std::string& target,
- int targetPort,
- const char* whichUri,
- const std::string& data,
- bool responseExpected,
- std::vector<size_t>& bandwidthData)
- {
- struct synchronization_tool sync;
- char *retval = NULL;
- struct mg_connection *conn = NULL;
- // Keep looping until item has been correctly received
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- sync.val2 = 0;
- while (!sync.val)
- {
- // Set up connection to a server
- while (!conn)
- {
- if (responseExpected)
- conn = mg_connect_websocket_client(target.c_str(), targetPort, USE_SSL, NULL, 0, whichUri, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- else
- conn = mg_connect_websocket_client(target.c_str(), targetPort, USE_SSL, NULL, 0, whichUri, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't connect to server for purposes of sending item." << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), false);
- // Set up a file to receive a response at (if it's expected)
- if (responseExpected)
- retval = set_temp_filename(rng, conn);
- // Send request data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait until the server has closed the connection
- while (!sync.val2)
- sync.cv.wait(lck);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), false);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- conn = NULL;
- }
- return retval;
- }
- /*
- * DATA SERIALIZERS
- */
- std::string make_vote_string(
- const std::vector<Proof>& pi,
- const std::vector<TwistBipoint>& newVotes,
- const Twistpoint& shortTermPublicKey)
- {
- std::stringstream buffer;
- BinarySizeT sizeOfVector;
- sizeOfVector.set(pi.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << pi[i];
- sizeOfVector.set(newVotes.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << newVotes[i];
- buffer << shortTermPublicKey;
- // Clients always tell the server they should share the vote row with other servers; servers never tell other servers to do this
- BinaryBool shouldDeal(true);
- buffer << shouldDeal;
- return buffer.str();
- }
- std::string make_rep_proof_string(
- const std::vector<Proof>& pi,
- const Twistpoint& shortTermPublicKey,
- const Scalar& threshold)
- {
- std::stringstream buffer;
- BinarySizeT sizeOfVector;
- sizeOfVector.set(pi.size());
-
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << pi[i];
- buffer << shortTermPublicKey;
- buffer << threshold;
- return buffer.str();
- }
- /**********************************************************
- **** ****
- **** other client-relevant handler member functions ****
- **** ****
- **********************************************************/
- /*
- * CLIENT READY HANDLER
- */
- ClientReadyHandler::ClientReadyHandler(
- struct synchronization_tool *exitSync)
- : exitSync(exitSync)
- { /* */ }
- bool ClientReadyHandler::handleGet(
- CivetServer *server,
- struct mg_connection *conn)
- {
- std::unique_lock<std::mutex> exitLock(exitSync->mtx, std::defer_lock);
- if (!exitLock.try_lock())
- {
- mg_printf(conn, "HTTP/1.1 503 Service Unavailable\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Client is still making previous votes or a reputation proof.\n");
- }
- else
- {
- mg_printf(conn, "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Client is ready to move forward.\n");
- }
- return true;
- }
- /*********************************************************
- **** ****
- **** PrsonaClientWebSocketHandler member functions ****
- **** ****
- *********************************************************/
- /*
- * CONSTRUCTOR
- */
- PrsonaClientWebSocketHandler::PrsonaClientWebSocketHandler(
- std::default_random_engine& rng,
- PrsonaClient *prsonaClient,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- std::mutex& outputMtx,
- const std::string& outputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename)
- : rng(rng), prsonaClient(prsonaClient), serverIPs(serverIPs), serverPorts(serverPorts), outputMtx(outputMtx), outputFilename(outputFilename), usageMtx(usageMtx), usageFilename(usageFilename)
- { /* */ }
- /*
- * REQUIRED BY INHERITED CLASS
- */
- bool PrsonaClientWebSocketHandler::handleConnection(
- CivetServer *server,
- const struct mg_connection *conn)
- {
- const struct mg_request_info *info = mg_get_request_info(conn);
-
- // Check if the request being made is something this client can respond to
- bool flag = (info->query_string && info->query_string[0] == PRSONA_VERIFY_REPUTATION_PROOF);
- return flag;
- }
- void PrsonaClientWebSocketHandler::handleReadyState(
- CivetServer *server,
- struct mg_connection *conn)
- {
- const struct mg_request_info *info = mg_get_request_info(conn);
- // Set filenames for query types that will need to un-serialize data to respond correctly
- switch (info->query_string[0])
- {
- case PRSONA_VERIFY_REPUTATION_PROOF:
- set_temp_filename(rng, conn);
- break;
- default:
- mg_set_user_connection_data(conn, NULL);
- break;
- }
- }
- bool PrsonaClientWebSocketHandler::handleData(
- CivetServer *server,
- struct mg_connection *conn,
- int bits,
- char *data,
- size_t data_len)
- {
- char *filename = (char *) mg_get_user_connection_data(conn);
- FILE *currFile = NULL;
- switch (bits & 0xf)
- {
- // Requester has indicated they have sent all relevant data
- case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
- case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
- generate_response(server, conn, filename);
- break;
- // Requester has sent more data (which may theoretically be broken up into multiple packets)
- case MG_WEBSOCKET_OPCODE_BINARY:
- case MG_WEBSOCKET_OPCODE_CONTINUATION:
- currFile = fopen(filename, "ab");
- fwrite(data, sizeof(char), data_len, currFile);
- fclose(currFile);
- return true;
- // Something strange has happened
- default:
- std::cerr << "Unknown packet type received. Failing." << std::endl;
- break;
- }
- return false;
- }
- void PrsonaClientWebSocketHandler::handleClose(
- CivetServer *server,
- const struct mg_connection *conn)
- {
- char *filename = (char *) mg_get_user_connection_data(conn);
- // If we didn't have a temp file for this request, don't do anything
- if (!filename)
- return;
- // If we did, delete it
- remove(filename);
- delete [] filename;
- }
- /*
- * RESPONSE ROUTER FUNCTION
- */
- void PrsonaClientWebSocketHandler::generate_response(
- CivetServer *server,
- struct mg_connection *conn,
- const char *filename)
- {
- const struct mg_request_info *info = mg_get_request_info(conn);
- // Select the correct response for this type of request
- switch (info->query_string[0])
- {
- case PRSONA_VERIFY_REPUTATION_PROOF:
- verify_reputation_proof(server, conn, filename);
- break;
- default:
- break;
- }
- }
- /*
- * REPUTATION PROOF RESPONSE
- */
- void PrsonaClientWebSocketHandler::verify_reputation_proof(
- CivetServer *civetServer,
- struct mg_connection *conn,
- const char *filename)
- {
- std::vector<Proof> pi;
- Twistpoint shortTermPublicKey;
- Scalar threshold;
- std::vector<size_t> bandwidthData(2);
- // Un-serialize the reputation proof
- std::ifstream file(filename);
- file.ignore(std::numeric_limits<std::streamsize>::max());
- std::streamsize bandwidthRcv = file.gcount();
- file.clear();
- file.seekg(0, std::ios_base::beg);
- BinarySizeT sizeOfVector;
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- file >> currProof;
- pi.push_back(currProof);
- }
- file >> shortTermPublicKey;
- file >> threshold;
- std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer->getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Get current fresh generator (it's not guaranteed we've done this in the current epoch)
- std::vector<Proof> generatorProof;
- Twistpoint freshGenerator = get_generator(rng, serverIPs, serverPorts, true, generatorProof, bandwidthData);
- // Load fresh generator into client object
- prsonaClient->receive_fresh_generator(generatorProof, freshGenerator);
- // Get what the servers say is this user's encrypted score
- std::vector<Proof> encryptedScoreProof;
- EGCiphertext encryptedScore = get_server_committed_val<EGCiphertext>(rng, serverIPs, serverPorts, REQUEST_CLIENT_TALLY_URI, REQUEST_CLIENT_TALLY_COMMITMENT_URI, encryptedScoreProof, shortTermPublicKey, bandwidthData);
- // Check if the proof verifies correctly
- bool flag = prsonaClient->verify_reputation_proof(pi, shortTermPublicKey, threshold, encryptedScoreProof, encryptedScore);
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer->getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0] + bandwidthRcv;
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1] + 1;
- write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- // Tell the prover whether or not we accept the proof
- std::string data = flag ? "\x01" : "\x00";
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), 1);
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
|