OTExtensionWithMatrix OTExtensionWithMatrix::setup(TwoPartyPlayer& player, int128 delta, OT_ROLE role, bool passive) { BaseOT baseOT(128, 128, &player, INV_ROLE(role)); PRNG G; G.ReSeed(); baseOT.set_receiver_inputs(delta); baseOT.exec_base(false); return OTExtensionWithMatrix(baseOT, &player, passive); }
void PartSetup<FD>::insecure_debug_keys(vector<PartSetup<FD> >& setups, int nplayers, bool simple_pk) { cout << "generating INSECURE keys for debugging" << endl; setups.clear(); Rq_Element zero(params, evaluation, evaluation), one(params, evaluation, evaluation); zero.assign_zero(); one.assign_one(); PRNG G; G.ReSeed(); if (simple_pk) pk.assign(zero, zero, zero, zero - one); else pk.KeyGen(one, G, nplayers); setups.resize(nplayers, *this); setups[0].sk.assign(one); for (int i = 1; i < nplayers; i++) setups[i].sk.assign(zero); }
void PartSetup<FD>::fake(vector<FHE_SK>& sks, vector<T>& alphais, int nplayers, bool distributed) { insecure("global key generation"); if (distributed) cout << "Faking distributed key generation" << endl; else cout << "Faking key generation with extra noise" << endl; PRNG G; G.ReSeed(); pk = FHE_PK(params, FieldD.get_prime()); FHE_SK sk(params, FieldD.get_prime()); calpha = Ciphertext(params); sks.resize(nplayers, pk); alphais.resize(nplayers); if (distributed) DistKeyGen::fake(pk, sks, FieldD.get_prime(), nplayers); else { Rq_Element sk = FHE_SK(pk).s(); for (int i = 0; i < nplayers; i++) { Rq_Element ski = pk.sample_secret_key(G); sks[i].assign(ski); sk += ski; } pk.KeyGen(sk, G, nplayers); } for (int i = 0; i < nplayers; i++) { Plaintext_<FD> m(FieldD); m.randomize(G,Diagonal); Ciphertext calphai = pk.encrypt(m); calpha += calphai; alphais[i] = m.element(0); } }
void OTExtensionWithMatrix::transfer(int nOTs, const BitVector& receiverInput) { #ifdef OTEXT_TIMER timeval totalstartv, totalendv; gettimeofday(&totalstartv, NULL); #endif cout << "\tDoing " << nOTs << " extended OTs as " << role_to_str(ot_role) << endl; if (nOTs % nbaseOTs != 0) throw invalid_length(); //"nOTs must be a multiple of nbaseOTs\n"); if (nOTs == 0) return; // add k + s to account for discarding k OTs nOTs += 2 * 128; int slice = nOTs / nsubloops / 128; BitMatrix t1(nOTs), u(nOTs); senderOutputMatrices.resize(2, BitMatrix(nOTs)); // resize to account for extra k OTs that are discarded PRNG G; G.ReSeed(); BitVector newReceiverInput(nOTs); for (unsigned int i = 0; i < receiverInput.size_bytes(); i++) { newReceiverInput.set_byte(i, receiverInput.get_byte(i)); } //BitVector newReceiverInput(receiverInput); newReceiverInput.resize(nOTs); receiverOutputMatrix.resize(nOTs); for (int loop = 0; loop < nloops; loop++) { // randomize last 128 + 128 bits that will be discarded for (int i = 0; i < 4; i++) newReceiverInput.set_word(nOTs/64 - i, G.get_word()); // subloop for first part to interleave communication with computation for (int start = 0; start < nOTs / 128; start += slice) { vector<octetStream> os(2); BitMatrixSlice receiverOutputSlice(receiverOutputMatrix, start, slice); BitMatrixSlice senderOutputSlices[2] = { BitMatrixSlice(senderOutputMatrices[0], start, slice), BitMatrixSlice(senderOutputMatrices[1], start, slice) }; BitMatrixSlice t1Slice(t1, start, slice); BitMatrixSlice uSlice(u, start, slice); // expand with PRG and create correlation if (ot_role & RECEIVER) { for (int i = 0; i < nbaseOTs; i++) { receiverOutputSlice.randomize(i, G_sender[i][0]); t1Slice.randomize(i, G_sender[i][1]); } t1Slice ^= receiverOutputSlice; t1Slice ^= newReceiverInput; t1Slice.pack(os[0]); // t1 = receiverOutputMatrix; // t1 ^= newReceiverInput; // receiverOutputMatrix.print_side_by_side(t1); } #ifdef OTEXT_TIMER timeval commst1, commst2; gettimeofday(&commst1, NULL); #endif // send t0 + t1 + x send_if_ot_receiver(player, os, ot_role); // sender adjusts using base receiver bits if (ot_role & SENDER) { for (int i = 0; i < nbaseOTs; i++) // randomize base receiver output senderOutputSlices[0].randomize(i, G_receiver[i]); // u = t0 + t1 + x uSlice.unpack(os[1]); senderOutputSlices[0].conditional_xor(baseReceiverInput, u); } #ifdef OTEXT_TIMER gettimeofday(&commst2, NULL); #ifdef VERBOSE double commstime = timeval_diff(&commst1, &commst2); cout << "\t\tCommunication took time " << commstime/1000000 << endl << flush; #endif times["Communication"] += timeval_diff(&commst1, &commst2); #endif // transpose t0[i] onto receiverOutput and tmp (q[i]) onto senderOutput[i][0] #ifdef VERBOSE cout << "Starting matrix transpose\n" << flush << endl; #endif #ifdef OTEXT_TIMER timeval transt1, transt2; gettimeofday(&transt1, NULL); #endif // transpose in 128-bit chunks if (ot_role & RECEIVER) receiverOutputSlice.transpose(); if (ot_role & SENDER) senderOutputSlices[0].transpose(); #ifdef OTEXT_TIMER gettimeofday(&transt2, NULL); #ifdef VERBOSE double transtime = timeval_diff(&transt1, &transt2); cout << "\t\tMatrix transpose took time " << transtime/1000000 << endl << flush; #endif times["Matrix transpose"] += timeval_diff(&transt1, &transt2); #endif } // correlation check if (!passive_only) { #ifdef OTEXT_TIMER timeval startv, endv; gettimeofday(&startv, NULL); #endif check_correlation(nOTs, newReceiverInput); #ifdef OTEXT_TIMER gettimeofday(&endv, NULL); #ifdef VERBOSE double elapsed = timeval_diff(&startv, &endv); cout << "\t\tTotal correlation check time: " << elapsed/1000000 << endl << flush; #endif times["Total correlation check"] += timeval_diff(&startv, &endv); #endif } hash_outputs(nOTs); #ifdef OTEXT_TIMER #ifdef VERBOSE gettimeofday(&totalendv, NULL); double elapsed = timeval_diff(&totalstartv, &totalendv); cout << "\t\tTotal thread time: " << elapsed/1000000 << endl << flush; #endif #endif } #ifdef OTEXT_TIMER gettimeofday(&totalendv, NULL); times["Total thread"] += timeval_diff(&totalstartv, &totalendv); #endif receiverOutputMatrix.resize(nOTs - 2 * 128); senderOutputMatrices[0].resize(nOTs - 2 * 128); senderOutputMatrices[1].resize(nOTs - 2 * 128); }
int main(int argc, const char** argv) { ezOptionParser opt; opt.add( "", // Default. 1, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. "This player's number, 0/1 (required).", // Help description. "-p", // Flag token. "--player" // Flag token. ); opt.add( "5000", // Default. 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. "Base port number (default: 5000).", // Help description. "-pn", // Flag token. "--portnum" // Flag token. ); opt.add( "localhost", // Default. 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. "Host name(s) that player 0 is running on (default: localhost). Split with commas.", // Help description. "-h", // Flag token. "--hostname" // Flag token. ); opt.add( "1024", 0, 1, 0, "Number of extended OTs to run (default: 1024).", "-n", "--nOTs" ); opt.add( "128", // Default. 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. "Number of base OTs to run (default: 128).", // Help description. "-b", // Flag token. "--nbase" // Flag token. ); opt.add( "s", 0, 1, 0, "Mode for OT. a (asymmetric) or s (symmetric, i.e. play both sender/receiver) (default: s).", "-m", "--mode" ); opt.add( "1", 0, 1, 0, "Number of threads (default: 1).", "-x", "--nthreads" ); opt.add( "1", 0, 1, 0, "Number of loops (default: 1).", "-l", "--nloops" ); opt.add( "1", 0, 1, 0, "Number of subloops (default: 1).", "-s", "--nsubloops" ); opt.add( "", // Default. 0, // Required? 0, // Number of args expected. 0, // Delimiter if expecting multiple args. "Run in passive security mode.", // Help description. "-pas", // Flag token. "--passive" // Flag token. ); opt.add( "", // Default. 0, // Required? 0, // Number of args expected. 0, // Delimiter if expecting multiple args. "Write results to files.", // Help description. "-o", // Flag token. "--output" // Flag token. ); opt.add( "", // Default. 0, // Required? 0, // Number of args expected. 0, // Delimiter if expecting multiple args. "Use fake base OTs.", // Help description. "-f", // Flag token. "--fake" // Flag token. ); opt.parse(argc, argv); string hostname, ot_mode, usage; int my_num, portnum_base, nthreads, nloops, nsubloops, nbase; long nOTs; bool passive = false; opt.get("-p")->getInt(my_num); opt.get("-pn")->getInt(portnum_base); opt.get("-h")->getString(hostname); opt.get("-n")->getLong(nOTs); opt.get("-m")->getString(ot_mode); opt.get("--nthreads")->getInt(nthreads); opt.get("--nloops")->getInt(nloops); opt.get("--nsubloops")->getInt(nsubloops); opt.get("--nbase")->getInt(nbase); if (opt.isSet("-pas")) passive = true; if (!opt.isSet("-p")) { opt.getUsage(usage); cout << usage; exit(0); } cout << "Player 0 host name = " << hostname << endl; cout << "Creating " << nOTs << " extended OTs in " << nthreads << " threads\n"; cout << "Running in mode " << ot_mode << endl; if (passive) cout << "Running with PASSIVE security only\n"; if (nbase < 128) cout << "WARNING: only using " << nbase << " seed OTs, using these for OT extensions is insecure.\n"; OT_ROLE ot_role; if (ot_mode.compare("s") == 0) ot_role = BOTH; else if (ot_mode.compare("a") == 0) { if (my_num == 0) ot_role = SENDER; else ot_role = RECEIVER; } else { cerr << "Invalid OT mode argument: " << ot_mode << endl; exit(1); } // PRG for generating inputs etc PRNG G; G.ReSeed(); // Several names for multiplexing vector<Names> N; unsigned int pos = 0; while (pos < hostname.length()) { string::size_type new_pos = hostname.find(',', pos); if (new_pos == string::npos) new_pos = hostname.length(); int len = new_pos - pos; string name = hostname.substr(pos, len); pos = new_pos + 1; vector<string> names(2); names[my_num] = "localhost"; names[1-my_num] = name; N.push_back(Names(my_num, portnum_base, names)); } TwoPartyPlayer* P = new TwoPartyPlayer(N[0], 1 - my_num, 500); timeval baseOTstart, baseOTend; gettimeofday(&baseOTstart, NULL); // swap role for base OTs BaseOT baseOT = BaseOT(nbase, 128, 1 - my_num, P, INV_ROLE(ot_role)); FakeOT fakeOT = FakeOT(nbase, 128, 1 - my_num, P, INV_ROLE(ot_role)); BaseOT* bot_; if (opt.isSet("-f")) { cout << "WARNING: using fake base OTs, not secure\n"; bot_ = &fakeOT; } else { cout << "Using Chou-Orlandi base OTs\n"; bot_ = &baseOT; } BaseOT& bot = *bot_; bot.exec_base(); gettimeofday(&baseOTend, NULL); double basetime = timeval_diff(&baseOTstart, &baseOTend); cout << "\t\tBaseTime (" << role_to_str(ot_role) << "): " << basetime/1000000 << endl << flush; // Receiver send something to force synchronization // (since Sender finishes baseOTs before Receiver) int a = 3; vector<octetStream> os(2); os[0].store(a); P->send_receive_player(os); os[1].get(a); cout << a << endl; #ifdef BASE_OT_DEBUG // check base OTs bot.check(); // check after extending with PRG a few times for (int i = 0; i < 8; i++) { bot.extend_length(); bot.check(); } cout << "Verifying base OTs (debugging)\n"; #endif // divide nOTs between threads and loops nOTs = DIV_CEIL(nOTs, nthreads * nloops); // round up to multiple of base OTs and subloops // discount for discarded OTs nOTs = DIV_CEIL(nOTs + 2 * 128, nbase * nsubloops) * nbase * nsubloops - 2 * 128; cout << "Running " << nOTs << " OT extensions per thread and loop\n" << flush; BitVector receiverInput(nOTs); receiverInput.randomize(G); // convert baseOT selection bits to BitVector // (not already BitVector due to legacy PVW code) BitVector baseReceiverInput(nbase); for (int i = 0; i < nbase; i++) { baseReceiverInput.set_bit(i, bot.receiver_inputs[i]); } cout << "Initialize OT Extension\n"; vector<OT_thread_info> tinfos(nthreads); vector<pthread_t> threads(nthreads); timeval OTextstart, OTextend; gettimeofday(&OTextstart, NULL); #ifndef __MACH__ timespec start, end; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); #endif // copy base inputs/outputs for each thread vector<BitVector> base_receiver_input_copy(nthreads); vector<vector< vector<BitVector> > > base_sender_inputs_copy(nthreads, vector<vector<BitVector> >(nbase, vector<BitVector>(2))); vector< vector<BitVector> > base_receiver_outputs_copy(nthreads, vector<BitVector>(nbase)); vector<TwoPartyPlayer*> players(nthreads); for (int i = 0; i < nthreads; i++) { tinfos[i].receiverInput.assign(receiverInput); base_receiver_input_copy[i].assign(baseReceiverInput); for (int j = 0; j < nbase; j++) { base_sender_inputs_copy[i][j][0].assign(bot.sender_inputs[j][0]); base_sender_inputs_copy[i][j][1].assign(bot.sender_inputs[j][1]); base_receiver_outputs_copy[i][j].assign(bot.receiver_outputs[j]); } // now setup resources for each thread // round robin with the names players[i] = new TwoPartyPlayer(N[i%N.size()], 1 - my_num, (i+1) * 1000); tinfos[i].thread_num = i+1; tinfos[i].other_player_num = 1 - my_num; tinfos[i].nOTs = nOTs; tinfos[i].ot_ext = new OTExtensionWithMatrix(nbase, bot.length(), nloops, nsubloops, players[i], base_receiver_input_copy[i], base_sender_inputs_copy[i], base_receiver_outputs_copy[i], ot_role, passive); // create the thread pthread_create(&threads[i], NULL, run_otext_thread, &tinfos[i]); // extend base OTs with PRG for the next thread bot.extend_length(); } // wait for threads to finish for (int i = 0; i < nthreads; i++) { pthread_join(threads[i],NULL); cout << "thread " << i+1 << " finished\n" << flush; } map<string,long long>& times = tinfos[0].ot_ext->times; for (map<string,long long>::iterator it = times.begin(); it != times.end(); it++) { long long sum = 0; for (int i = 0; i < nthreads; i++) sum += tinfos[i].ot_ext->times[it->first]; cout << it->first << " on average took time " << double(sum) / nthreads / 1e6 << endl; } gettimeofday(&OTextend, NULL); #ifndef __MACH__ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); cout << "Processor time: " << double(timespec_diff(&start, &end)) / 1e9 << endl; #endif double totaltime = timeval_diff(&OTextstart, &OTextend); cout << "Time for OTExt threads (" << role_to_str(ot_role) << "): " << totaltime/1000000 << endl << flush; if (opt.isSet("-o")) { char filename[1024]; sprintf(filename, RECEIVER_INPUT, my_num); ofstream outf(filename); receiverInput.output(outf, false); outf.close(); sprintf(filename, RECEIVER_OUTPUT, my_num); outf.open(filename); for (unsigned int i = 0; i < tinfos[0].ot_ext->receiverOutput.size(); i++) tinfos[0].ot_ext->receiverOutput[i].output(outf, false); outf.close(); for (int i = 0; i < 2; i++) { sprintf(filename, SENDER_OUTPUT, my_num, i); outf.open(filename); for (int j = 0; j < nOTs; j++) tinfos[0].ot_ext->senderOutput[i][j].output(outf, false); outf.close(); } } }
void PairwiseGenerator<FD>::run() { PRNG G; G.ReSeed(); MAC_Check<typename FD::T> MC(machine.setup<FD>().alphai); while (total < machine.nTriplesPerThread) { timers["Randomization"].start(); a.randomize(G); b.randomize(G); timers["Randomization"].stop(); size_t prover_memory = EC.generate_proof(C, a, ciphertexts, cleartexts); timers["Plaintext multiplication"].start(); c.mul(a, b); timers["Plaintext multiplication"].stop(); timers["FFT of b"].start(); for (int i = 0; i < machine.sec; i++) b_mod_q.at(i).from_vec(b.at(i).get_poly()); timers["FFT of b"].stop(); timers["Proof exchange"].start(); size_t verifier_memory = EC.create_more(ciphertexts, cleartexts); timers["Proof exchange"].stop(); volatile_memory = max(prover_memory, verifier_memory); Rq_Element values({machine.setup<FD>().params, evaluation, evaluation}); for (int k = 0; k < machine.sec; k++) { producer.ai = a[k]; producer.bi = b[k]; producer.ci = c[k]; for (int j = 0; j < 3; j++) { timers["Plaintext multiplication"].start(); producer.macs[j].mul(machine.setup<FD>().alpha, producer.values[j]); timers["Plaintext multiplication"].stop(); if (j == 1) values = b_mod_q[k]; else { timers["Plaintext conversion"].start(); values.from_vec(producer.values[j].get_poly()); timers["Plaintext conversion"].stop(); } for (auto m : multipliers) m->multiply_alpha_and_add(producer.macs[j], values); } producer.reset(); total += producer.sacrifice(P, MC); } timers["Checking"].start(); MC.Check(P); timers["Checking"].stop(); } cout << "Could save " << 1e-9 * a.report_size(CAPACITY) << " GB" << endl; timers.insert(EC.timers.begin(), EC.timers.end()); timers.insert(producer.timers.begin(), producer.timers.end()); timers["Networking"] = P.timer; }