#include "Tools/Subroutines.h" #include "Exceptions/Exceptions.h" #include "Tools/random.h" #include "EncCommit.h" #include "FHE/P2Data.h" #include #include using namespace std; // XXXX File_prefix is only used for active code #ifndef file_prefix #define file_prefix "/tmp/" #endif template EncCommit::~EncCommit() { for (auto& x : timers) cout << x.first << ": " << x.second.elapsed() << endl; } // Set up for covert template void EncCommit::init(const Player& PP,const FHE_PK& fhepk,int params,condition cc) { P=&PP; pk=&fhepk; num_runs=params; cond=cc; covert=true; } // Set up for active template void EncCommit::init(const Player& PP,const FHE_PK& fhepk,condition cc,const FD& FieldD,int thr) { covert=false; thread=thr; const FHE_Params& params=fhepk.get_params(); t = DEFAULT_T; b = DEFAULT_B; TT = b * t; // Probability of cheating in one run is... // ee:=(1-b)*log(t)/log(2.0)-b*log(1+log(log(2)))/log(2.0)+log(M)/log(2); // Valid prover could fail, so we allow M failures giving // prob of valid prover failing of (1/delta)^M M=5; P=&PP; pk=&fhepk; cond=cc; // Currently cannot deal with cond!=Full for active adversaries if (cond!=Full) { throw not_implemented(); } c.resize(t); m.resize(t, Plaintext(FieldD)); for (int i=0; i void EncCommit::next_covert(Plaintext& mess, vector& C) const { covert_generation(mess, C, {size_t(P->num_players()), pk}, P, num_runs, cond); } template void covert_generation(Plaintext_& mess, vector& C, const vector& pks, const Player* P, int num_runs, condition cond) { const FHE_Params& params=(*pks[0]).get_params(); /* Commit to the seeds */ vector< vector > seeds(num_runs, vector((*P).num_players())); vector< vector > Comm_seeds(num_runs, vector((*P).num_players())); vector Open_seeds(num_runs); vector G(num_runs); Commit_To_Seeds(G,seeds,Comm_seeds,Open_seeds,*P,num_runs); // Generate the messages and ciphertexts vector< Plaintext_ > m(num_runs,mess.get_field()); vector c(num_runs,params); Random_Coins rc(params); for (int i=0; imy_num()]).encrypt(c[i],m[i],rc); //cout << "xxxxxxxxxxxxxxxxxxxxx" << endl; //cout << i << "\t" << (*P).socket(P.my_num()) << endl; //cout << i << "\t" << m[i] << endl; //cout << i << "\t" << rc << endl; //cout << i << "\t" << c[i] << endl; } // Broadcast and receive ciphertexts vector< vector > ctx(num_runs, vector ((*P).num_players())); for (int i=0; i e((*P).num_players()); vector Comm_e((*P).num_players()); vector Open_e((*P).num_players()); Commit_To_Challenge(e,Comm_e,Open_e,*P,num_runs); // Open challenge int challenge=Open_Challenge(e,Open_e,Comm_e,*P,num_runs); // Open seeds, but not the challenge run Open(seeds,Comm_seeds,Open_seeds,*P,num_runs,challenge); // Now check all the prior executions Plaintext_ mm(mess.get_field()); Ciphertext cc(params); octetStream occ; for (int i=0; i void EncCommit::next_active(Plaintext& mess, vector& C) const { const FHE_Params& params=(*pk).get_params(); if (not has_left()) { Create_More(); } mess=m[cnt]; C.resize((*P).num_players(),Ciphertext(params)); for (int i=0; i<(*P).num_players(); i++) { C[i]=c[cnt][i]; } cnt--; } bool check_norm(const Rq_Element& value, const bigint& bound) { bool res = (value.infinity_norm() > bound); if (res) cout << "out of bound by (log) " << log2(value.infinity_norm().get_d() / bound.get_d()) << endl; return res; } template void EncCommit::Create_More() const { const FHE_Params& params=(*pk).get_params(); // Tweak by using p rather than p/2, as we do not center the ciphertexts int rhoi=(int) (6*params.get_R()); bigint comm = active_mask(params.phi_m(), b, t); bigint Bound1=m[0].get_field().get_prime()*comm; bigint Bound2=comm; bigint Bound3=rhoi*comm; bigint UBound1=2*(Bound1-m[0].get_field().get_prime()); bigint UBound2=2*(Bound2-1); bigint UBound3=2*(Bound3-rhoi); int my_num=(*P).my_num(); /* First generate the good ciphertexts and messages for myself */ PRNG G; G.ReSeed(); vector rc(t,params); for (int i=0; i > ctx_c(t, vector ((*P).num_players())); for (int i=0; i > seeds(2*TT, vector((*P).num_players())); vector< vector > Comm_seeds(2*TT, vector((*P).num_players())); vector< octetStream > ctx_Delta((*P).num_players()); Ciphertext ctx_C(params); vector Open_seeds(2*TT); vector Gseed(2*TT); vector open(2*TT); vector z(4,Rq_Element(params.FFTD(),polynomial,polynomial)); vector Comm_data((*P).num_players()); char filename[1024]; bool fail=true; int iter=0; while (fail && iter(G, numBits(Bound1))); } rr.generateUniform(G,Bound2,Bound3,Bound3); (*pk).quasi_encrypt(cc,mm,rr); occ.reset_write_head(); cc.pack(occ); ctx_D.reset_write_head(); ctx_C.pack(ctx_D); if (!occ.equals(ctx_D)) { cout << "Error opening position " << i << endl; // Can only get here if Prover is trying to cheat so abort throw bad_enccommit(); } } } inpf.close(); } } // Now move all unopened values of ctx_Delta,seeds to the first TT positions // - Done via index int count=0; vector index(TT); for (int i=0; i<2*TT; i++) { if (open[i]==0) { index[count]=i; count++; } } for (int i=0; i(G, numBits(Bound1))); } rc_Delta.generateUniform(G,Bound2,Bound3,Bound3); auto vm=m[i].get_iterator(); z[0].from(vm); add(z[0],z[0],m_Delta); add(rr,rc[i],rc_Delta); z[1]=rr.u(); z[2]=rr.v(); z[3]=rr.w(); // Step b if (check_norm(z[0], UBound1)) { cout << "F0:" << i << " " << j << endl; fail=true; } if (check_norm(z[1], UBound2)) { cout << "F1:" << i << " " << j << endl; fail=true; } if (check_norm(z[2], UBound3)) { cout << "F2:" << i << " " << j << endl; fail=true; } if (check_norm(z[3], UBound3)) { cout << "F3:" << i << " " << j << endl; fail=true; } // Set my data to transmit Comm_data[my_num].reset_write_head(); if (!fail) { z[0].pack(Comm_data[my_num]); z[1].pack(Comm_data[my_num]); z[2].pack(Comm_data[my_num]); z[3].pack(Comm_data[my_num]); } (*P).Broadcast_Receive(Comm_data); Ciphertext enc1(params),enc2(params),eDelta(params); octetStream oe1,oe2; sprintf(filename,"%sctx_Delta-%d-%d-%d",file_prefix,my_num,index[b*i+j],thread); ifstream inpf(filename); for (int k=0; k<(*P).num_players(); k++) { timers["ciphertext reading"].start(); ctx_C.input(inpf); timers["ciphertext reading"].stop(); if (k!=my_num) { if (Comm_data[k].get_length()==0) { fail=true; } else { z[0].unpack(Comm_data[k]); z[1].unpack(Comm_data[k]); z[2].unpack(Comm_data[k]); z[3].unpack(Comm_data[k]); // Check size (any wrong means proving cheating) if (z[0].infinity_norm()>UBound1) { cout << "R0" << endl; throw bad_enccommit(); } if (z[1].infinity_norm()>UBound2) { cout << "R1" << endl; throw bad_enccommit(); } if (z[2].infinity_norm()>UBound3) { cout << "R2" << endl; throw bad_enccommit(); } if (z[3].infinity_norm()>UBound3) { cout << "R3" << endl; throw bad_enccommit(); } // Need to encrypt with z0,..,z1 and check equal to ci+delta_{b*i+j} rr.assign(z[1],z[2],z[3]); (*pk).quasi_encrypt(enc1,z[0],rr); add(enc2,c[i][k],ctx_C); enc1.pack(oe1); enc2.pack(oe2); // If this is not true then we have a cheating prover if (!oe1.equals(oe2)) { cout << "EFail " << k << endl; throw bad_enccommit(); } } } } inpf.close(); } } if (fail) { iter++; } } if (fail) { throw bad_enccommit(); } cnt=t-1; } template class EncCommit; template class EncCommit; template class EncCommitBase; template class EncCommitBase;