Files
MP-SPDZ/Fake-Offline.cpp
2016-09-02 19:16:51 +01:00

555 lines
15 KiB
C++

// (C) 2016 University of Bristol. See License.txt
#include "Math/gf2n.h"
#include "Math/gfp.h"
#include "Math/Share.h"
#include "Math/Setup.h"
#include "Auth/fake-stuff.h"
#include "Exceptions/Exceptions.h"
#include "Math/Setup.h"
#include "Processor/Data_Files.h"
#include "Tools/mkpath.h"
#include "Tools/ezOptionParser.h"
#include <sstream>
#include <fstream>
using namespace std;
string prep_data_prefix;
/* N = Number players
* ntrip = Number triples needed
* str = "2" or "p"
*/
template<class T>
void make_mult_triples(const T& key,int N,int ntrip,const string& str,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a,b,c;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
/* Generate Triples */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Triples-" << str << "-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
}
for (int i=0; i<ntrip; i++)
{
if (!zero)
a.randomize(G);
make_share(Sa,a,N,key,G);
if (!zero)
b.randomize(G);
make_share(Sb,b,N,key,G);
c.mul(a,b);
make_share(Sc,c,N,key,G);
for (int j=0; j<N; j++)
{ Sa[j].output(outf[j],false);
Sb[j].output(outf[j],false);
Sc[j].output(outf[j],false);
}
}
for (int i=0; i<N; i++)
{ outf[i].close(); }
delete[] outf;
}
void make_bit_triples(const gf2n& key,int N,int ntrip,Dtype dtype,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
gf2n a,b,c, one;
one.assign_one();
vector<Share<gf2n> > Sa(N),Sb(N),Sc(N);
/* Generate Triples */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << Data_Files::dtype_names[dtype] << "-2-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
}
for (int i=0; i<ntrip; i++)
{
if (!zero)
a.randomize(G);
a.AND(a, one);
make_share(Sa,a,N,key,G);
if (!zero)
b.randomize(G);
if (dtype == DATA_BITTRIPLE)
b.AND(b, one);
make_share(Sb,b,N,key,G);
c.mul(a,b);
make_share(Sc,c,N,key,G);
for (int j=0; j<N; j++)
{ Sa[j].output(outf[j],false);
Sb[j].output(outf[j],false);
Sc[j].output(outf[j],false);
}
}
for (int i=0; i<N; i++)
{ outf[i].close(); }
delete[] outf;
}
/* N = Number players
* ntrip = Number tuples needed
* str = "2" or "p"
*/
template<class T>
void make_square_tuples(const T& key,int N,int ntrip,const string& str,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a,c;
vector<Share<T> > Sa(N),Sc(N);
/* Generate Squares */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Squares-" << str << "-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
}
for (int i=0; i<ntrip; i++)
{
if (!zero)
a.randomize(G);
make_share(Sa,a,N,key,G);
c.mul(a,a);
make_share(Sc,c,N,key,G);
for (int j=0; j<N; j++)
{ Sa[j].output(outf[j],false);
Sc[j].output(outf[j],false);
}
}
for (int i=0; i<N; i++)
{ outf[i].close(); }
delete[] outf;
}
/* N = Number players
* ntrip = Number bits needed
* str = "2" or "p"
*/
template<class T>
void make_bits(const T& key,int N,int ntrip,const string& str,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a;
vector<Share<T> > Sa(N);
/* Generate Bits */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Bits-" << str << "-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
}
for (int i=0; i<ntrip; i++)
{ if ((G.get_uchar()&1)==0 || zero) { a.assign_zero(); }
else { a.assign_one(); }
make_share(Sa,a,N,key,G);
for (int j=0; j<N; j++)
{ Sa[j].output(outf[j],false); }
}
for (int i=0; i<N; i++)
{ outf[i].close(); }
delete[] outf;
}
/* N = Number players
* ntrip = Number inputs needed
* str = "2" or "p"
*
*/
template<class T>
void make_inputs(const T& key,int N,int ntrip,const string& str,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a;
vector<Share<T> > Sa(N);
/* Generate Inputs */
for (int player=0; player<N; player++)
{ for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Inputs-" << str << "-P" << i << "-" << player;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
}
for (int i=0; i<ntrip; i++)
{
if (!zero)
a.randomize(G);
make_share(Sa,a,N,key,G);
for (int j=0; j<N; j++)
{ Sa[j].output(outf[j],false);
if (j==player)
{ a.output(outf[j],false); }
}
}
for (int i=0; i<N; i++)
{ outf[i].close(); }
}
delete[] outf;
}
/* N = Number players
* ntrip = Number inverses needed
* str = "2" or "p"
*/
template<class T>
void make_inverse(const T& key,int N,int ntrip,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a,b;
vector<Share<T> > Sa(N),Sb(N);
/* Generate Triples */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Inverses-" << T::type_char() << "-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
}
for (int i=0; i<ntrip; i++)
{
if (zero)
// ironic?
a.assign_one();
else
do
a.randomize(G);
while (a.is_zero());
make_share(Sa,a,N,key,G);
b=a; b.invert();
make_share(Sb,b,N,key,G);
for (int j=0; j<N; j++)
{ Sa[j].output(outf[j],false);
Sb[j].output(outf[j],false);
}
}
for (int i=0; i<N; i++)
{ outf[i].close(); }
delete[] outf;
}
template<class T>
void make_PreMulC(const T& key, int N, int ntrip, bool zero)
{
stringstream ss;
ss << prep_data_prefix << "PreMulC-" << T::type_char();
Files<T> files(N, key, ss.str());
PRNG G;
G.ReSeed();
T a, b, c;
c = 1;
for (int i=0; i<ntrip; i++)
{
// close the circle
if (i == ntrip - 1 || zero)
a.assign_one();
else
do
a.randomize(G);
while (a.is_zero());
files.output_shares(a);
b = a;
b.invert();
files.output_shares(b);
files.output_shares(a * c);
c = b;
}
}
int main(int argc, const char** argv)
{
ez::ezOptionParser opt;
opt.syntax = "./Fake-Offline.x <nplayers> [OPTIONS]\n\nOptions with 2 arguments take the form '-X <#gf2n tuples>,<#modp tuples>'";
opt.example = "./Fake-Offline.x 2 -lgp 128 -lg2 128 --default 10000\n./Fake-Offline.x 3 -trip 50000,10000 -btrip 100000\n";
opt.add(
"128", // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Bit length of GF(p) field (default: 128)", // Help description.
"-lgp", // Flag token.
"--lgp" // Flag token.
);
opt.add(
"40", // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Bit length of GF(2^n) field (default: 40)", // Help description.
"-lg2", // Flag token.
"--lg2" // Flag token.
);
opt.add(
"1000", // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Default number of tuples to generate for ALL data types (default: 1000)", // Help description.
"-d", // Flag token.
"--default" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
2, // Number of args expected.
',', // Delimiter if expecting multiple args.
"Number of triples, for gf2n / modp types", // Help description.
"-trip", // Flag token.
"--ntriples" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
2, // Number of args expected.
',', // Delimiter if expecting multiple args.
"Number of random bits, for gf2n / modp types", // Help description.
"-bit", // Flag token.
"--nbits" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
2, // Number of args expected.
',', // Delimiter if expecting multiple args.
"Number of input tuples, for gf2n / modp types", // Help description.
"-inp", // Flag token.
"--ninputs" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
2, // Number of args expected.
',', // Delimiter if expecting multiple args.
"Number of square tuples, for gf2n / modp types", // Help description.
"-sq", // Flag token.
"--nsquares" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Number of inverse tuples (modp only)", // Help description.
"-inv", // Flag token.
"--ninverses" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Number of GF(2) triples", // Help description.
"-btrip", // Flag token.
"--nbittriples" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Number of GF(2) x GF(2^n) triples", // Help description.
"-mixed", // Flag token.
"--nbitgf2ntriples" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
0, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Set all values to zero, but not the shares", // Help description.
"-z", // Flag token.
"--zero" // Flag token.
);
opt.parse(argc, argv);
vector<string> badOptions;
string usage;
unsigned int i;
if(!opt.gotRequired(badOptions))
{
for (i=0; i < badOptions.size(); ++i)
cerr << "ERROR: Missing required option " << badOptions[i] << ".";
opt.getUsage(usage);
cout << usage;
return 1;
}
if(!opt.gotExpected(badOptions))
{
for(i=0; i < badOptions.size(); ++i)
cerr << "ERROR: Got unexpected number of arguments for option " << badOptions[i] << ".";
opt.getUsage(usage);
cout << usage;
return 1;
}
int nplayers;
if (opt.firstArgs.size() == 2)
{
nplayers = atoi(opt.firstArgs[1]->c_str());
}
else if (opt.lastArgs.size() == 1)
{
nplayers = atoi(opt.lastArgs[0]->c_str());
}
else
{
cerr << "ERROR: invalid number of arguments\n";
opt.getUsage(usage);
cout << usage;
return 1;
}
int default_num = 0;
int ntrip2=0, ntripp=0, nbits2=0,nbitsp=0,nsqr2=0,nsqrp=0,ninp2=0,ninpp=0,ninv=0, nbittrip=0, nbitgf2ntrip=0;
vector<int> list_options;
int lg2, lgp;
opt.get("--lgp")->getInt(lgp);
opt.get("--lg2")->getInt(lg2);
opt.get("--default")->getInt(default_num);
ntrip2 = ntripp = nbits2 = nbitsp = nsqr2 = nsqrp = ninp2 = ninpp = ninv =
nbittrip = nbitgf2ntrip = default_num;
if (opt.isSet("--ntriples"))
{
opt.get("--ntriples")->getInts(list_options);
ntrip2 = list_options[0];
ntripp = list_options[1];
}
if (opt.isSet("--nbits"))
{
opt.get("--nbits")->getInts(list_options);
nbits2 = list_options[0];
nbitsp = list_options[1];
}
if (opt.isSet("--ninputs"))
{
opt.get("--ninputs")->getInts(list_options);
ninp2 = list_options[0];
ninpp = list_options[1];
}
if (opt.isSet("--nsquares"))
{
opt.get("--nsquares")->getInts(list_options);
nsqr2 = list_options[0];
nsqrp = list_options[1];
}
if (opt.isSet("--ninverses"))
opt.get("--ninverses")->getInt(ninv);
if (opt.isSet("--nbittriples"))
opt.get("--nbittriples")->getInt(nbittrip);
if (opt.isSet("--nbitgf2ntriples"))
opt.get("--nbitgf2ntriples")->getInt(nbitgf2ntrip);
bool zero = opt.isSet("--zero");
if (zero)
cout << "Set all values to zero" << endl;
PRNG G;
G.ReSeed();
prep_data_prefix = get_prep_dir(nplayers, lgp, lg2);
// Set up the fields
ofstream outf;
bigint p;
generate_online_setup(outf, prep_data_prefix, p, lgp, lg2);
generate_keys(prep_data_prefix, nplayers);
/* Find number players and MAC keys etc*/
gfp keyp,pp; keyp.assign_zero();
gf2n key2,p2; key2.assign_zero();
int tmpN = 0;
ifstream inpf;
// create Player-Data if not there
if (mkdir_p("Player-Data") == -1)
{
cerr << "mkdir_p(Player-Data) failed\n";
throw file_error();
}
for (i = 0; i < (unsigned int)nplayers; i++)
{
stringstream filename;
filename << prep_data_prefix << "Player-MAC-Keys-P" << i;
inpf.open(filename.str().c_str());
if (inpf.fail())
{
inpf.close();
cout << "No MAC key share for player " << i << ", generating a fresh one\n";
pp.randomize(G);
p2.randomize(G);
ofstream outf(filename.str().c_str());
if (outf.fail())
throw file_error(filename.str().c_str());
outf << nplayers << " " << pp << " " << p2;
outf.close();
cout << "Written new MAC key share to " << filename.str() << endl;
}
else
{
inpf >> tmpN; // not needed here
pp.input(inpf,true);
p2.input(inpf,true);
inpf.close();
}
cout << " Key " << i << "\t p: " << pp << "\n\t 2: " << p2 << endl;
keyp.add(pp);
key2.add(p2);
}
cout << "--------------\n";
cout << "Final Keys :\t p: " << keyp << "\n\t\t 2: " << key2 << endl;
make_mult_triples(key2,nplayers,ntrip2,"2",zero);
make_mult_triples(keyp,nplayers,ntripp,"p",zero);
make_bits(key2,nplayers,nbits2,"2",zero);
make_bits(keyp,nplayers,nbitsp,"p",zero);
make_square_tuples(key2,nplayers,nsqr2,"2",zero);
make_square_tuples(keyp,nplayers,nsqrp,"p",zero);
make_inputs(key2,nplayers,ninp2,"2",zero);
make_inputs(keyp,nplayers,ninpp,"p",zero);
make_inverse(key2,nplayers,ninv,zero);
make_inverse(keyp,nplayers,ninv,zero);
make_bit_triples(key2,nplayers,nbittrip,DATA_BITTRIPLE,zero);
make_bit_triples(key2,nplayers,nbitgf2ntrip,DATA_BITGF2NTRIPLE,zero);
make_PreMulC(key2,nplayers,ninv,zero);
make_PreMulC(keyp,nplayers,ninv,zero);
}