diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a0406a8e..744d0ff1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ The changelog explains changes pulled through from the private development repository. Bug fixes and small enhancements are committed between releases and not documented here. +## 0.3.1 (Apr 19, 2022) + +- Protocol in dealer model +- Command-line option for security parameter +- Fixed security bug in SPDZ2k (see Section 3.4 of [the updated paper](https://eprint.iacr.org/2018/482)) +- Ability to run high-level (Python) code from C++ +- More memory capacity due to 64-bit addressing +- Homomorphic encryption for more fields of characteristic two +- Docker container + ## 0.3.0 (Feb 17, 2022) - Semi-honest computation based on threshold semi-homomorphic encryption diff --git a/Compiler/GC/instructions.py b/Compiler/GC/instructions.py index ef9c14a3f..e53b71879 100644 --- a/Compiler/GC/instructions.py +++ b/Compiler/GC/instructions.py @@ -305,7 +305,7 @@ class ldmsb(base.DirectMemoryInstruction, base.ReadMemoryInstruction, :param: memory address (int) """ code = opcodes['LDMSB'] - arg_format = ['sbw','int'] + arg_format = ['sbw','long'] class stmsb(base.DirectMemoryWriteInstruction, base.VectorInstruction): """ Copy secret bit register to secret bit memory cell with compile-time @@ -315,7 +315,7 @@ class stmsb(base.DirectMemoryWriteInstruction, base.VectorInstruction): :param: memory address (int) """ code = opcodes['STMSB'] - arg_format = ['sb','int'] + arg_format = ['sb','long'] # def __init__(self, *args, **kwargs): # super(type(self), self).__init__(*args, **kwargs) # import inspect @@ -330,7 +330,7 @@ class ldmcb(base.DirectMemoryInstruction, base.ReadMemoryInstruction, :param: memory address (int) """ code = opcodes['LDMCB'] - arg_format = ['cbw','int'] + arg_format = ['cbw','long'] class stmcb(base.DirectMemoryWriteInstruction, base.VectorInstruction): """ Copy clear bit register to clear bit memory cell with compile-time @@ -340,7 +340,7 @@ class stmcb(base.DirectMemoryWriteInstruction, base.VectorInstruction): :param: memory address (int) """ code = opcodes['STMCB'] - arg_format = ['cb','int'] + arg_format = ['cb','long'] class ldmsbi(base.ReadMemoryInstruction, base.VectorInstruction): """ Copy secret bit memory cell with run-time address to secret bit diff --git a/Compiler/GC/types.py b/Compiler/GC/types.py index 38c37a261..6c3abad0a 100644 --- a/Compiler/GC/types.py +++ b/Compiler/GC/types.py @@ -3,6 +3,9 @@ fixed-length types obtained by :py:obj:`get_type(n)` are the preferred way of using them, and in some cases required in connection with container types. + +Computation using these types will always be executed as a binary +circuit. See :ref:`protocol-pairs` for the exact protocols. """ from Compiler.types import MemValue, read_mem_value, regint, Array, cint @@ -17,7 +20,6 @@ from functools import reduce class bits(Tape.Register, _structure, _bit): - """ Base class for binary registers. """ n = 40 unit = 64 PreOp = staticmethod(floatingpoint.PreOpN) @@ -400,12 +402,18 @@ def get_random_bit(): res = sbit() inst.bitb(res) return res + @staticmethod + def _check_input_player(player): + if not util.is_constant(player): + raise CompilerError('player must be known at compile time ' + 'for binary circuit inputs') @classmethod def get_input_from(cls, player, n_bits=None): """ Secret input from :py:obj:`player`. :param: player (int) """ + cls._check_input_player(player) if n_bits is None: n_bits = cls.n res = cls() @@ -653,6 +661,7 @@ def get_input_from(cls, player): :param: player (int) """ + sbits._check_input_player(player) res = cls.from_vec(sbit() for i in range(n)) inst.inputbvec(n + 3, 0, player, *res.v) return res @@ -780,6 +789,8 @@ def coerce(self, other): size = other.size return (other.get_vector(base, min(64, size - base)) \ for base in range(0, size, 64)) + if not isinstance(other, type(self)): + return type(self)(other) return other def __xor__(self, other): other = self.coerce(other) @@ -1222,6 +1233,7 @@ def get_input_from(cls, player): :param: player (int) """ + sbits._check_input_player(player) v = cls.int_type() inst.inputb(player, cls.k, cls.f, v) return cls._new(v) @@ -1287,6 +1299,7 @@ def get_input_from(cls, player): :param: player (int) """ v = [sbit() for i in range(sbitfix.k)] + sbits._check_input_player(player) inst.inputbvec(len(v) + 3, sbitfix.f, player, *v) return cls._new(cls.int_type.from_vec(v)) def __init__(self, value=None, *args, **kwargs): diff --git a/Compiler/allocator.py b/Compiler/allocator.py index cf2f13ef4..bf431ca38 100644 --- a/Compiler/allocator.py +++ b/Compiler/allocator.py @@ -15,11 +15,11 @@ class BlockAllocator: """ Manages freed memory blocks. """ def __init__(self): - self.by_logsize = [defaultdict(set) for i in range(32)] + self.by_logsize = [defaultdict(set) for i in range(64)] self.by_address = {} def by_size(self, size): - if size >= 2 ** 32: + if size >= 2 ** 64: raise CompilerError('size exceeds addressing capability') return self.by_logsize[int(math.log(size, 2))][size] diff --git a/Compiler/instructions.py b/Compiler/instructions.py index e06797684..8a10ee58c 100644 --- a/Compiler/instructions.py +++ b/Compiler/instructions.py @@ -69,7 +69,7 @@ class ldmc(base.DirectMemoryInstruction, base.ReadMemoryInstruction): """ __slots__ = [] code = base.opcodes['LDMC'] - arg_format = ['cw','int'] + arg_format = ['cw','long'] @base.gf2n @base.vectorize @@ -84,7 +84,7 @@ class ldms(base.DirectMemoryInstruction, base.ReadMemoryInstruction): """ __slots__ = [] code = base.opcodes['LDMS'] - arg_format = ['sw','int'] + arg_format = ['sw','long'] @base.gf2n @base.vectorize @@ -99,7 +99,7 @@ class stmc(base.DirectMemoryWriteInstruction): """ __slots__ = [] code = base.opcodes['STMC'] - arg_format = ['c','int'] + arg_format = ['c','long'] @base.gf2n @base.vectorize @@ -114,7 +114,7 @@ class stms(base.DirectMemoryWriteInstruction): """ __slots__ = [] code = base.opcodes['STMS'] - arg_format = ['s','int'] + arg_format = ['s','long'] @base.vectorize class ldmint(base.DirectMemoryInstruction, base.ReadMemoryInstruction): @@ -128,7 +128,7 @@ class ldmint(base.DirectMemoryInstruction, base.ReadMemoryInstruction): """ __slots__ = [] code = base.opcodes['LDMINT'] - arg_format = ['ciw','int'] + arg_format = ['ciw','long'] @base.vectorize class stmint(base.DirectMemoryWriteInstruction): @@ -142,7 +142,7 @@ class stmint(base.DirectMemoryWriteInstruction): """ __slots__ = [] code = base.opcodes['STMINT'] - arg_format = ['ci','int'] + arg_format = ['ci','long'] @base.vectorize class ldmci(base.ReadMemoryInstruction, base.IndirectMemoryInstruction): diff --git a/Compiler/instructions_base.py b/Compiler/instructions_base.py index d6c647add..8ae0b86fc 100644 --- a/Compiler/instructions_base.py +++ b/Compiler/instructions_base.py @@ -337,7 +337,7 @@ def reformat(arg_format): if isinstance(arg_format, list): __format = [] for __f in arg_format: - if __f in ('int', 'p', 'ci', 'str'): + if __f in ('int', 'long', 'p', 'ci', 'str'): __format.append(__f) else: __format.append(__f[0] + 'g' + __f[1:]) @@ -360,7 +360,7 @@ class GF2N_Instruction(instruction_cls): arg_format = instruction_cls.gf2n_arg_format elif isinstance(instruction_cls.arg_format, itertools.repeat): __f = next(instruction_cls.arg_format) - if __f != 'int' and __f != 'p': + if __f not in ('int', 'long', 'p'): arg_format = itertools.repeat(__f[0] + 'g' + __f[1:]) else: arg_format = copy.deepcopy(instruction_cls.arg_format) @@ -711,6 +711,14 @@ def __init__(self, f): def __str__(self): return str(self.i) +class LongArgFormat(IntArgFormat): + @classmethod + def encode(cls, arg): + return struct.pack('>Q', arg) + + def __init__(self, f): + self.i = struct.unpack('>Q', f.read(8))[0] + class ImmediateModpAF(IntArgFormat): @classmethod def check(cls, arg): @@ -768,6 +776,7 @@ def __str__(self): 'i': ImmediateModpAF, 'ig': ImmediateGF2NAF, 'int': IntArgFormat, + 'long': LongArgFormat, 'p': PlayerNoAF, 'str': String, } diff --git a/Compiler/library.py b/Compiler/library.py index 35d6f46f2..ef2fe1ab6 100644 --- a/Compiler/library.py +++ b/Compiler/library.py @@ -1149,6 +1149,7 @@ def multithread(n_threads, n_items=None, max_size=None): :param n_threads: compile-time (int) :param n_items: regint/cint/int (default: :py:obj:`n_threads`) + :param max_size: maximum size to be processed at once (default: no limit) The following executes ``f(0, 8)``, ``f(8, 8)``, and ``f(16, 9)`` in three different threads: @@ -1366,6 +1367,18 @@ def _(base, size): left = (left + 1) // 2 return inputs[0] +def tree_reduce(function, sequence): + """ Round-efficient reduction. The following computes the maximum + of the list :py:obj:`l`:: + + m = tree_reduce(lambda x, y: x.max(y), l) + + :param function: reduction function taking two arguments + :param sequence: list, vector, or array + + """ + return util.tree_reduce(function, sequence) + def foreach_enumerate(a): """ Run-time loop over public data. This uses ``Player-Data/Public-Input/``. Example: diff --git a/Compiler/ml.py b/Compiler/ml.py index c521934fe..02f0f04ed 100644 --- a/Compiler/ml.py +++ b/Compiler/ml.py @@ -1079,14 +1079,17 @@ def __repr__(self): (type(self).__name__, self.X.sizes, self.strides, self.ksize, self.padding) - def _forward(self, batch): + def forward(self, batch=None, training=False): + if batch is None: + batch = Array.create_from(regint(0)) def process(pool, bi, k, i, j): def m(a, b): c = a[0] > b[0] l = [c * x for x in a[1]] l += [(1 - c) * x for x in b[1]] return c.if_else(a[0], b[0]), l - red = util.tree_reduce(m, [(x[0], [1]) for x in pool]) + red = util.tree_reduce(m, [(x[0], [1] if training else []) + for x in pool]) self.Y[bi][i][j][k] = red[0] for i, x in enumerate(red[1]): self.comparisons[bi][k][i] = x diff --git a/Compiler/program.py b/Compiler/program.py index 366723304..78b802e14 100644 --- a/Compiler/program.py +++ b/Compiler/program.py @@ -400,6 +400,9 @@ def malloc(self, size, mem_type, reg_type=None, creator_tape=None): self.allocated_mem[mem_type] += size if len(str(addr)) != len(str(addr + size)) and self.verbose: print("Memory of type '%s' now of size %d" % (mem_type, addr + size)) + if addr + size >= 2 ** 32: + raise CompilerError("allocation exceeded for type '%s'" % + mem_type) self.allocated_mem_blocks[addr,mem_type] = size if single_size: from .library import get_thread_number, runtime_error_if diff --git a/Compiler/types.py b/Compiler/types.py index b63597338..99ca6a8c6 100644 --- a/Compiler/types.py +++ b/Compiler/types.py @@ -1710,7 +1710,12 @@ def reveal_to(self, player): res = Array.create_from(res) return personal(player, res) - def bit_decompose(self, length): + def bit_decompose(self, length=None): + """ Bit decomposition. + + :param length: number of bits + + """ return [personal(self.player, x) for x in self._v.bit_decompose(length)] def _san(self, other): @@ -2144,7 +2149,7 @@ class sint(_secret, _int): the bit length. :param val: initialization (sint/cint/regint/int/cgf2n or list - thereof or sbits/sbitvec/sfix) + thereof, sbits/sbitvec/sfix, or :py:class:`personal`) :param size: vector size (int), defaults to 1 or size of list When converting :py:class:`~Compiler.GC.types.sbits`, the result is a @@ -2152,6 +2157,9 @@ class sint(_secret, _int): :py:class:`~Compiler.GC.types.sbitvec`, the result is a vector of values with bit length equal the length of the input. + Initializing from a :py:class:`personal` value implies the + relevant party inputting their value securely. + """ __slots__ = [] instruction_type = 'modp' @@ -4285,6 +4293,7 @@ class sfix(_fix): """ Secret fixed-point number represented as secret integer, by multiplying with ``2^f`` and then rounding. See :py:class:`sint` for security considerations of the underlying integer operations. + The secret integer is stored as the :py:obj:`v` member. It supports basic arithmetic (``+, -, *, /``), returning :py:class:`sfix`, and comparisons (``==, !=, <, <=, >, >=``), @@ -5121,7 +5130,8 @@ class Array(_vectorizable): array ``a`` and ``i`` being a :py:class:`regint`, :py:class:`cint`, or a Python integer. - :param length: compile-time integer (int) or :py:obj:`None` for unknown length + :param length: compile-time integer (int) or :py:obj:`None` + for unknown length (need to specify :py:obj:`address`) :param value_type: basic type :param address: if given (regint/int), the array will not be allocated @@ -5178,6 +5188,8 @@ def delete(self): self.address = None def get_address(self, index): + if isinstance(index, (_secret, _single)): + raise CompilerError('need cleartext index') key = str(index) if self.length is not None: from .GC.types import cbits @@ -5211,6 +5223,7 @@ def get_slice(self, index): if index.step == 0: raise CompilerError('slice step cannot be zero') return index.start or 0, \ + index.stop if self.length is None else \ min(index.stop or self.length, self.length), index.step or 1 def __getitem__(self, index): @@ -5517,7 +5530,15 @@ def print_reveal_nested(self, end='\n'): :param end: string to print after (default: line break) """ - library.print_str('%s' + end, self.get_vector().reveal()) + if util.is_constant(self.length): + library.print_str('%s' + end, self.get_vector().reveal()) + else: + library.print_str('[') + @library.for_range(self.length - 1) + def _(i): + library.print_str('%s, ', self[i].reveal()) + library.print_str('%s', self[self.length - 1].reveal()) + library.print_str(']' + end) def reveal_to_binary_output(self, player=None): """ Reveal to binary output if supported by type. @@ -5893,7 +5914,8 @@ def dot(self, other, res_params=None, n_threads=None): """ Matrix-matrix and matrix-vector multiplication. :param self: two-dimensional - :param other: Matrix or Array of matching size and type """ + :param other: Matrix or Array of matching size and type + :param n_threads: number of threads (default: all in same thread) """ assert len(self.sizes) == 2 if isinstance(other, Array): assert len(other) == self.sizes[1] @@ -5928,6 +5950,7 @@ def _(base, size): res_matrix.assign_part_vector( self.get_part(base, size).direct_mul(other), base) except AttributeError: + assert n_threads is None if max(res_matrix.sizes) > 1000: raise AttributeError() A = self.get_vector() @@ -5937,7 +5960,7 @@ def _(base, size): res_params)) except (AttributeError, AssertionError): # fallback for sfloat etc. - @library.for_range_opt(self.sizes[0]) + @library.for_range_opt_multithread(n_threads, self.sizes[0]) def _(i): try: res_matrix[i] = self.value_type.row_matrix_mul( diff --git a/ECDSA/P256Element.h b/ECDSA/P256Element.h index e426bade9..4657b5d88 100644 --- a/ECDSA/P256Element.h +++ b/ECDSA/P256Element.h @@ -28,6 +28,7 @@ class P256Element : public ValueInterface static const true_type invertible; static int size() { return 0; } + static int length() { return 256; } static string type_string() { return "P256"; } static void init(); diff --git a/ECDSA/semi-ecdsa-party.cpp b/ECDSA/semi-ecdsa-party.cpp index 6bdcec286..d7a4d8836 100644 --- a/ECDSA/semi-ecdsa-party.cpp +++ b/ECDSA/semi-ecdsa-party.cpp @@ -10,6 +10,7 @@ #include "Protocols/SemiPrep.hpp" #include "Protocols/SemiInput.hpp" #include "Protocols/MAC_Check_Base.hpp" +#include "GC/SemiSecret.hpp" #include "ot-ecdsa-party.hpp" #include diff --git a/ExternalIO/Client.h b/ExternalIO/Client.h index 5f8e76fd3..de9e9cad4 100644 --- a/ExternalIO/Client.h +++ b/ExternalIO/Client.h @@ -49,8 +49,8 @@ class Client * @param n number of values * @returns vector of integer-like values */ - template - vector receive_outputs(int n); + template + vector receive_outputs(int n); }; #endif /* EXTERNALIO_CLIENT_H_ */ diff --git a/ExternalIO/Client.hpp b/ExternalIO/Client.hpp index 601d9a486..3af40f2f4 100644 --- a/ExternalIO/Client.hpp +++ b/ExternalIO/Client.hpp @@ -91,8 +91,8 @@ void Client::send_private_inputs(const vector& values) // Receive shares of the result and sum together. // Also receive authenticating values. -template -vector Client::receive_outputs(int n) +template +vector Client::receive_outputs(int n) { vector triples(3 * n); octetStream os; @@ -111,7 +111,7 @@ vector Client::receive_outputs(int n) } } - vector output_values; + vector output_values; for (int i = 0; i < 3 * n; i += 3) { if (T(triples[i] * triples[i + 1]) != triples[i + 2]) diff --git a/ExternalIO/bankers-bonus-client.cpp b/ExternalIO/bankers-bonus-client.cpp index f68384c00..b040dd5e8 100644 --- a/ExternalIO/bankers-bonus-client.cpp +++ b/ExternalIO/bankers-bonus-client.cpp @@ -46,7 +46,7 @@ #include #include -template +template void one_run(T salary_value, Client& client) { // Run the computation @@ -54,18 +54,18 @@ void one_run(T salary_value, Client& client) cout << "Sent private inputs to each SPDZ engine, waiting for result..." << endl; // Get the result back (client_id of winning client) - T result = client.receive_outputs(1)[0]; + U result = client.receive_outputs(1)[0]; cout << "Winning client id is : " << result << endl; } -template +template void run(double salary_value, Client& client) { // sint - one_run(long(round(salary_value)), client); + one_run(long(round(salary_value)), client); // sfix with f = 16 - one_run(long(round(salary_value * exp2(16))), client); + one_run(long(round(salary_value * exp2(16))), client); } int main(int argc, char** argv) @@ -125,7 +125,7 @@ int main(int argc, char** argv) { gfp::init_field(specification.get()); cerr << "using prime " << gfp::pr() << endl; - run(salary_value, client); + run(salary_value, client); break; } case 'R': @@ -134,13 +134,13 @@ int main(int argc, char** argv) switch (R) { case 64: - run>(salary_value, client); + run, Z2<64>>(salary_value, client); break; case 104: - run>(salary_value, client); + run, Z2<64>>(salary_value, client); break; case 128: - run>(salary_value, client); + run, Z2<64>>(salary_value, client); break; default: cerr << R << "-bit ring not implemented"; diff --git a/FHE/FHE_Params.cpp b/FHE/FHE_Params.cpp index 0de8bb1e9..5fb07f233 100644 --- a/FHE/FHE_Params.cpp +++ b/FHE/FHE_Params.cpp @@ -2,9 +2,11 @@ #include "FHE_Params.h" #include "FHE/Ring_Element.h" #include "Tools/Exceptions.h" +#include "Protocols/HemiOptions.h" +#include "Processor/OnlineOptions.h" -FHE_Params::FHE_Params(int n_mults) : - FFTData(n_mults + 1), Chi(0.7), sec_p(-1), matrix_dim(1) +FHE_Params::FHE_Params(int n_mults, int drown_sec) : + FFTData(n_mults + 1), Chi(0.7), sec_p(drown_sec), matrix_dim(1) { } @@ -17,16 +19,20 @@ void FHE_Params::set(const Ring& R, for (size_t i = 0; i < FFTData.size(); i++) FFTData[i].init(R,primes[i]); - set_sec(40); + set_sec(sec_p); } void FHE_Params::set_sec(int sec) { + assert(sec >= 0); sec_p=sec; Bval=1; Bval=Bval<matrix_dim = matrix_dim; } +void FHE_Params::set_matrix_dim_from_options() +{ + set_matrix_dim( + HemiOptions::singleton.plain_matmul ? + 1 : OnlineOptions::singleton.batch_size); +} + bigint FHE_Params::Q() const { bigint res = FFTData[0].get_prime(); diff --git a/FHE/FHE_Params.h b/FHE/FHE_Params.h index 9407b0ba4..8821e2e29 100644 --- a/FHE/FHE_Params.h +++ b/FHE/FHE_Params.h @@ -13,6 +13,7 @@ #include "FHE/FFT_Data.h" #include "FHE/DiscreteGauss.h" #include "Tools/random.h" +#include "Protocols/config.h" class FHE_Params { @@ -30,15 +31,17 @@ class FHE_Params public: - FHE_Params(int n_mults = 1); + FHE_Params(int n_mults = 1, int drown_sec = DEFAULT_SECURITY); int n_mults() const { return FFTData.size() - 1; } void set(const Ring& R,const vector& primes); void set(const vector& primes); void set_sec(int sec); + void set_min_sec(int sec); void set_matrix_dim(int matrix_dim); + void set_matrix_dim_from_options(); int get_matrix_dim() const { return matrix_dim; } const vector& FFTD() const { return FFTData; } diff --git a/FHE/Matrix.cpp b/FHE/Matrix.cpp index c9c23aaba..dcec137e4 100644 --- a/FHE/Matrix.cpp +++ b/FHE/Matrix.cpp @@ -68,6 +68,10 @@ void HNF(matrix& H,matrix& U,const matrix& A) { int m=A.size(),n=A[0].size(),r,i,j,k; +#ifdef VERBOSE + cerr << "HNF m=" << m << ", n=" << n << endl; +#endif + H=A; ident(U,n); r=min(m,n); @@ -79,9 +83,9 @@ void HNF(matrix& H,matrix& U,const matrix& A) { if (step==2) { // Step 2 k=-1; - mn=bigint(1)<<256; + mn=bigint(0); for (j=i; j 0) @@ -428,6 +429,16 @@ GF2X Subs_PowX_Mod(const GF2X& a,int pow,int m,const GF2X& c) +GF2X get_F(const Ring& Rg) +{ + GF2X F; + for (int i=0; i<=Rg.phi_m(); i++) + { if (((Rg.Phi()[i])%2)!=0) + { SetCoeff(F,i,1); } + } + //cout << "F = " << F << endl; + return F; +} void init(P2Data& P2D,const Ring& Rg) { @@ -438,16 +449,12 @@ void init(P2Data& P2D,const Ring& Rg) { SetCoeff(G,gf2n_short::get_t(i),1); } //cout << "G = " << G << endl; - for (int i=0; i<=Rg.phi_m(); i++) - { if (((Rg.Phi()[i])%2)!=0) - { SetCoeff(F,i,1); } - } - //cout << "F = " << F << endl; + F = get_F(Rg); // seed randomness to achieve same result for all players // randomness is used in SFCanZass and FindRoot SetSeed(ZZ(0)); - + // Now factor F modulo 2 vec_GF2X facts=SFCanZass(F); @@ -459,17 +466,34 @@ void init(P2Data& P2D,const Ring& Rg) // Compute the quotient group QGroup QGrp; int Gord=-1,e=Rg.phi_m()/d; // e = # of plaintext slots, phi(m)/degree - int seed=1; - while (Gord!=e) + + if ((e*gf2n_short::degree())!=Rg.phi_m()) + { cout << "Plaintext type requires Gord*gf2n_short::degree == phi_m" << endl; + cout << e << " * " << gf2n_short::degree() << " != " << Rg.phi_m() << endl; + throw invalid_params(); + } + + int max_tries = 10; + for (int seed = 0;; seed++) { QGrp.assign(Rg.m(),seed); // QGrp encodes the the quotient group Z_m^*/<2> - Gord=QGrp.order(); - if (Gord!=e) { cout << "Group order wrong, need to repeat the Haf-Mc algorithm" << endl; seed++; } + Gord = QGrp.order(); + if (Gord == e) + { + break; + } + else + { + if (seed == max_tries) + { + cerr << "abort after " << max_tries << " tries" << endl; + throw invalid_params(); + } + else + cout << "Group order wrong, need to repeat the Haf-Mc algorithm" + << endl; + } } //cout << " l = " << Gord << " , d = " << d << endl; - if ((Gord*gf2n_short::degree())!=Rg.phi_m()) - { cout << "Plaintext type requires Gord*gf2n_short::degree == phi_m" << endl; - throw not_implemented(); - } vector Fi(Gord); vector Rts(Gord); @@ -590,8 +614,23 @@ void char_2_dimension(int& m, int& lg2) m=5797; lg2=40; break; + case 64: + m = 9615; + break; + case 63: + m = 9271; + break; + case 28: + m = 3277; + break; case 16: - m = 13107; + m = 4369; + break; + case 12: + m = 4095; + break; + case 11: + m = 2047; break; default: throw runtime_error("field size not supported"); @@ -628,7 +667,7 @@ void Parameters::SPDZ_Data_Setup(FHE_Params& params, P2Data& P2D) finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[0], round_up, params); } - if (NoiseBounds::min_phi_m(lg2p0 + lg2p1, params) > phi_N(m)) + if (NoiseBounds::min_phi_m(lg2p0 + lg2p1, params) * 2 > m) throw runtime_error("number of slots too small"); cout << "m = " << m << endl; diff --git a/FHE/NTL-Subs.h b/FHE/NTL-Subs.h index acaba70b6..7d7d13de6 100644 --- a/FHE/NTL-Subs.h +++ b/FHE/NTL-Subs.h @@ -55,12 +55,19 @@ int generate_semi_setup(int plaintext_length, int sec, FHE_Params& params, FD& FieldD, bool round_up, int n = 1); // field-independent semi-homomorphic setup -int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, +int common_semi_setup(FHE_Params& params, int m, bigint p, int& lgp0, int lgp1, bool round_up); void init(Ring& Rg, int m, bool generate_poly); void init(P2Data& P2D,const Ring& Rg); +namespace NTL +{ +class GF2X; +} + +NTL::GF2X get_F(const Ring& Rg); + // For use when we want p to be a specific value void SPDZ_Data_Setup_Char_p_General(Ring& R, PPData& PPD, bigint& pr0, bigint& pr1, int n, int sec, bigint& p, FHE_Params& params); diff --git a/FHE/NoiseBounds.cpp b/FHE/NoiseBounds.cpp index f2e151c42..a1fe3e033 100644 --- a/FHE/NoiseBounds.cpp +++ b/FHE/NoiseBounds.cpp @@ -36,11 +36,12 @@ SemiHomomorphicNoiseBounds::SemiHomomorphicNoiseBounds(const bigint& p, * (20.5 + c1 * sigma * sqrt(phi_m) + 20 * c1 * V_s); // unify parameters by taking maximum over TopGear or not bigint B_clean_top_gear = B_clean * 2; - bigint B_clean_not_top_gear = B_clean << int(ceil(sec / 2.)); + bigint B_clean_not_top_gear = B_clean << max(slack - sec, 0); B_clean = max(B_clean_not_top_gear, B_clean_top_gear); B_scale = (c1 + c2 * V_s) * p * sqrt(phi_m / 12.0); int matrix_dim = params.get_matrix_dim(); #ifdef NOISY + cout << "phi(m): " << phi_m << endl; cout << "p * sqrt(phi(m) / 12): " << p * sqrt(phi_m / 12.0) << endl; cout << "V_s: " << V_s << endl; cout << "c1: " << c1 << endl; @@ -50,10 +51,13 @@ SemiHomomorphicNoiseBounds::SemiHomomorphicNoiseBounds(const bigint& p, cout << "B_clean: " << B_clean << endl; cout << "B_scale: " << B_scale << endl; cout << "matrix dimension: " << matrix_dim << endl; + cout << "drown sec: " << params.secp() << endl; + cout << "sec: " << sec << endl; #endif assert(matrix_dim > 0); - drown = 1 + matrix_dim * n * (bigint(1) << sec); + assert(params.secp() >= 0); + drown = 1 + (p > 2 ? matrix_dim : 1) * n * (bigint(1) << params.secp()); } bigint SemiHomomorphicNoiseBounds::min_p0(const bigint& p1) @@ -71,8 +75,14 @@ double SemiHomomorphicNoiseBounds::min_phi_m(int log_q, double sigma) { if (sigma <= 0) sigma = FHE_Params().get_R(); - // the constant was updated using Martin Albrecht's LWE estimator in Sep 2019 - return 37.8 * (log_q - log2(sigma)); + // the constant was updated using Martin Albrecht's LWE estimator in Mar 2022 + // found the following pairs for 128-bit security + // and alpha = 0.7 * sqrt(2*pi) / q + // m = 2048, log_2(q) = 68 + // m = 4096, log_2(q) = 138 + // m = 8192, log_2(q) = 302 + // m = 16384, log_2(q) = 560 + return 15.1 * log_q; } double SemiHomomorphicNoiseBounds::min_phi_m(int log_q, const FHE_Params& params) diff --git a/FHE/Subroutines.cpp b/FHE/Subroutines.cpp index 8ec6a7cee..a688b1691 100644 --- a/FHE/Subroutines.cpp +++ b/FHE/Subroutines.cpp @@ -11,35 +11,15 @@ void Subs(modp& ans,const vector& poly,const modp& x,const Zp_Data& ZpD) assignZero(ans,ZpD); for (int i=poly.size()-1; i>=0; i--) { Mul(ans,ans,x,ZpD); - switch (poly[i]) - { case 0: - break; - case 1: - Add(ans,ans,one,ZpD); - break; - case -1: - Sub(ans,ans,one,ZpD); - break; - case 2: - Add(ans,ans,one,ZpD); - Add(ans,ans,one,ZpD); - break; - case -2: - Sub(ans,ans,one,ZpD); - Sub(ans,ans,one,ZpD); - break; - case 3: - Add(ans,ans,one,ZpD); - Add(ans,ans,one,ZpD); - Add(ans,ans,one,ZpD); - break; - case -3: - Sub(ans,ans,one,ZpD); - Sub(ans,ans,one,ZpD); - Sub(ans,ans,one,ZpD); - break; - default: - throw not_implemented(); + if (poly[i] > 0) + { + for (int j = 0; j < poly[i]; j++) + Add(ans, ans, one, ZpD); + } + if (poly[i] < 0) + { + for (int j = 0; j < -poly[i]; j++) + Sub(ans, ans, one, ZpD); } } } diff --git a/FHEOffline/DataSetup.cpp b/FHEOffline/DataSetup.cpp index 48a8a6ef8..0dc8d9675 100644 --- a/FHEOffline/DataSetup.cpp +++ b/FHEOffline/DataSetup.cpp @@ -40,10 +40,9 @@ template void PartSetup::generate_setup(int n_parties, int plaintext_length, int sec, int slack, bool round_up) { - sec = max(sec, 40); + params.set_min_sec(sec); Parameters(n_parties, plaintext_length, sec, slack, round_up).generate_setup( params, FieldD); - params.set_sec(sec); pk = FHE_PK(params, FieldD.get_prime()); sk = FHE_SK(params, FieldD.get_prime()); calpha = Ciphertext(params); @@ -180,11 +179,8 @@ void PartSetup::init_field() } template -void PartSetup::check(int sec) const +void PartSetup::check() const { - sec = max(sec, 40); - if (abs(sec - params.secp()) > 2) - throw runtime_error("security parameters vary too much between protocol and distributed decryption"); sk.check(params, pk, FieldD.get_prime()); } diff --git a/FHEOffline/DataSetup.h b/FHEOffline/DataSetup.h index 88c9e05fc..1c606506d 100644 --- a/FHEOffline/DataSetup.h +++ b/FHEOffline/DataSetup.h @@ -57,7 +57,7 @@ class PartSetup void init_field(); - void check(int sec) const; + void check() const; bool operator!=(const PartSetup& other); void secure_init(Player& P, MachineBase& machine, int plaintext_length, diff --git a/FHEOffline/Multiplier.cpp b/FHEOffline/Multiplier.cpp index 92632002c..43ad7e842 100644 --- a/FHEOffline/Multiplier.cpp +++ b/FHEOffline/Multiplier.cpp @@ -69,7 +69,7 @@ void Multiplier::add(Plaintext_& res, const Ciphertext& c, product_share.randomize(G); bigint B = 6 * machine.setup().params.get_R(); B *= machine.setup().FieldD.get_prime(); - B <<= machine.drown_sec; + B <<= machine.setup().params.secp(); // slack B *= NonInteractiveProof::slack(machine.sec, machine.setup().params.phi_m()); diff --git a/FHEOffline/PairwiseMachine.cpp b/FHEOffline/PairwiseMachine.cpp index e41fe1837..b19dd62cf 100644 --- a/FHEOffline/PairwiseMachine.cpp +++ b/FHEOffline/PairwiseMachine.cpp @@ -29,7 +29,7 @@ void PairwiseMachine::init() { if (use_gf2n) { - field_size = 40; + field_size = gf2n_short::DEFAULT_LENGTH; gf2n_short::init_field(field_size); setup_keys(); } @@ -67,7 +67,7 @@ void PairwiseMachine::setup_keys() { auto& N = P; PairwiseSetup& s = setup(); - s.init(P, drown_sec, field_size, extra_slack); + s.init(P, sec, field_size, extra_slack); if (output) write_mac_key(get_prep_dir(P), P.my_num(), P.num_players(), s.alphai); for (auto& x : other_pks) diff --git a/FHEOffline/PairwiseSetup.cpp b/FHEOffline/PairwiseSetup.cpp index 047c84f2c..59223ad03 100644 --- a/FHEOffline/PairwiseSetup.cpp +++ b/FHEOffline/PairwiseSetup.cpp @@ -65,11 +65,12 @@ template void secure_init(T& setup, Player& P, U& machine, int plaintext_length, int sec, FHE_Params& params) { + assert(sec >= 0); machine.sec = sec; - sec = max(sec, 40); - machine.drown_sec = sec; + params.set_min_sec(sec); string filename = PREP_DIR + T::name() + "-" + to_string(plaintext_length) + "-" + to_string(sec) + "-" + + to_string(params.secp()) + "-" + to_string(params.get_matrix_dim()) + "-" + OnlineOptions::singleton.prime.get_str() + "-" + to_string(CowGearOptions::singleton.top_gear()) + "-P" diff --git a/FHEOffline/Proof.h b/FHEOffline/Proof.h index 5e690b67c..6059ef3bc 100644 --- a/FHEOffline/Proof.h +++ b/FHEOffline/Proof.h @@ -78,6 +78,7 @@ class Proof diagonal(diagonal), B_plain_length(0), B_rand_length(0), pk(&pk), n_proofs(n_proofs) { sec=sc; + assert(sec > 0); tau=Tau; rho=Rho; phim=(pk.get_params()).phi_m(); diff --git a/FHEOffline/Sacrificing.cpp b/FHEOffline/Sacrificing.cpp index dab3e507a..63d559d53 100644 --- a/FHEOffline/Sacrificing.cpp +++ b/FHEOffline/Sacrificing.cpp @@ -10,6 +10,8 @@ #include "Tools/Subroutines.h" +#include "Protocols/mac_key.hpp" + // The number of sacrifices to amortize at one time #define amortize 512 @@ -19,12 +21,7 @@ void Triple_Checking(const Player& P, MAC_Check& MC, int nm, int output_thread, TripleSacriFactory< Share >& factory, bool write_output, bool clear, string dir) { - if (T::length() < 40) - { - cerr << "Field too small for reasonable security" << endl; - cerr << "Use a larger field or remove this warning from " << __FILE__ << endl; - exit(1); - } + check_field_size(); ofstream outf; if (write_output) diff --git a/FHEOffline/SimpleMachine.cpp b/FHEOffline/SimpleMachine.cpp index 04d190f1c..a7be00a42 100644 --- a/FHEOffline/SimpleMachine.cpp +++ b/FHEOffline/SimpleMachine.cpp @@ -27,7 +27,7 @@ void* run_generator(void* generator) MachineBase::MachineBase() : throughput_loop_thread(0),portnum_base(0), data_type(DATA_TRIPLE), - sec(0), drown_sec(0), field_size(0), extra_slack(0), + sec(0), field_size(0), extra_slack(0), produce_inputs(false), use_gf2n(false) { @@ -91,7 +91,6 @@ void MachineBase::parse_options(int argc, const char** argv) opt.get("-h")->getString(hostname); opt.get("-pn")->getInt(portnum_base); opt.get("-s")->getInt(sec); - drown_sec = max(40, sec); opt.get("-f")->getInt(field_size); use_gf2n = opt.isSet("-2"); if (use_gf2n) @@ -221,7 +220,7 @@ void MultiplicativeMachine::fake_keys(int slack) PartSetup& part_setup = setup.part(); if (P.my_num() == 0) { - part_setup.generate_setup(N.num_players(), field_size, drown_sec, slack, true); + part_setup.generate_setup(N.num_players(), field_size, sec, slack, true); vector > setups; part_setup.fake(setups, P.num_players(), false); for (int i = 1; i < P.num_players(); i++) @@ -238,7 +237,7 @@ void MultiplicativeMachine::fake_keys(int slack) P.receive_player(0, os); } part_setup.unpack(os); - part_setup.check(drown_sec); + part_setup.check(); part_setup.alphai = read_or_generate_mac_key>(P); Plaintext_ m(part_setup.FieldD); diff --git a/FHEOffline/SimpleMachine.h b/FHEOffline/SimpleMachine.h index 8ca37bbfe..e8d071700 100644 --- a/FHEOffline/SimpleMachine.h +++ b/FHEOffline/SimpleMachine.h @@ -26,7 +26,6 @@ class MachineBase : public OfflineMachineBase public: int sec; - int drown_sec; int field_size; int extra_slack; bool produce_inputs; diff --git a/FHEOffline/TemiSetup.cpp b/FHEOffline/TemiSetup.cpp index fc222ed51..fd922d4cf 100644 --- a/FHEOffline/TemiSetup.cpp +++ b/FHEOffline/TemiSetup.cpp @@ -15,9 +15,7 @@ TemiSetup::TemiSetup() this->pk = {this->params, 0}; this->sk = {this->params, 0}; this->calpha = this->params; - this->params.set_matrix_dim( - HemiOptions::singleton.plain_matmul ? - 1 : OnlineOptions::singleton.batch_size); + this->params.set_matrix_dim_from_options(); } template diff --git a/GC/CcdShare.h b/GC/CcdShare.h index e890ce633..894d3ae74 100644 --- a/GC/CcdShare.h +++ b/GC/CcdShare.h @@ -40,7 +40,7 @@ class CcdShare : public ShamirShare, public ShareSecret> return "CCD"; } - static MAC_Check* new_mc(T) + static MAC_Check* new_mc(typename super::mac_key_type) { return new MAC_Check; } diff --git a/GC/DealerPrep.h b/GC/DealerPrep.h new file mode 100644 index 000000000..a3bd4bcc8 --- /dev/null +++ b/GC/DealerPrep.h @@ -0,0 +1,69 @@ +/* + * DealerPrep.h + * + */ + +#ifndef GC_DEALERPREP_H_ +#define GC_DEALERPREP_H_ + +#include "Protocols/DealerPrep.h" +#include "Protocols/ProtocolSet.h" +#include "ShiftableTripleBuffer.h" +#include "SemiSecret.h" + +namespace GC +{ +class DealerPrep : public BufferPrep, ShiftableTripleBuffer +{ + Player* P; + +public: + DealerPrep(DataPositions& usage, int = -1) : + BufferPrep(usage), P(0) + { + } + + void set_protocol(DealerSecret::Protocol& protocol) + { + P = &protocol.P; + } + + void buffer_triples() + { + ProtocolSetup> setup(*P); + ProtocolSet> set(*P, setup); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + { + auto triple = set.preprocessing.get_triple( + DealerSecret::default_length); + this->triples.push_back({{triple[0], triple[1], triple[2]}}); + } + } + + void buffer_bits() + { + SeededPRNG G; + if (P->my_num() != 0) + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + this->bits.push_back(G.get_bit()); + else + this->bits.resize( + this->bits.size() + OnlineOptions::singleton.batch_size); + } + + void get(Dtype type, DealerSecret* data) + { + BufferPrep::get(type, data); + } + + array get_triple_no_count(int n_bits) + { + if (n_bits == -1) + n_bits = DealerSecret::default_length; + return ShiftableTripleBuffer::get_triple_no_count(n_bits); + } +}; + +} + +#endif /* GC_DEALERPREP_H_ */ diff --git a/GC/FakeSecret.h b/GC/FakeSecret.h index 00e6c52c9..ee7a84462 100644 --- a/GC/FakeSecret.h +++ b/GC/FakeSecret.h @@ -10,6 +10,7 @@ #include "GC/Memory.h" #include "GC/Access.h" #include "GC/ArgTuples.h" +#include "GC/NoShare.h" #include "Math/gf2nlong.h" #include "Tools/SwitchableOutput.h" @@ -40,7 +41,6 @@ class FakeSecret : public ShareInterface, public BitVec typedef FakeSecret DynamicType; typedef Memory DynamicMemory; - typedef BitVec mac_key_type; typedef BitVec clear; typedef BitVec open_type; diff --git a/GC/MaliciousCcdShare.h b/GC/MaliciousCcdShare.h index 9dc63fc63..fbc66ea1a 100644 --- a/GC/MaliciousCcdShare.h +++ b/GC/MaliciousCcdShare.h @@ -44,7 +44,7 @@ class MaliciousCcdShare: public MaliciousShamirShare, public ShareSecret< return "Malicious CCD"; } - static MAC_Check* new_mc(T) + static MAC_Check* new_mc(typename super::mac_key_type) { return new MAC_Check; } diff --git a/GC/MaliciousRepSecret.h b/GC/MaliciousRepSecret.h index 500bbb5af..9f941d51d 100644 --- a/GC/MaliciousRepSecret.h +++ b/GC/MaliciousRepSecret.h @@ -30,7 +30,7 @@ class SmallMalRepSecret : public FixedVec, 2> typedef MaliciousRepMC MC; typedef BitVec_ open_type; typedef open_type clear; - typedef BitVec mac_key_type; + typedef NoValue mac_key_type; static MC* new_mc(mac_key_type) { @@ -71,7 +71,7 @@ class MalRepSecretBase : public ReplicatedSecret static const bool expensive_triples = true; - static MC* new_mc(BitVec) + static MC* new_mc(typename super::mac_key_type) { try { diff --git a/GC/NoShare.h b/GC/NoShare.h index c435ec3f8..49f93ac42 100644 --- a/GC/NoShare.h +++ b/GC/NoShare.h @@ -60,35 +60,43 @@ class NoValue : public ValueInterface throw not_implemented(); } + static void init_minimum(int) + { + } + static void fail() { throw runtime_error("VM does not support binary circuits"); } NoValue() {} - NoValue(int) { fail(); } + NoValue(bool) {} + NoValue(ValueInterface) {} + NoValue(int128) {} void assign(const char*) { fail(); } + const char* get_ptr() const { return (char*) this; } + int get() const { fail(); return 0; } int operator<<(int) const { fail(); return 0; } void operator+=(int) { fail(); } - bool operator!=(NoValue) const { fail(); return 0; } + bool operator!=(NoValue) const { return false; } bool operator==(int) { fail(); return false; } bool get_bit(int) { fail(); return 0; } - void randomize(PRNG&) { fail(); } + void randomize(PRNG&) {} void invert() { fail(); } void mask(int) { fail(); } void input(istream&, bool) { fail(); } - void output(ostream&, bool) { fail(); } + void output(ostream&, bool) {} }; inline ostream& operator<<(ostream& o, NoValue) diff --git a/GC/Processor.hpp b/GC/Processor.hpp index 663d55fcb..96b2d62d8 100644 --- a/GC/Processor.hpp +++ b/GC/Processor.hpp @@ -340,7 +340,7 @@ void Processor::convcbit2s(const BaseInstruction& instruction) for (int i = 0; i < DIV_CEIL(instruction.get_n(), unit); i++) S[instruction.get_r(0) + i] = T::constant(C[instruction.get_r(1) + i], share_thread.P->my_num(), share_thread.MC->get_alphai(), - min(unsigned(unit), instruction.get_n() - i * unit)); + min(size_t(unit), instruction.get_n() - i * unit)); } template diff --git a/GC/SemiSecret.h b/GC/SemiSecret.h index ae10b5222..e95554bf5 100644 --- a/GC/SemiSecret.h +++ b/GC/SemiSecret.h @@ -8,6 +8,7 @@ #include "Protocols/SemiMC.h" #include "Protocols/SemiShare.h" +#include "Protocols/DealerShare.h" #include "Processor/DummyProtocol.h" #include "ShareSecret.h" @@ -17,71 +18,116 @@ namespace GC { class SemiPrep; +class DealerPrep; -class SemiSecret : public SemiShare, public ShareSecret +template +class SemiSecretBase : public V, public ShareSecret { + typedef V super; + public: - typedef Memory DynamicMemory; + typedef Memory DynamicMemory; - typedef SemiMC MC; - typedef DirectSemiMC Direct_MC; - typedef Beaver Protocol; - typedef MC MAC_Check; - typedef SemiPrep LivePrep; - typedef SemiInput Input; + typedef Beaver Protocol; - typedef SemiSecret part_type; - typedef SemiSecret small_type; + typedef T part_type; + typedef T small_type; static const int default_length = sizeof(BitVec) * 8; static string type_string() { return "binary secret"; } static string phase_name() { return "Binary computation"; } - static MC* new_mc(mac_key_type); - - template - static void generate_mac_key(mac_key_type, T) - { - } - - static void trans(Processor& processor, int n_outputs, + static void trans(Processor& processor, int n_outputs, const vector& args); - SemiSecret() + SemiSecretBase() { } - SemiSecret(long other) : - SemiShare(other) + SemiSecretBase(long other) : + V(other) { } - SemiSecret(const IntBase& other) : - SemiShare(other) + template + SemiSecretBase(const IntBase& other) : + V(other) { } template - SemiSecret(const Z2& other) : - SemiShare(other) + SemiSecretBase(const Z2& other) : + V(other) { } void load_clear(int n, const Integer& x); - void bitcom(Memory& S, const vector& regs); - void bitdec(Memory& S, const vector& regs) const; + void bitcom(Memory& S, const vector& regs); + void bitdec(Memory& S, const vector& regs) const; - void xor_(int n, const SemiSecret& x, const SemiSecret& y) + void xor_(int n, const T& x, const T& y) { *this = BitVec(x ^ y).mask(n); } - void xor_bit(int i, const SemiSecret& bit) + void xor_bit(int i, const T& bit) { *this ^= bit << i; } void reveal(size_t n_bits, Clear& x); - SemiSecret lsb() + T lsb() { return *this & 1; } }; +class SemiSecret: public SemiSecretBase> +{ + typedef SemiSecret This; + +public: + typedef SemiSecretBase> super; + + typedef SemiMC MC; + typedef DirectSemiMC Direct_MC; + typedef MC MAC_Check; + typedef SemiInput Input; + typedef SemiPrep LivePrep; + + static MC* new_mc(typename SemiShare::mac_key_type); + + SemiSecret() + { + } + + template + SemiSecret(const T& other) : + super(other) + { + } +}; + +class DealerSecret : public SemiSecretBase> +{ + typedef DealerSecret This; + +public: + typedef SemiSecretBase> super; + + typedef DealerMC MC; + typedef DirectDealerMC Direct_MC; + typedef MC MAC_Check; + typedef DealerInput Input; + typedef DealerPrep LivePrep; + + static MC* new_mc(typename super::mac_key_type); + + DealerSecret() + { + } + + template + DealerSecret(const T& other) : + super(other) + { + } +}; + } /* namespace GC */ #endif /* GC_SEMISECRET_H_ */ diff --git a/GC/SemiSecret.cpp b/GC/SemiSecret.hpp similarity index 61% rename from GC/SemiSecret.cpp rename to GC/SemiSecret.hpp index 704e2a2fb..f6a4d3984 100644 --- a/GC/SemiSecret.cpp +++ b/GC/SemiSecret.hpp @@ -4,17 +4,30 @@ */ #include "GC/ShareParty.h" -#include "SemiSecret.h" - #include "GC/ShareSecret.hpp" #include "Protocols/MAC_Check_Base.hpp" +#include "Protocols/DealerMC.h" +#include "SemiSecret.h" namespace GC { -const int SemiSecret::default_length; +template +const int SemiSecretBase::default_length; + +inline +SemiSecret::MC* SemiSecret::new_mc( + typename super::mac_key_type) +{ + if (OnlineOptions::singleton.direct) + return new Direct_MC; + else + return new MC; +} -SemiSecret::MC* SemiSecret::new_mc(mac_key_type) +inline +DealerSecret::MC* DealerSecret::new_mc( + typename super::mac_key_type) { if (OnlineOptions::singleton.direct) return new Direct_MC; @@ -22,7 +35,8 @@ SemiSecret::MC* SemiSecret::new_mc(mac_key_type) return new MC; } -void SemiSecret::trans(Processor& processor, int n_outputs, +template +void SemiSecretBase::trans(Processor& processor, int n_outputs, const vector& args) { int N_BITS = default_length; @@ -46,29 +60,33 @@ void SemiSecret::trans(Processor& processor, int n_outputs, } } -void SemiSecret::load_clear(int n, const Integer& x) +template +void SemiSecretBase::load_clear(int n, const Integer& x) { - check_length(n, x); - *this = constant(x, ShareThread::s().P->my_num()); + this->check_length(n, x); + *this = this->constant(x, ShareThread::s().P->my_num()); } -void SemiSecret::bitcom(Memory& S, const vector& regs) +template +void SemiSecretBase::bitcom(Memory& S, const vector& regs) { *this = 0; for (unsigned int i = 0; i < regs.size(); i++) *this ^= (S[regs[i]] << i); } -void SemiSecret::bitdec(Memory& S, +template +void SemiSecretBase::bitdec(Memory& S, const vector& regs) const { for (unsigned int i = 0; i < regs.size(); i++) S[regs[i]] = (*this >> i) & 1; } -void SemiSecret::reveal(size_t n_bits, Clear& x) +template +void SemiSecretBase::reveal(size_t n_bits, Clear& x) { - auto& thread = ShareThread::s(); + auto& thread = ShareThread::s(); x = thread.MC->POpen(*this, *thread.P).mask(n_bits); } diff --git a/GC/ShareSecret.h b/GC/ShareSecret.h index 6d9f26525..fb254486b 100644 --- a/GC/ShareSecret.h +++ b/GC/ShareSecret.h @@ -112,8 +112,8 @@ class RepSecretBase : public FixedVec, public ShareSecret typedef BitVec clear; typedef BitVec open_type; - typedef BitVec mac_type; - typedef BitVec mac_key_type; + typedef NoShare mac_type; + typedef NoValue mac_key_type; typedef NoShare bit_type; @@ -213,7 +213,7 @@ class SmallRepSecret : public FixedVec, 2> typedef ReplicatedMC MC; typedef BitVec_ open_type; typedef open_type clear; - typedef BitVec mac_key_type; + typedef NoValue mac_key_type; static MC* new_mc(mac_key_type) { diff --git a/GC/ThreadMaster.hpp b/GC/ThreadMaster.hpp index c6c9dcaac..a426eea29 100644 --- a/GC/ThreadMaster.hpp +++ b/GC/ThreadMaster.hpp @@ -11,6 +11,8 @@ #include "instructions.h" +#include "Tools/benchmarking.h" + #include "Machine.hpp" namespace GC @@ -58,15 +60,10 @@ Thread* ThreadMaster::new_thread(int i) template void ThreadMaster::run() { -#ifndef INSECURE if (not opts.live_prep) { - cerr - << "Preprocessing from file not supported by binary virtual machines" - << endl; - exit(1); + insecure("preprocessing from file in binary virtual machines"); } -#endif P = new PlainPlayer(N, "main"); diff --git a/GC/TinyMC.h b/GC/TinyMC.h index e0a0b948b..ac3a29ab2 100644 --- a/GC/TinyMC.h +++ b/GC/TinyMC.h @@ -48,12 +48,12 @@ class TinyMC : public MAC_Check_Base part_MC.exchange(P); } - typename T::open_type finalize_open() + typename T::open_type finalize_raw() { int n = sizes.next(); typename T::open_type opened = 0; for (int i = 0; i < n; i++) - opened += typename T::open_type(part_MC.finalize_open().get_bit(0)) << i; + opened += typename T::open_type(part_MC.finalize_raw().get_bit(0)) << i; return opened; } diff --git a/Machines/SPDZ2k.hpp b/Machines/SPDZ2k.hpp index 6cb02779d..04508c09a 100644 --- a/Machines/SPDZ2k.hpp +++ b/Machines/SPDZ2k.hpp @@ -5,6 +5,7 @@ #include "Protocols/Spdz2kShare.h" #include "Protocols/Spdz2kPrep.h" +#include "Protocols/SPDZ2k.h" #include "GC/TinySecret.h" #include "GC/TinyMC.h" diff --git a/Machines/Semi.hpp b/Machines/Semi.hpp index 1a0931467..02686df79 100644 --- a/Machines/Semi.hpp +++ b/Machines/Semi.hpp @@ -19,3 +19,4 @@ #include "Protocols/SemiMC.hpp" #include "Protocols/Beaver.hpp" #include "Protocols/MalRepRingPrep.hpp" +#include "GC/SemiSecret.hpp" diff --git a/Machines/ShamirMachine.hpp b/Machines/ShamirMachine.hpp index 9f18d3a6f..d8cc30140 100644 --- a/Machines/ShamirMachine.hpp +++ b/Machines/ShamirMachine.hpp @@ -97,6 +97,5 @@ ShamirMachineSpec::ShamirMachineSpec(int argc, const char** argv) auto& opts = ShamirOptions::singleton; ez::ezOptionParser opt; opts = {opt, argc, argv}; - T::bit_type::part_type::open_type::init_field(); HonestMajorityFieldMachine(argc, argv, opt, opts.nparties); } diff --git a/Machines/TripleMachine.cpp b/Machines/TripleMachine.cpp index 82cde5e8d..e4a876fe2 100644 --- a/Machines/TripleMachine.cpp +++ b/Machines/TripleMachine.cpp @@ -142,8 +142,8 @@ TripleMachine::TripleMachine(int argc, const char** argv) : gfpvar1::init_field(prime, false); else gfpvar1::init_default(128, false); - gf2n_long::init_field(128); - gf2n_short::init_field(40); + gf2n_long::init_field(); + gf2n_short::init_field(); PRNG G; G.ReSeed(); diff --git a/Machines/dealer-ring-party.cpp b/Machines/dealer-ring-party.cpp new file mode 100644 index 000000000..4bc8fab1a --- /dev/null +++ b/Machines/dealer-ring-party.cpp @@ -0,0 +1,22 @@ +/* + * dealer-ring-party.cpp + * + */ + +#include "Protocols/DealerShare.h" +#include "Protocols/DealerInput.h" + +#include "Processor/RingMachine.hpp" +#include "Processor/Machine.hpp" +#include "Protocols/Replicated.hpp" +#include "Protocols/DealerPrep.hpp" +#include "Protocols/DealerInput.hpp" +#include "Protocols/DealerMC.hpp" +#include "Protocols/Beaver.hpp" +#include "Semi.hpp" +#include "GC/DealerPrep.h" + +int main(int argc, const char** argv) +{ + HonestMajorityRingMachine(argc, argv, 0); +} diff --git a/Machines/emulate.cpp b/Machines/emulate.cpp index f26f5f324..5999050c2 100644 --- a/Machines/emulate.cpp +++ b/Machines/emulate.cpp @@ -54,9 +54,8 @@ int main(int argc, const char** argv) { #define X(L) \ case L: \ - Machine>, FakeShare>(0, N, progname, \ - online_opts.memtype, gf2n::default_degree(), 0, 0, 0, 0, false, \ - online_opts.live_prep, online_opts).run(); \ + Machine>, FakeShare>(N, false, online_opts, \ + gf2n::default_degree()).run(progname); \ break; X(64) X(128) X(256) X(192) X(384) X(512) #ifdef RING_SIZE diff --git a/Machines/hemi-party.cpp b/Machines/hemi-party.cpp index 934c15dcd..60e0d6e4f 100644 --- a/Machines/hemi-party.cpp +++ b/Machines/hemi-party.cpp @@ -27,6 +27,7 @@ #include "Protocols/MalRepRingPrep.hpp" #include "GC/ShareSecret.hpp" #include "GC/SemiHonestRepPrep.h" +#include "GC/SemiSecret.hpp" #include "Math/gfp.hpp" int main(int argc, const char** argv) diff --git a/Machines/malicious-ccd-party.cpp b/Machines/malicious-ccd-party.cpp index 4ce84aea3..55ec8b99b 100644 --- a/Machines/malicious-ccd-party.cpp +++ b/Machines/malicious-ccd-party.cpp @@ -18,8 +18,9 @@ int main(int argc, const char** argv) { - gf2n_short::init_field(40); ez::ezOptionParser opt; ShamirOptions::singleton = {opt, argc, argv}; + OnlineOptions opts(opt, argc, argv); + gf2n_short::init_minimum(opts.security_parameter); GC::ShareParty>(argc, argv, opt); } diff --git a/Machines/semi-bin-party.cpp b/Machines/semi-bin-party.cpp index fbd0a6345..6c99ebf9c 100644 --- a/Machines/semi-bin-party.cpp +++ b/Machines/semi-bin-party.cpp @@ -14,6 +14,7 @@ #include "GC/Thread.hpp" #include "GC/ThreadMaster.hpp" #include "GC/Processor.hpp" +#include "GC/SemiSecret.hpp" #include "Protocols/MAC_Check_Base.hpp" #include "Protocols/SemiMC.hpp" #include "Protocols/SemiInput.hpp" diff --git a/Machines/soho-party.cpp b/Machines/soho-party.cpp index 7ecc450da..ced64919f 100644 --- a/Machines/soho-party.cpp +++ b/Machines/soho-party.cpp @@ -25,6 +25,7 @@ #include "Protocols/MalRepRingPrep.hpp" #include "GC/ShareSecret.hpp" #include "GC/SemiHonestRepPrep.h" +#include "GC/SemiSecret.hpp" #include "Math/gfp.hpp" int main(int argc, const char** argv) diff --git a/Machines/spdz2k-party.cpp b/Machines/spdz2k-party.cpp index 8aba31737..9e8267376 100644 --- a/Machines/spdz2k-party.cpp +++ b/Machines/spdz2k-party.cpp @@ -22,12 +22,12 @@ int main(int argc, const char** argv) 1, // Number of args expected. 0, // Delimiter if expecting multiple args. "SPDZ2k security parameter (default: 64)", // Help description. - "-S", // Flag token. - "--security" // Flag token. + "-SP", // Flag token. + "--spdz2k-security" // Flag token. ); opt.parse(argc, argv); int s; - opt.get("-S")->getInt(s); + opt.get("-SP")->getInt(s); opt.resetArgs(); RingOptions ring_options(opt, argc, argv); int k = ring_options.R; @@ -62,6 +62,8 @@ int main(int argc, const char** argv) cerr << "add Z(" << k << ", " << s << ") to " << __FILE__ << " at line " << (__LINE__ - 11) << " and create Machines/SPDZ2^" << k << "+" << s << ".cpp based on Machines/SPDZ2^72+64.cpp" << endl; + cerr << "Alternatively, compile with -DRING_SIZE=" << k + << " and -DSPDZ2K_DEFAULT_SECURITY=" << s << endl; } exit(1); } diff --git a/Machines/temi-party.cpp b/Machines/temi-party.cpp index 12e99dc27..f8abd35d8 100644 --- a/Machines/temi-party.cpp +++ b/Machines/temi-party.cpp @@ -26,6 +26,7 @@ #include "Protocols/Hemi.hpp" #include "GC/ShareSecret.hpp" #include "GC/SemiHonestRepPrep.h" +#include "GC/SemiSecret.hpp" #include "Math/gfp.hpp" int main(int argc, const char** argv) diff --git a/Machines/tinier-party.cpp b/Machines/tinier-party.cpp index 82122bd11..67234a8a5 100644 --- a/Machines/tinier-party.cpp +++ b/Machines/tinier-party.cpp @@ -28,6 +28,8 @@ int main(int argc, const char** argv) { - gf2n_short::init_field(40); + ez::ezOptionParser opt; + OnlineOptions opts(opt, argc, argv); + gf2n_short::init_minimum(opts.security_parameter); GC::simple_binary_main>(argc, argv, 1000); } diff --git a/Machines/tiny-party.cpp b/Machines/tiny-party.cpp index 7e72361eb..f83f839f5 100644 --- a/Machines/tiny-party.cpp +++ b/Machines/tiny-party.cpp @@ -29,5 +29,5 @@ int main(int argc, const char** argv) { - GC::simple_binary_main>(argc, argv, 1000); + GC::simple_binary_main>(argc, argv, 1000); } diff --git a/Makefile b/Makefile index 4f558e1d6..3c2be0090 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ PROCESSOR = $(patsubst %.cpp,%.o,$(wildcard Processor/*.cpp)) FHEOBJS = $(patsubst %.cpp,%.o,$(wildcard FHEOffline/*.cpp FHE/*.cpp)) Protocols/CowGearOptions.o GC = $(patsubst %.cpp,%.o,$(wildcard GC/*.cpp)) $(PROCESSOR) -GC_SEMI = GC/SemiSecret.o GC/SemiPrep.o GC/square64.o +GC_SEMI = GC/SemiPrep.o GC/square64.o OT = $(patsubst %.cpp,%.o,$(wildcard OT/*.cpp)) OT_EXE = ot.x ot-offline.x @@ -57,7 +57,7 @@ vm: arithmetic binary doc: cd doc; $(MAKE) html -arithmetic: rep-ring rep-field shamir semi2k-party.x semi-party.x mascot sy +arithmetic: rep-ring rep-field shamir semi2k-party.x semi-party.x mascot sy dealer-ring-party.x binary: rep-bin yao semi-bin-party.x tinier-party.x tiny-party.x ccd-party.x malicious-ccd-party.x real-bmr all: overdrive she-offline @@ -162,7 +162,7 @@ bmr-%.x: $(BMR) $(VM) Machines/bmr-%.cpp $(LIBSIMPLEOT) bmr-clean: -rm BMR/*.o BMR/*/*.o GC/*.o -bankers-bonus-client.x: ExternalIO/bankers-bonus-client.cpp $(COMMON) +bankers-bonus-client.x: ExternalIO/bankers-bonus-client.o $(COMMON) $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) simple-offline.x: $(FHEOFFLINE) @@ -203,13 +203,13 @@ replicated-field-party.x: GC/square64.o brain-party.x: GC/square64.o malicious-rep-bin-party.x: GC/square64.o ps-rep-bin-party.x: GC/PostSacriBin.o -semi-bin-party.x: $(OT) GC/SemiSecret.o GC/SemiPrep.o GC/square64.o +semi-bin-party.x: $(OT) GC/SemiPrep.o GC/square64.o tiny-party.x: $(OT) tinier-party.x: $(OT) spdz2k-party.x: $(TINIER) $(patsubst %.cpp,%.o,$(wildcard Machines/SPDZ2*.cpp)) static/spdz2k-party.x: $(patsubst %.cpp,%.o,$(wildcard Machines/SPDZ2*.cpp)) -semi-party.x: $(OT) GC/SemiSecret.o GC/SemiPrep.o GC/square64.o -semi2k-party.x: $(OT) GC/SemiSecret.o GC/SemiPrep.o GC/square64.o +semi-party.x: $(OT) GC/SemiPrep.o GC/square64.o +semi2k-party.x: $(OT) GC/SemiPrep.o GC/square64.o hemi-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT) temi-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT) soho-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT) @@ -234,15 +234,16 @@ malicious-rep-ring-party.x: Protocols/MalRepRingOptions.o sy-rep-ring-party.x: Protocols/MalRepRingOptions.o rep4-ring-party.x: GC/Rep4Secret.o no-party.x: Protocols/ShareInterface.o -semi-ecdsa-party.x: $(OT) $(LIBSIMPLEOT) GC/SemiPrep.o GC/SemiSecret.o +semi-ecdsa-party.x: $(OT) $(LIBSIMPLEOT) GC/SemiPrep.o mascot-ecdsa-party.x: $(OT) $(LIBSIMPLEOT) fake-spdz-ecdsa-party.x: $(OT) $(LIBSIMPLEOT) emulate.x: GC/FakeSecret.o -semi-bmr-party.x: GC/SemiPrep.o GC/SemiSecret.o $(OT) +semi-bmr-party.x: GC/SemiPrep.o $(OT) real-bmr-party.x: $(OT) paper-example.x: $(VM) $(OT) $(FHEOFFLINE) -binary-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/SemiSecret.o GC/AtlasSecret.o -mixed-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/SemiSecret.o GC/AtlasSecret.o Machines/Tinier.o +binary-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/AtlasSecret.o +mixed-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/AtlasSecret.o Machines/Tinier.o +l2h-example.x: $(VM) $(OT) Machines/Tinier.o mascot-offline.x: $(VM) $(TINIER) cowgear-offline.x: $(TINIER) $(FHEOFFLINE) static/rep-bmr-party.x: $(BMR) @@ -253,6 +254,7 @@ static/semi-bmr-party.x: $(BMR) static/real-bmr-party.x: $(BMR) static/bmr-program-party.x: $(BMR) static/no-party.x: Protocols/ShareInterface.o +Test/failure.x: Protocols/MalRepRingOptions.o ifeq ($(AVX_OT), 1) $(LIBSIMPLEOT): SimpleOT/Makefile @@ -270,7 +272,7 @@ Programs/Circuits: .PHONY: mpir-setup mpir-global mpir mpir-setup: - git submodule update --init mpir + git submodule update --init mpir || git clone https://github.com/wbhart/mpir cd mpir; \ autoreconf -i; \ autoreconf -i @@ -306,7 +308,7 @@ linux-machine-setup: endif simde/simde: - git submodule update --init simde + git submodule update --init simde || git clone https://github.com/simd-everywhere/simde clean: -rm -f */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o static/*.x *.so diff --git a/Math/Integer.h b/Math/Integer.h index 8104724c0..1fbb257fc 100644 --- a/Math/Integer.h +++ b/Math/Integer.h @@ -37,8 +37,6 @@ class IntBase : public ValueInterface static void specification(octetStream& os); - static void init_default(int lgp) { (void)lgp; } - static bool allows(Dtype type) { return type <= DATA_BIT; } IntBase() { a = 0; } diff --git a/Math/Setup.cpp b/Math/Setup.cpp index b4800017c..dc76e47d7 100644 --- a/Math/Setup.cpp +++ b/Math/Setup.cpp @@ -27,6 +27,13 @@ void SPDZ_Data_Setup_Primes(bigint& p,int lgp,int& idx,int& m) cerr << "Setting up parameters" << endl; #endif + m = default_m(lgp, idx); + generate_prime(p, lgp, m); +} + +int default_m(int& lgp, int& idx) +{ + int m; switch (lgp) { case -1: m=16; @@ -56,15 +63,12 @@ void SPDZ_Data_Setup_Primes(bigint& p,int lgp,int& idx,int& m) default: m=1; idx=0; -#ifdef VERBOSE - cerr << "no precomputed parameters, trying anyway" << endl; -#endif break; } #ifdef VERBOSE cerr << "m = " << m << endl; #endif - generate_prime(p, lgp, m); + return m; } bigint generate_prime(int lgp, int m) @@ -95,6 +99,9 @@ void generate_prime(bigint& p, int lgp, int m) return; } + int idx; + m = max(m, default_m(lgp, idx)); + bigint u; int ex; ex = lgp - numBits(m); diff --git a/Math/Setup.h b/Math/Setup.h index f8405ba3b..8c599198e 100644 --- a/Math/Setup.h +++ b/Math/Setup.h @@ -35,6 +35,7 @@ bigint SPDZ_Data_Setup_Primes(int lgp); void SPDZ_Data_Setup_Primes(bigint& p,int lgp,int& idx,int& m); void generate_prime(bigint& p, int lgp, int m); bigint generate_prime(int lgp, int m); +int default_m(int& lgp, int& idx); string get_prep_sub_dir(const string& prep_dir, int nparties, int log2mod, const string& type_short); diff --git a/Math/bigint.h b/Math/bigint.h index 5cd319817..cb79f2424 100644 --- a/Math/bigint.h +++ b/Math/bigint.h @@ -12,6 +12,7 @@ using namespace std; #include "Tools/random.h" #include "Tools/octetStream.h" #include "Tools/avx_memcpy.h" +#include "Protocols/config.h" enum ReportType { @@ -270,7 +271,8 @@ inline int probPrime(const bigint& x) { gmp_randstate_t rand_state; gmp_randinit_default(rand_state); - int ans=mpz_probable_prime_p(x.get_mpz_t(),rand_state,40,0); + int ans = mpz_probable_prime_p(x.get_mpz_t(), rand_state, + max(40, DEFAULT_SECURITY), 0); gmp_randclear(rand_state); return ans; } diff --git a/Math/gf2n.cpp b/Math/gf2n.cpp index f9491fb7b..44e424794 100644 --- a/Math/gf2n.cpp +++ b/Math/gf2n.cpp @@ -18,7 +18,7 @@ bool gf2n_::useC; word gf2n_short_table[256][256]; -#define num_2_fields 7 +#define num_2_fields 17 /* Require * 2*(n-1)-64+t1<64 @@ -26,11 +26,21 @@ word gf2n_short_table[256][256]; int fields_2[num_2_fields][4] = { { 4, 1, 0, 0 }, + { 5, 2, 0, 0 }, + { 6, 1, 0, 0 }, + { 7, 1, 0, 0 }, { 8, 4, 3, 1 }, + { 9, 1, 0, 0 }, + { 10, 3, 0, 0}, + { 11, 2, 0, 0}, + { 12, 3, 0, 0}, + { 14, 5, 0, 0}, + { 15, 1, 0, 0}, { 16, 5, 3, 1 }, { 28, 1, 0, 0 }, { 40, 20, 15, 10 }, { 63, 1, 0, 0 }, + { 64, 4, 3, 1}, { 128, 7, 2, 1 }, }; @@ -55,6 +65,21 @@ void gf2n_::init_tables() } } +template +void gf2n_::init_minimum(int lower) +{ + if (lower <= n) + return; + + for (int i = 0; i < num_2_fields; i++) + { + int n = fields_2[i][0]; + if (lower <= n and n <= MAX_N_BITS) + return init_field(n); + } + throw runtime_error("no suitable field for minimum degree " + to_string(lower)); +} + void gf2n_short::init_field(int nn) { super::init_field(nn == 0 ? DEFAULT_LENGTH : nn); @@ -88,7 +113,7 @@ void gf2n_::init_field(int nn) if (j==-1) { - throw runtime_error("field size not supported"); + throw gf2n_not_supported(nn); } n=nn; @@ -332,7 +357,11 @@ gf2n_ gf2n_::invert() const if (n < 64) return U(invert(a)); else - return invert>(a).get_lower(); + { + gf2n_ res; + res.a = invert(a).get_lower(); + return res; + } } template<> diff --git a/Math/gf2n.h b/Math/gf2n.h index add8627cf..485d84308 100644 --- a/Math/gf2n.h +++ b/Math/gf2n.h @@ -65,6 +65,7 @@ class gf2n_ : public ValueInterface static void init_field(int nn = 0); static void init_default(int, bool = false) { init_field(); } + static void init_minimum(int lower); static void reset() { n = 0; } static int degree() { return n; } @@ -213,7 +214,7 @@ class gf2n_short : public gf2n_ static const int DEFAULT_LENGTH = 40; static int length() { return n == 0 ? DEFAULT_LENGTH : n; } - static int default_degree() { return 40; } + static int default_degree() { return DEFAULT_LENGTH; } static void init_field(int nn = 0); diff --git a/Networking/AllButLastPlayer.h b/Networking/AllButLastPlayer.h new file mode 100644 index 000000000..22482c481 --- /dev/null +++ b/Networking/AllButLastPlayer.h @@ -0,0 +1,67 @@ +/* + * AllButZeroPlayer.h + * + */ + +#ifndef NETWORKING_ALLBUTLASTPLAYER_H_ +#define NETWORKING_ALLBUTLASTPLAYER_H_ + +#include "Player.h" + +class AllButLastPlayer : public Player +{ + const Player& P; + Names* N; + +public: + AllButLastPlayer(const Player& P) : + Player(*(N = new Names(P.my_num(), P.num_players() - 1))), P(P) + { + } + + ~AllButLastPlayer() + { + delete N; + } + + void send_to_no_stats(int player, const octetStream& o) const + { + P.send_to(player, o); + } + + void receive_player_no_stats(int i, octetStream& o) const + { + P.receive_player(i, o); + } + + void send_receive_all_no_stats(const vector>& channels, + const vector& to_send, + vector& to_receive) const + { + auto my_channels = channels; + my_channels.resize(P.num_players()); + for (auto& x : my_channels) + x.resize(P.num_players()); + auto my_to_send = to_send; + if (P.my_num() != P.num_players() - 1) + P.send_receive_all(my_channels, my_to_send, to_receive); + to_receive.resize(P.num_players() - 1); + } + + void Broadcast_Receive_no_stats(vector& os) const + { + vector to_send(P.num_players(), os[P.my_num()]); + vector> channels(P.num_players(), + vector(P.num_players(), true)); + for (auto& x: channels) + x.back() = false; + channels.back() = vector(P.num_players(), false); + vector to_receive; + P.send_receive_all(channels, to_send, to_receive); + for (int i = 0; i < P.num_players() - 1; i++) + if (i != P.my_num()) + os[i] = to_receive[i]; + } +}; + +#endif diff --git a/Networking/Player.cpp b/Networking/Player.cpp index b4bab177f..a7935f305 100644 --- a/Networking/Player.cpp +++ b/Networking/Player.cpp @@ -146,10 +146,18 @@ void Names::setup_names(const char *servername, int my_port) #endif // Now get the set of names - octetStream os; - os.Receive(socket_num); - os.get(names); - os.get(ports); + try + { + octetStream os; + os.Receive(socket_num); + os.get(names); + os.get(ports); + } + catch (exception& e) + { + throw runtime_error(string("error in network setup: ") + e.what()); + } + if (names.size() != ports.size()) throw runtime_error("invalid network setup"); nplayers = names.size(); @@ -186,6 +194,11 @@ Names::Names(const Names& other) server = 0; } +Names::Names(int my_num, int num_players) : + nplayers(num_players), portnum_base(-1), player_no(my_num), server(0) +{ +} + Names::~Names() { if (server != 0) @@ -817,6 +830,17 @@ void NamedCommStats::print(bool newline) cerr << endl; } +void NamedCommStats::reset() +{ + clear(); + sent = 0; +} + +void PlayerBase::reset_stats() +{ + comm_stats.reset(); +} + NamedCommStats Player::total_comm() const { auto res = comm_stats; diff --git a/Networking/Player.h b/Networking/Player.h index ff4bdcd1d..a547d4795 100644 --- a/Networking/Player.h +++ b/Networking/Player.h @@ -116,7 +116,7 @@ class Names Names(ez::ezOptionParser& opt, int argc, const char** argv, int default_nplayers = 2); - Names() : nplayers(1), portnum_base(-1), player_no(0), server(0) { ; } + Names(int my_num = 0, int num_players = 1); Names(const Names& other); ~Names(); @@ -159,6 +159,7 @@ class NamedCommStats : public map NamedCommStats operator-(const NamedCommStats& other) const; size_t total_data(); void print(bool newline = false); + void reset(); #ifdef VERBOSE_COMM CommStats& operator[](const string& name) { @@ -190,10 +191,19 @@ class PlayerBase virtual int my_num() const = 0; virtual int num_players() const = 0; - virtual void pass_around(octetStream& o, int offset = 1) const = 0; - virtual void Broadcast_Receive(vector& o) const = 0; + virtual void receive_player(int, octetStream&) const + { throw not_implemented(); } + virtual void pass_around(octetStream&, int = 1) const + { throw not_implemented(); } + virtual void Broadcast_Receive(vector&) const + { throw not_implemented(); } virtual void unchecked_broadcast(vector& o) const { Broadcast_Receive(o); } + virtual void send_receive_all(const vector&, + vector&) const + { throw not_implemented(); } + + void reset_stats(); }; /** @@ -230,8 +240,8 @@ class Player : public PlayerBase virtual bool is_encrypted() { return false; } - virtual void send_long(int i, long a) const = 0; - virtual long receive_long(int i) const = 0; + virtual void send_long(int, long) const { throw not_implemented(); } + virtual long receive_long(int) const { throw not_implemented(); } // The following functions generally update the statistics // and then call the *_no_stats equivalent specified by a subclass. @@ -283,7 +293,8 @@ class Player : public PlayerBase * reusing the buffer if possible. */ void exchange(int other, const octetStream& to_send, octetStream& ot_receive) const; - virtual void exchange_no_stats(int other, const octetStream& to_send, octetStream& ot_receive) const = 0; + virtual void exchange_no_stats(int, const octetStream&, octetStream&) const + { throw runtime_error("implement exchange"); } /** * Exchange information with one other party, reusing the buffer. */ @@ -304,8 +315,8 @@ class Player : public PlayerBase * The default is to send to the next party while receiving from the previous. */ void pass_around(octetStream& to_send, octetStream& to_receive, int offset) const; - virtual void pass_around_no_stats(const octetStream& to_send, - octetStream& to_receive, int offset) const = 0; + virtual void pass_around_no_stats(const octetStream&, octetStream&, + int) const { throw runtime_error("implement passing around"); } /** * Broadcast and receive data to/from all players. @@ -317,7 +328,8 @@ class Player : public PlayerBase * Assumes o[player_no] contains the data to be broadcast by me. */ virtual void Broadcast_Receive(vector& o) const; - virtual void Broadcast_Receive_no_stats(vector& o) const = 0; + virtual void Broadcast_Receive_no_stats(vector&) const + { throw runtime_error("implement broadcast"); } /** * Run protocol to verify broadcast is correct diff --git a/OT/NPartyTripleGenerator.hpp b/OT/NPartyTripleGenerator.hpp index 732850bc4..5fdbb3d6c 100644 --- a/OT/NPartyTripleGenerator.hpp +++ b/OT/NPartyTripleGenerator.hpp @@ -15,6 +15,7 @@ #include "Protocols/MAC_Check.hpp" #include "Protocols/SemiInput.hpp" #include "Protocols/SemiMC.hpp" +#include "Protocols/mac_key.hpp" #include #include @@ -274,9 +275,9 @@ void NPartyTripleGenerator::generateInputs(int player) inputs.resize(nTriplesPerLoop); typename W::input_check_type::MAC_Check MC(mac_key); - MC.POpen(check_sum, globalPlayer); // use zero element because all is perfectly randomized MC.set_random_element({}); + MC.POpen(check_sum, globalPlayer); MC.Check(globalPlayer); } @@ -673,7 +674,7 @@ void MascotTripleGenerator::sacrifice(typename T::MAC_Check& MC, PRNG& G) auto& outputFile = this->outputFile; auto& uncheckedTriples = this->uncheckedTriples; - assert(T::clear::length() >= 40); + check_field_size(); vector maskedAs(nTriplesPerLoop); vector > maskedTriples(nTriplesPerLoop); @@ -744,6 +745,8 @@ void Spdz2kTripleGenerator::sacrificeZ2k(U& MC, PRNG& G) // and first part of [sigma], i.e., t * [c] - [chat] maskedTriples[j].template prepare_sacrifice(uncheckedTriples[j], G); maskedAs[j] = maskedTriples[j].a[0]; + // enough randomness in values + MC.set_random_element({}); } vector openedAs(nTriplesPerLoop); @@ -754,6 +757,8 @@ void Spdz2kTripleGenerator::sacrificeZ2k(U& MC, PRNG& G) for (int j = 0; j < nTriplesPerLoop; j++) { // compute t * [c] - [chat] - [b] * p sigmas.push_back(maskedTriples[j].computeCheckShare(V(openedAs[j]))); + // enough randomness in values + MC.set_random_element({}); } vector open_sigmas; diff --git a/Processor/BaseMachine.cpp b/Processor/BaseMachine.cpp index 019fc6f28..33d5f441b 100644 --- a/Processor/BaseMachine.cpp +++ b/Processor/BaseMachine.cpp @@ -59,6 +59,8 @@ void BaseMachine::load_schedule(const string& progname, bool load_bytecode) cerr << "Number of program sequences I need to load = " << nprogs << endl; #endif + bc_filenames.clear(); + // Load in the programs string threadname; for (int i=0; i void Sub_Data_Files::buffer_edabits_with_queues(bool strict, int n_bits, false_type) { -#ifndef INSECURE - throw runtime_error("no secure implementation of reading edaBits from files"); -#endif + insecure("reading edaBits from files"); if (edabit_buffers.find(n_bits) == edabit_buffers.end()) { string filename = PrepBase::get_edabit_filename(prep_data_dir, diff --git a/Processor/Input.h b/Processor/Input.h index 728c81f6a..0a84a55f2 100644 --- a/Processor/Input.h +++ b/Processor/Input.h @@ -26,7 +26,7 @@ class InputBase typedef typename T::clear clear; protected: - Player* P; + PlayerBase* P; int my_num; Buffer buffer; @@ -63,7 +63,7 @@ class InputBase /// Initialize input round for ``player`` virtual void reset(int player) = 0; /// Initialize input round for all players - void reset_all(Player& P); + void reset_all(PlayerBase& P); /// Schedule input from me virtual void add_mine(const typename T::open_type& input, int n_bits = -1) = 0; diff --git a/Processor/Input.hpp b/Processor/Input.hpp index 246c9eb1d..09c6e056a 100644 --- a/Processor/Input.hpp +++ b/Processor/Input.hpp @@ -81,7 +81,7 @@ void InputBase::reset(int player) } template -void InputBase::reset_all(Player& P) +void InputBase::reset_all(PlayerBase& P) { this->P = &P; my_num = P.my_num(); diff --git a/Processor/Instruction.h b/Processor/Instruction.h index a7e1e3185..5279b2584 100644 --- a/Processor/Instruction.h +++ b/Processor/Instruction.h @@ -328,14 +328,14 @@ class BaseInstruction int opcode; // The code int size; // Vector size int r[4]; // Fixed parameter registers - unsigned int n; // Possible immediate value + size_t n; // Possible immediate value vector start; // Values for a start/stop open public: virtual ~BaseInstruction() {}; int get_r(int i) const { return r[i]; } - unsigned int get_n() const { return n; } + size_t get_n() const { return n; } const vector& get_start() const { return start; } int get_opcode() const { return opcode; } int get_size() const { return size; } @@ -350,7 +350,7 @@ class BaseInstruction bool is_direct_memory_access() const; // Returns the memory size used if applicable and known - unsigned get_mem(RegType reg_type) const; + size_t get_mem(RegType reg_type) const; // Returns the maximal register used unsigned get_max_reg(int reg_type) const; diff --git a/Processor/Instruction.hpp b/Processor/Instruction.hpp index 1bc46f94f..2a5dce70c 100644 --- a/Processor/Instruction.hpp +++ b/Processor/Instruction.hpp @@ -218,24 +218,10 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos) // instructions with 1 register + 1 integer operand case LDI: case LDSI: - case LDMC: - case LDMS: - case STMC: - case STMS: - case LDMSB: - case STMSB: - case LDMCB: - case STMCB: - case LDMINT: - case STMINT: case JMPNZ: case JMPEQZ: case GLDI: case GLDSI: - case GLDMC: - case GLDMS: - case GSTMC: - case GSTMS: case PRINTREG: case PRINTREGB: case GPRINTREG: @@ -247,6 +233,24 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos) r[0]=get_int(s); n = get_int(s); break; + // instructions with 1 register + 1 long operand + case LDMC: + case LDMS: + case STMC: + case STMS: + case LDMSB: + case STMSB: + case LDMCB: + case STMCB: + case LDMINT: + case STMINT: + case GLDMC: + case GLDMS: + case GSTMC: + case GSTMS: + r[0] = get_int(s); + n = get_long(s); + break; // instructions with 1 integer operand case PRINTSTR: case PRINTCHR: @@ -783,7 +787,7 @@ unsigned BaseInstruction::get_max_reg(int reg_type) const } inline -unsigned BaseInstruction::get_mem(RegType reg_type) const +size_t BaseInstruction::get_mem(RegType reg_type) const { if (get_reg_type() == reg_type and is_direct_memory_access()) return n + size; @@ -843,7 +847,7 @@ inline void Instruction::execute(Processor& Proc) const } int r[3] = {this->r[0], this->r[1], this->r[2]}; - int n = this->n; + int64_t n = this->n; for (int i = 0; i < size; i++) { switch (opcode) { @@ -1065,7 +1069,7 @@ inline void Instruction::execute(Processor& Proc) const case PRINTREG: { Proc.out << "Reg[" << r[0] << "] = " << Proc.read_Cp(r[0]) - << " # " << string((char*)&n,sizeof(n)) << endl; + << " # " << string((char*)&n, 4) << endl; } break; case PRINTREGPLAIN: @@ -1085,7 +1089,7 @@ inline void Instruction::execute(Processor& Proc) const case CONDPRINTSTR: if (not Proc.read_Cp(r[0]).is_zero()) { - string str = {(char*)&n, sizeof(n)}; + string str = {(char*)&n, 4}; size_t n = str.find('\0'); if (n < 4) str.erase(n); @@ -1313,7 +1317,7 @@ void Instruction::print(SwitchableOutput& out, T* v, T* p, T* s, T* z, T* nan) c out << "["; for (int i = 0; i < size; i++) { - if (p == 0) + if (p == 0 or (*p == 0 and s == 0)) out << v[i]; else if (s == 0) out << bigint::get_float(v[i], p[i], {}, {}); diff --git a/Processor/Machine.h b/Processor/Machine.h index 331a9a22c..8b3d018cc 100644 --- a/Processor/Machine.h +++ b/Processor/Machine.h @@ -46,6 +46,8 @@ class Machine : public BaseMachine void load_program(const string& threadname, const string& filename); + void prepare(const string& progname_str); + void suggest_optimizations(); public: @@ -71,10 +73,10 @@ class Machine : public BaseMachine ExecutionStats stats; - Machine(int my_number, Names& playerNames, const string& progname, - const string& memtype, int lg2, bool direct, int opening_sum, - bool receive_threads, int max_broadcast, bool use_encryption, bool live_prep, - OnlineOptions opts); + static void init_binary_domains(int security_parameter, int lg2); + + Machine(Names& playerNames, bool use_encryption = true, + const OnlineOptions opts = sint(), int lg2 = 0); ~Machine(); const Names& get_N() { return N; } @@ -92,7 +94,11 @@ class Machine : public BaseMachine DataPositions run_tape(int thread_number, int tape_number, int arg, const DataPositions& pos); DataPositions join_tape(int thread_number); - void run(); + + void run(const string& progname); + + void run_step(const string& progname); + pair stop_threads(); string memory_filename(); @@ -102,6 +108,9 @@ class Machine : public BaseMachine void reqbl(int n); typename sint::bit_type::mac_key_type get_bit_mac_key() { return alphabi; } + typename sint::mac_key_type get_sint_mac_key() { return alphapi; } + + Player& get_player() { return *P; } }; #endif /* MACHINE_H_ */ diff --git a/Processor/Machine.hpp b/Processor/Machine.hpp index e720b2a99..e0299c2f3 100644 --- a/Processor/Machine.hpp +++ b/Processor/Machine.hpp @@ -24,28 +24,52 @@ using namespace std; template -Machine::Machine(int my_number, Names& playerNames, - const string& progname_str, const string& memtype, - int lg2, bool direct, - int opening_sum, bool receive_threads, int max_broadcast, - bool use_encryption, bool live_prep, OnlineOptions opts) - : my_number(my_number), N(playerNames), - direct(direct), opening_sum(opening_sum), - receive_threads(receive_threads), max_broadcast(max_broadcast), - use_encryption(use_encryption), live_prep(live_prep), opts(opts) +void Machine::init_binary_domains(int security_parameter, int lg2) { + sgf2n::clear::init_field(lg2); + + if (not is_same()) + { + if (sgf2n::clear::degree() < security_parameter) + { + cerr << "Security parameter needs to be at most n in GF(2^n)." + << endl; + cerr << "Increase the latter (-lg2) or decrease the former (-S)." + << endl; + exit(1); + } + } + + if (not is_same()) + { + sint::bit_type::mac_key_type::init_minimum(security_parameter); + } + else + { + // Initialize field for CCD + sint::bit_type::part_type::open_type::init_field(); + } +} + +template +Machine::Machine(Names& playerNames, bool use_encryption, + const OnlineOptions opts, int lg2) + : my_number(playerNames.my_num()), N(playerNames), + direct(opts.direct), opening_sum(opts.opening_sum), + receive_threads(opts.receive_threads), max_broadcast(opts.max_broadcast), + use_encryption(use_encryption), live_prep(opts.live_prep), opts(opts) +{ + OnlineOptions::singleton = opts; + if (opening_sum < 2) this->opening_sum = N.num_players(); if (max_broadcast < 2) this->max_broadcast = N.num_players(); // Set up the fields - sgf2n::clear::init_field(lg2); sint::clear::read_or_generate_setup(prep_dir_prefix(), opts); - sint::bit_type::mac_key_type::init_field(); - // Initialize gf2n_short for CCD - sint::bit_type::part_type::open_type::init_field(); + init_binary_domains(opts.security_parameter, lg2); // make directory for outputs if necessary mkdir_p(PREP_DIR); @@ -75,6 +99,7 @@ Machine::Machine(int my_number, Names& playerNames, sint::clear::next::template init(false); // Initialize the global memory + auto memtype = opts.memtype; if (memtype.compare("old")==0) { ifstream inpf; @@ -92,9 +117,18 @@ Machine::Machine(int my_number, Names& playerNames, { cerr << "Invalid memory argument" << endl; exit(1); } +} +template +void Machine::prepare(const string& progname_str) +{ + int old_n_threads = nthreads; + progs.clear(); load_schedule(progname_str); + // keep preprocessing + nthreads = max(old_n_threads, nthreads); + // initialize persistence if necessary for (auto& prog : progs) { @@ -122,7 +156,7 @@ Machine::Machine(int my_number, Names& playerNames, if (live_prep and (sint::needs_ot or sgf2n::needs_ot or sint::bit_type::needs_ot)) { - for (int i = 0; i < nthreads; i++) + for (int i = old_n_threads; i < nthreads; i++) ot_setups.push_back({ *P, true }); } @@ -132,7 +166,7 @@ Machine::Machine(int my_number, Names& playerNames, queues.resize(nthreads); join_timer.resize(nthreads); - for (int i=0; i::Machine(int my_number, Names& playerNames, } // synchronize with clients before starting timer - for (int i=0; iresult(); } @@ -155,6 +189,9 @@ Machine::Machine(int my_number, Names& playerNames, template Machine::~Machine() { + sint::LivePrep::teardown(); + sgf2n::LivePrep::teardown(); + delete P; for (auto& queue : queues) delete queue; @@ -308,14 +345,12 @@ DataPositions Machine::run_tape(int thread_number, int tape_number, //printf("Running line %d\n",exec); if (progs[tape_number].usage_unknown()) { -#ifndef INSECURE if (not opts.live_prep and thread_number != 0) { - cerr << "Internally called tape " << tape_number << - " has unknown offline data usage" << endl; - throw invalid_program(); + insecure( + "Internally called tape " + to_string(tape_number) + + " has unknown offline data usage"); } -#endif return DataPositions(N.num_players()); } else @@ -336,23 +371,20 @@ DataPositions Machine::join_tape(int i) } template -void Machine::run() +void Machine::run_step(const string& progname) { - Timer proc_timer(CLOCK_PROCESS_CPUTIME_ID); - proc_timer.start(); - timer[0].start({}); - - // run main tape + prepare(progname); run_tape(0, 0, 0, N.num_players()); join_tape(0); +} - print_compiler(); - - finish_timer.start(); +template +pair Machine::stop_threads() +{ // Tell all C-threads to stop for (int i=0; ischedule(-1); } @@ -369,6 +401,40 @@ void Machine::run() pos.increase(queues[i]->result().pos); pthread_join(threads[i],NULL); } + + auto comm_stats = total_comm(); + + for (auto& queue : queues) + delete queue; + + queues.clear(); + + nthreads = 0; + + return {pos, comm_stats}; +} + +template +void Machine::run(const string& progname) +{ + prepare(progname); + + Timer proc_timer(CLOCK_PROCESS_CPUTIME_ID); + proc_timer.start(); + timer[0].start({}); + + // run main tape + run_tape(0, 0, 0, N.num_players()); + join_tape(0); + + print_compiler(); + + finish_timer.start(); + + // actual usage + auto res = stop_threads(); + DataPositions& pos = res.first; + finish_timer.stop(); #ifdef VERBOSE @@ -387,7 +453,7 @@ void Machine::run() cerr << "Finish timer: " << finish_timer.elapsed() << endl; #endif - NamedCommStats comm_stats = total_comm(); + NamedCommStats& comm_stats = res.second; if (opts.verbose) { @@ -475,17 +541,12 @@ void Machine::run() stats.print(); } -#ifndef INSECURE if (not opts.file_prep_per_thread) { Data_Files df(*this); df.seekg(pos); df.prune(); } -#endif - - sint::LivePrep::teardown(); - sgf2n::LivePrep::teardown(); suggest_optimizations(); diff --git a/Processor/OfflineMachine.hpp b/Processor/OfflineMachine.hpp index 6e0bb525d..b04ea6a15 100644 --- a/Processor/OfflineMachine.hpp +++ b/Processor/OfflineMachine.hpp @@ -37,13 +37,16 @@ template int OfflineMachine::run() { T::clear::init_default(this->online_opts.prime_length()); - U::clear::init_field(U::clear::default_degree()); - T::bit_type::mac_key_type::init_field(); + Machine::init_binary_domains(this->online_opts.security_parameter, + this->lg2); auto binary_mac_key = read_generate_write_mac_key< typename T::bit_type::part_type>(P); typename T::bit_type::LivePrep bit_prep(usage); GC::ShareThread thread(bit_prep, P, binary_mac_key); + // setup before generation to fix prime + T::LivePrep::basic_setup(P); + generate(); generate(); generate(); diff --git a/Processor/Online-Thread.hpp b/Processor/Online-Thread.hpp index e98f1a3a1..b0c5e5795 100644 --- a/Processor/Online-Thread.hpp +++ b/Processor/Online-Thread.hpp @@ -100,6 +100,9 @@ void thread_info::Sub_Main_Func() processor = new Processor(tinfo->thread_num,P,*MC2,*MCp,machine,progs.at(thread_num > 0)); auto& Proc = *processor; + // don't count communication for initialization + P.reset_stats(); + bool flag=true; int program=-3; // int exec=0; @@ -287,10 +290,8 @@ void thread_info::Sub_Main_Func() // final check Proc.check(); -#ifndef INSECURE if (machine.opts.file_prep_per_thread) Proc.DataF.prune(); -#endif wait_timer.start(); queues->next(); diff --git a/Processor/OnlineMachine.h b/Processor/OnlineMachine.h index 9804828eb..68e38e379 100644 --- a/Processor/OnlineMachine.h +++ b/Processor/OnlineMachine.h @@ -17,11 +17,11 @@ class OnlineMachine const char** argv; OnlineOptions& online_opts; - int lg2, opening_sum, max_broadcast; + int lg2; Names playerNames; - bool use_encryption, receive_threads; + bool use_encryption; ez::ezOptionParser& opt; diff --git a/Processor/OnlineMachine.hpp b/Processor/OnlineMachine.hpp index 4e944d624..d4c66e9aa 100644 --- a/Processor/OnlineMachine.hpp +++ b/Processor/OnlineMachine.hpp @@ -18,7 +18,7 @@ template int spdz_main(int argc, const char** argv, ez::ezOptionParser& opt, bool live_prep_default = true) { OnlineOptions& online_opts = OnlineOptions::singleton; - online_opts = {opt, argc, argv, 1000, live_prep_default, T::clear::invertible}; + online_opts = {opt, argc, argv, T(), live_prep_default}; DishonestMajorityMachine machine(argc, argv, opt, online_opts, typename U::clear()); return machine.run(); @@ -28,8 +28,7 @@ template OnlineMachine::OnlineMachine(int argc, const char** argv, ez::ezOptionParser& opt, OnlineOptions& online_opts, int nplayers, V) : argc(argc), argv(argv), online_opts(online_opts), lg2(0), - opening_sum(0), max_broadcast(0), - use_encryption(false), receive_threads(false), + use_encryption(false), opt(opt), nplayers(nplayers) { opt.add( @@ -125,33 +124,6 @@ DishonestMajorityMachine::DishonestMajorityMachine(int argc, const char** argv, opt.example = string() + argv[0] + " -p 0 -N 2 sample-prog\n" + argv[0] + " -h localhost -p 1 -N 2 sample-prog\n"; - opt.add( - "0", // Default. - 0, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Sum at most n shares at once when using indirect communication", // Help description. - "-s", // Flag token. - "--opening-sum" // Flag token. - ); - opt.add( - "", // Default. - 0, // Required? - 0, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Use player-specific threads for communication", // Help description. - "-t", // Flag token. - "--threads" // Flag token. - ); - opt.add( - "0", // Default. - 0, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Maximum number of parties to send to at once", // Help description. - "-mb", // Flag token. - "--max-broadcast" // Flag token. - ); opt.add( "", // Default. 0, // Required? @@ -163,11 +135,7 @@ DishonestMajorityMachine::DishonestMajorityMachine(int argc, const char** argv, ); online_opts.finalize(opt, argc, argv); - opt.get("--opening-sum")->getInt(opening_sum); - opt.get("--max-broadcast")->getInt(max_broadcast); - use_encryption = opt.isSet("--encrypted"); - receive_threads = opt.isSet("--threads"); start_networking(); } @@ -230,12 +198,8 @@ int OnlineMachine::run() try #endif { - Machine(online_opts.playerno, playerNames, online_opts.progname, - online_opts.memtype, lg2, - online_opts.direct, opening_sum, - receive_threads, max_broadcast, - use_encryption, online_opts.live_prep, - online_opts).run(); + Machine(playerNames, use_encryption, online_opts, lg2).run( + online_opts.progname); if (online_opts.verbose) { diff --git a/Processor/OnlineOptions.cpp b/Processor/OnlineOptions.cpp index 2a5e090bd..d404f642d 100644 --- a/Processor/OnlineOptions.cpp +++ b/Processor/OnlineOptions.cpp @@ -8,6 +8,7 @@ #include "Math/gfp.h" #include "Math/gfpvar.h" #include "Protocols/HemiOptions.h" +#include "Protocols/config.h" #include "Math/gfp.hpp" @@ -26,10 +27,14 @@ OnlineOptions::OnlineOptions() : playerno(-1) bits_from_squares = false; direct = false; bucket_size = 4; + security_parameter = DEFAULT_SECURITY; cmd_private_input_file = "Player-Data/Input"; cmd_private_output_file = ""; file_prep_per_thread = false; - trunc_error = 40; + trunc_error = DEFAULT_SECURITY; + opening_sum = 0; + max_broadcast = 0; + receive_threads = false; #ifdef VERBOSE verbose = true; #else @@ -38,7 +43,7 @@ OnlineOptions::OnlineOptions() : playerno(-1) } OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc, - const char** argv, false_type) : + const char** argv, bool security) : OnlineOptions() { opt.syntax = std::string(argv[0]) + " [OPTIONS] [] "; @@ -104,6 +109,18 @@ OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc, "--bucket-size" // Flag token. ); + if (security) + opt.add( + to_string(security_parameter).c_str(), // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + ("Security parameter (default: " + to_string(security_parameter) + + ")").c_str(), // Help description. + "-S", // Flag token. + "--security" // Flag token. + ); + opt.parse(argc, argv); interactive = opt.isSet("-I"); @@ -117,13 +134,24 @@ OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc, verbose = opt.isSet("--verbose"); #endif + if (security) + { + opt.get("-S")->getInt(security_parameter); + cerr << "Using security parameter " << security_parameter << endl; + if (security_parameter <= 0) + { + cerr << "Invalid security parameter: " << security_parameter << endl; + exit(1); + } + } + opt.resetArgs(); } OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv, int default_batch_size, bool default_live_prep, - bool variable_prime_length) : - OnlineOptions(opt, argc, argv, false_type()) + bool variable_prime_length, bool security) : + OnlineOptions(opt, argc, argv, security) { if (default_batch_size <= 0) default_batch_size = batch_size; @@ -263,6 +291,9 @@ void OnlineOptions::finalize(ez::ezOptionParser& opt, int argc, vector badOptions; unsigned int i; + opt.footer += "\nSee also https://mp-spdz.readthedocs.io/en/latest/networking.html " + "for documentation on the networking setup.\n"; + if (allArgs.size() != 3u - opt.isSet("-p")) { cerr << "ERROR: incorrect number of arguments to " << argv[0] << endl; @@ -329,6 +360,16 @@ void OnlineOptions::finalize(ez::ezOptionParser& opt, int argc, } set_trunc_error(opt); + + auto o = opt.get("--opening-sum"); + if (o) + o->getInt(opening_sum); + + o = opt.get("--max-broadcast"); + if (o) + o->getInt(max_broadcast); + + receive_threads = opt.isSet("--threads"); } void OnlineOptions::set_trunc_error(ez::ezOptionParser& opt) diff --git a/Processor/OnlineOptions.h b/Processor/OnlineOptions.h index 4b2fe4f8c..61c1352bc 100644 --- a/Processor/OnlineOptions.h +++ b/Processor/OnlineOptions.h @@ -26,21 +26,26 @@ class OnlineOptions bool bits_from_squares; bool direct; int bucket_size; + int security_parameter; std::string cmd_private_input_file; std::string cmd_private_output_file; bool verbose; bool file_prep_per_thread; int trunc_error; + int opening_sum, max_broadcast; + bool receive_threads; OnlineOptions(); OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv, - false_type); + bool security); OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv, int default_batch_size = 0, bool default_live_prep = true, - bool variable_prime_length = false); + bool variable_prime_length = false, bool security = true); template OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv, T, bool default_live_prep = true); + template + OnlineOptions(T); ~OnlineOptions() {} void finalize(ez::ezOptionParser& opt, int argc, const char** argv); diff --git a/Processor/OnlineOptions.hpp b/Processor/OnlineOptions.hpp index 8961853e5..d8b71cea6 100644 --- a/Processor/OnlineOptions.hpp +++ b/Processor/OnlineOptions.hpp @@ -20,11 +20,49 @@ OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc, 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. - "Probabilistic truncation error " - "(2^-x, default: 40)", // Help description. + ("Probabilistic truncation error (2^-x, default: " + + to_string(trunc_error) + ")").c_str(), // Help description. "-E", // Flag token. "--trunc-error" // Flag token. ); + + if (T::dishonest_majority) + { + opt.add( + "0", // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Sum at most n shares at once when using indirect communication", // Help description. + "-s", // Flag token. + "--opening-sum" // Flag token. + ); + opt.add( + "", // Default. + 0, // Required? + 0, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Use player-specific threads for communication", // Help description. + "-t", // Flag token. + "--threads" // Flag token. + ); + opt.add( + "0", // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Maximum number of parties to send to at once", // Help description. + "-mb", // Flag token. + "--max-broadcast" // Flag token. + ); + } +} + +template +OnlineOptions::OnlineOptions(T) : OnlineOptions() +{ + if (T::dishonest_majority) + batch_size = 1000; } #endif /* PROCESSOR_ONLINEOPTIONS_HPP_ */ diff --git a/Processor/Program.h b/Processor/Program.h index 87a263f08..8fb3df141 100644 --- a/Processor/Program.h +++ b/Processor/Program.h @@ -21,7 +21,7 @@ class Program unsigned max_reg[MAX_REG_TYPE]; // Memory size used directly - unsigned max_mem[MAX_REG_TYPE]; + size_t max_mem[MAX_REG_TYPE]; // True if program contains variable-sized loop bool unknown_usage; @@ -48,7 +48,7 @@ class Program unsigned num_reg(RegType reg_type) const { return max_reg[reg_type]; } - unsigned direct_mem(RegType reg_type) const + size_t direct_mem(RegType reg_type) const { return max_mem[reg_type]; } friend ostream& operator<<(ostream& s,const Program& P); diff --git a/Processor/RingMachine.hpp b/Processor/RingMachine.hpp index f2bfc6c1b..626942212 100644 --- a/Processor/RingMachine.hpp +++ b/Processor/RingMachine.hpp @@ -65,7 +65,7 @@ HonestMajorityRingMachineWithSecurity::HonestMajorityRingMachineWithSecuri int argc, const char** argv, ez::ezOptionParser& opt) { OnlineOptions online_opts(opt, argc, argv); - RingOptions opts(opt, argc, argv, true); + RingOptions opts(opt, argc, argv); HonestMajorityMachine machine(argc, argv, opt, online_opts); int R = opts.ring_size_from_opts_or_schedule(online_opts.progname); switch (R) @@ -76,15 +76,19 @@ HonestMajorityRingMachineWithSecurity::HonestMajorityRingMachineWithSecuri break; #define X(K) \ case K: \ - switch (opts.S) \ + { \ + int S = online_opts.security_parameter; \ + switch (S) \ { \ - Y(K, 40) \ + Y(K, DEFAULT_SECURITY) \ default: \ - cerr << "not compiled for security parameter " << to_string(opts.S) << endl; \ - cerr << "add 'Y(K, " << opts.S << ")' to " __FILE__ ", line 76" << endl; \ + cerr << "not compiled for security parameter " << to_string(S) << endl; \ + cerr << "add 'Y(K, " << S << ")' to " __FILE__ ", line 76" << endl; \ + cerr << "or compile with -DDEFAULT_SECURITY=" << S << endl; \ exit(1); \ } \ - break; + break; \ + } X(64) #ifdef RING_SIZE X(RING_SIZE) diff --git a/Processor/RingOptions.cpp b/Processor/RingOptions.cpp index d59a709a8..ec9e9f066 100644 --- a/Processor/RingOptions.cpp +++ b/Processor/RingOptions.cpp @@ -9,8 +9,7 @@ #include using namespace std; -RingOptions::RingOptions(ez::ezOptionParser& opt, int argc, const char** argv, - bool security) +RingOptions::RingOptions(ez::ezOptionParser& opt, int argc, const char** argv) { opt.add( "64", // Default. @@ -21,28 +20,12 @@ RingOptions::RingOptions(ez::ezOptionParser& opt, int argc, const char** argv, "-R", // Flag token. "--ring" // Flag token. ); - if (security) - opt.add( - "40", // Default. - 0, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Security parameter (default: 40)", // Help description. - "-S", // Flag token. - "--security" // Flag token. - ); opt.parse(argc, argv); opt.get("-R")->getInt(R); - if (security) - opt.get("-S")->getInt(S); - else - S = -1; R_is_set = opt.isSet("-R"); opt.resetArgs(); if (R_is_set) cerr << "Trying to run " << R << "-bit computation" << endl; - if (security) - cerr << "Using security parameter " << S << endl; } int RingOptions::ring_size_from_opts_or_schedule(string progname) diff --git a/Processor/RingOptions.h b/Processor/RingOptions.h index 899c7021a..8f5361f60 100644 --- a/Processor/RingOptions.h +++ b/Processor/RingOptions.h @@ -16,10 +16,8 @@ class RingOptions public: int R; - int S; - RingOptions(ez::ezOptionParser& opt, int argc, const char** argv, - bool security = false); + RingOptions(ez::ezOptionParser& opt, int argc, const char** argv); int ring_size_from_opts_or_schedule(string progname); }; diff --git a/Processor/instructions.h b/Processor/instructions.h index 5928fdabc..bf443b0f7 100644 --- a/Processor/instructions.h +++ b/Processor/instructions.h @@ -203,7 +203,7 @@ *dest++ = *op1++ == *op2++) \ X(PRINTINT, Proc.out << Proc.read_Ci(r[0]) << flush,) \ X(PRINTFLOATPREC, Proc.out << setprecision(n),) \ - X(PRINTSTR, Proc.out << string((char*)&n,sizeof(n)) << flush,) \ + X(PRINTSTR, Proc.out << string((char*)&n,4) << flush,) \ X(PRINTCHR, Proc.out << string((char*)&n,1) << flush,) \ X(SHUFFLE, shuffle(Proc),) \ X(BITDECINT, bitdecint(Proc),) \ @@ -270,7 +270,7 @@ *dest++ = *op1++ >> n) \ X(GPRINTREG, auto source = &C2[r[0]], \ Proc.out << "Reg[" << r[0] << "] = " << *source++ \ - << " # " << string((char*)&n,sizeof(n)) << endl) \ + << " # " << string((char*)&n, 4) << endl) \ X(GPRINTREGPLAIN, auto source = &C2[r[0]], \ Proc.out << *source++ << flush) \ X(GBITDEC, gbitdec(C2),) \ diff --git a/Programs/Source/l2h_comparison.mpc b/Programs/Source/l2h_comparison.mpc new file mode 100644 index 000000000..c233caa77 --- /dev/null +++ b/Programs/Source/l2h_comparison.mpc @@ -0,0 +1,3 @@ +res = sint.load_mem(0) < sint.load_mem(1) +res.store_in_mem(3) +print_ln('comparison in VM: %s', res.reveal()) diff --git a/Programs/Source/l2h_multiplication.mpc b/Programs/Source/l2h_multiplication.mpc new file mode 100644 index 000000000..aecbca651 --- /dev/null +++ b/Programs/Source/l2h_multiplication.mpc @@ -0,0 +1 @@ +(sint.load_mem(0) * sint.load_mem(1)).store_in_mem(2) diff --git a/Protocols/Beaver.h b/Protocols/Beaver.h index 2d28127c7..9b695d0d1 100644 --- a/Protocols/Beaver.h +++ b/Protocols/Beaver.h @@ -23,6 +23,7 @@ class Player; template class Beaver : public ProtocolBase { +protected: vector shares; vector opened; vector> triples; diff --git a/Protocols/ChaiGearPrep.hpp b/Protocols/ChaiGearPrep.hpp index 69b16fcf2..076931787 100644 --- a/Protocols/ChaiGearPrep.hpp +++ b/Protocols/ChaiGearPrep.hpp @@ -43,15 +43,16 @@ void ChaiGearPrep::basic_setup(Player& P) assert(machine == 0); machine = new MultiplicativeMachine; auto& setup = machine->setup.part(); - auto& options = CowGearOptions::singleton; + int lowgear_security = OnlineOptions::singleton.security_parameter; #ifdef VERBOSE + auto& options = CowGearOptions::singleton; cerr << "Covert security parameter for key and MAC generation: " << options.covert_security << endl; cerr << "Triple generation security parameter: " - << options.lowgear_security << endl; + << lowgear_security << endl; #endif - machine->sec = options.lowgear_security; - setup.secure_init(P, *machine, T::clear::length(), options.lowgear_security); + machine->sec = lowgear_security; + setup.secure_init(P, *machine, T::clear::length(), lowgear_security); T::clear::template init(); #ifdef VERBOSE cerr << T::type_string() << " parameter setup took " << timer.elapsed() diff --git a/Protocols/CowGearOptions.cpp b/Protocols/CowGearOptions.cpp index 9212a7e06..e018dd8bd 100644 --- a/Protocols/CowGearOptions.cpp +++ b/Protocols/CowGearOptions.cpp @@ -23,7 +23,6 @@ CowGearOptions::CowGearOptions(bool covert) covert_security = -1; } - lowgear_security = 40; use_top_gear = false; } @@ -49,7 +48,7 @@ CowGearOptions::CowGearOptions(ez::ezOptionParser& opt, int argc, 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. - "LowGear security parameter (default: 40)", // Help description. + "DEPRECATED: use -S/--security", // Help description. "-l", // Flag token. "--lowgear-security" // Flag token. ); @@ -76,15 +75,8 @@ CowGearOptions::CowGearOptions(ez::ezOptionParser& opt, int argc, opt.get("-c")->getInt(covert_security); if (opt.isSet("-l")) { - opt.get("-l")->getInt(lowgear_security); - if (lowgear_security <= 0) - { - throw exception(); - cerr << "Invalid LowGear Security parameter: " << lowgear_security << endl; - exit(1); - } - if (covert_security > (1LL << lowgear_security)) - insecure(", LowGear security less than key generation security"); + cerr << "Deprecated parameter, use -S/--security" << endl; + exit(1); } use_top_gear = not opt.isSet("-J"); if (opt.isSet("-T")) diff --git a/Protocols/CowGearOptions.h b/Protocols/CowGearOptions.h index f79bd5212..af9006dcc 100644 --- a/Protocols/CowGearOptions.h +++ b/Protocols/CowGearOptions.h @@ -16,7 +16,6 @@ class CowGearOptions static CowGearOptions singleton; int covert_security; - int lowgear_security; CowGearOptions(bool covert = true); CowGearOptions(ez::ezOptionParser& opt, int argc, const char** argv, diff --git a/Protocols/CowGearPrep.hpp b/Protocols/CowGearPrep.hpp index 3b9daae1e..36b36d663 100644 --- a/Protocols/CowGearPrep.hpp +++ b/Protocols/CowGearPrep.hpp @@ -38,14 +38,15 @@ void CowGearPrep::basic_setup(Player& P) pairwise_machine = new PairwiseMachine(P); auto& machine = *pairwise_machine; auto& setup = machine.setup(); - auto& options = CowGearOptions::singleton; + int lowgear_security = OnlineOptions::singleton.security_parameter; #ifdef VERBOSE + auto& options = CowGearOptions::singleton; if (T::covert) cerr << "Covert security parameter for key and MAC generation: " << options.covert_security << endl; - cerr << "LowGear security parameter: " << options.lowgear_security << endl; + cerr << "LowGear security parameter: " << lowgear_security << endl; #endif - setup.secure_init(P, machine, T::clear::length(), options.lowgear_security); + setup.secure_init(P, machine, T::clear::length(), lowgear_security); T::clear::template init(); #ifdef VERBOSE cerr << T::type_string() << " parameter setup took " << timer.elapsed() diff --git a/Protocols/DabitSacrifice.h b/Protocols/DabitSacrifice.h index 3b436547d..6da8cc238 100644 --- a/Protocols/DabitSacrifice.h +++ b/Protocols/DabitSacrifice.h @@ -9,10 +9,12 @@ template class DabitSacrifice { - static const int S = 40; + const int S; public: - static int minimum_n_inputs(int n_outputs = 0) + DabitSacrifice(); + + int minimum_n_inputs(int n_outputs = 0) { if (n_outputs < 1) n_outputs = OnlineOptions::singleton.batch_size; diff --git a/Protocols/DabitSacrifice.hpp b/Protocols/DabitSacrifice.hpp index aa2abf615..74d9f0267 100644 --- a/Protocols/DabitSacrifice.hpp +++ b/Protocols/DabitSacrifice.hpp @@ -11,6 +11,12 @@ #include +template +DabitSacrifice::DabitSacrifice() : + S(OnlineOptions::singleton.security_parameter) +{ +} + template dabit& operator+=(dabit& x, const dabit& y) { diff --git a/Protocols/DealerInput.h b/Protocols/DealerInput.h new file mode 100644 index 000000000..7d0699da4 --- /dev/null +++ b/Protocols/DealerInput.h @@ -0,0 +1,38 @@ +/* + * DealerInput.h + * + */ + +#ifndef PROTOCOLS_DEALERINPUT_H_ +#define PROTOCOLS_DEALERINPUT_H_ + +#include "../Networking/AllButLastPlayer.h" +#include "Processor/Input.h" + +template +class DealerInput : public InputBase +{ + Player& P; + octetStreams to_send, to_receive; + SeededPRNG G; + vector> shares; + bool from_dealer; + AllButLastPlayer sub_player; + SemiInput>* internal; + +public: + DealerInput(SubProcessor& proc, typename T::MAC_Check&); + DealerInput(typename T::MAC_Check&, Preprocessing&, Player& P); + DealerInput(Player& P); + ~DealerInput(); + + bool is_dealer(int player = -1); + + void reset(int player); + void add_mine(const typename T::open_type& input, int n_bits = -1); + void add_other(int player, int n_bits = -1); + void exchange(); + T finalize(int player, int n_bits = -1); +}; + +#endif /* PROTOCOLS_DEALERINPUT_H_ */ diff --git a/Protocols/DealerInput.hpp b/Protocols/DealerInput.hpp new file mode 100644 index 000000000..26bfb9a1a --- /dev/null +++ b/Protocols/DealerInput.hpp @@ -0,0 +1,115 @@ +/* + * DealerInput.hpp + * + */ + +#ifndef PROTOCOLS_DEALERINPUT_HPP_ +#define PROTOCOLS_DEALERINPUT_HPP_ + +#include "DealerInput.h" + +template +DealerInput::DealerInput(SubProcessor& proc, typename T::MAC_Check&) : + DealerInput(proc.P) +{ +} + +template +DealerInput::DealerInput(typename T::MAC_Check&, Preprocessing&, + Player& P) : + DealerInput(P) +{ +} + +template +DealerInput::DealerInput(Player& P) : + P(P), to_send(P), shares(P.num_players()), from_dealer(false), + sub_player(P) +{ + if (is_dealer()) + internal = 0; + else + internal = new SemiInput>(0, sub_player); +} + +template +DealerInput::~DealerInput() +{ + if (internal) + delete internal; +} + +template +bool DealerInput::is_dealer(int player) +{ + int dealer_player = P.num_players() - 1; + if (player == -1) + return P.my_num() == dealer_player; + else + return player == dealer_player; +} + +template +void DealerInput::reset(int player) +{ + if (player == 0) + { + to_send.reset(P); + from_dealer = false; + } + else if (not is_dealer()) + internal->reset(player - 1); +} + +template +void DealerInput::add_mine(const typename T::open_type& input, + int) +{ + if (is_dealer()) + { + make_share(shares.data(), input, P.num_players() - 1, 0, G); + for (int i = 1; i < P.num_players(); i++) + shares.at(i - 1).pack(to_send[i]); + from_dealer = true; + } + else + internal->add_mine(input); +} + +template +void DealerInput::add_other(int player, int) +{ + if (is_dealer(player)) + from_dealer = true; + else if (not is_dealer()) + internal->add_other(player); +} + +template +void DealerInput::exchange() +{ + if (from_dealer) + { + vector senders(P.num_players()); + senders.back() = true; + P.send_receive_all(senders, to_send, to_receive); + } + else if (not is_dealer()) + internal->exchange(); +} + +template +T DealerInput::finalize(int player, int) +{ + if (is_dealer()) + return {}; + else + { + if (is_dealer(player)) + return to_receive.back().template get(); + else + return internal->finalize(player); + } +} + +#endif /* PROTOCOLS_DEALERINPUT_HPP_ */ diff --git a/Protocols/DealerMC.h b/Protocols/DealerMC.h new file mode 100644 index 000000000..5311f8132 --- /dev/null +++ b/Protocols/DealerMC.h @@ -0,0 +1,42 @@ +/* + * DealerMC.h + * + */ + +#ifndef PROTOCOLS_DEALERMC_H_ +#define PROTOCOLS_DEALERMC_H_ + +#include "MAC_Check_Base.h" +#include "Networking/AllButLastPlayer.h" + +template +class DealerMC : public MAC_Check_Base +{ + typedef SemiMC> internal_type; + internal_type& internal; + AllButLastPlayer* sub_player; + +public: + DealerMC(typename T::mac_key_type = {}, int = 0, int = 0); + DealerMC(internal_type& internal); + ~DealerMC(); + + void init_open(const Player& P, int n = 0); + void prepare_open(const T& secret); + void exchange(const Player& P); + typename T::open_type finalize_raw(); + + DealerMC& get_part_MC() + { + return *this; + } +}; + +template +class DirectDealerMC : public DealerMC +{ +public: + DirectDealerMC(typename T::mac_key_type = {}); +}; + +#endif /* PROTOCOLS_DEALERMC_H_ */ diff --git a/Protocols/DealerMC.hpp b/Protocols/DealerMC.hpp new file mode 100644 index 000000000..a9ddc035c --- /dev/null +++ b/Protocols/DealerMC.hpp @@ -0,0 +1,76 @@ +/* + * DealerMC.hpp + * + */ + +#ifndef PROTOCOLS_DEALERMC_HPP_ +#define PROTOCOLS_DEALERMC_HPP_ + +#include "DealerMC.h" + +template +DealerMC::DealerMC(typename T::mac_key_type, int, int) : + DealerMC(*(new internal_type)) +{ +} + +template +DirectDealerMC::DirectDealerMC(typename T::mac_key_type) : + DealerMC(*(new DirectSemiMC>)) +{ +} + +template +DealerMC::DealerMC(internal_type& internal) : + internal(internal), sub_player(0) +{ +} + +template +DealerMC::~DealerMC() +{ + delete &internal; + if (sub_player) + delete sub_player; +} + +template +void DealerMC::init_open(const Player& P, int n) +{ + if (P.my_num() != P.num_players() - 1) + { + if (not sub_player) + sub_player = new AllButLastPlayer(P); + internal.init_open(P, n); + } +} + +template +void DealerMC::prepare_open(const T& secret) +{ + if (sub_player) + internal.prepare_open(secret); + else + { + if (secret != T()) + throw runtime_error("share for dealer should be 0"); + } +} + +template +void DealerMC::exchange(const Player&) +{ + if (sub_player) + internal.exchange(*sub_player); +} + +template +typename T::open_type DealerMC::finalize_raw() +{ + if (sub_player) + return internal.finalize_raw(); + else + return {}; +} + +#endif /* PROTOCOLS_DEALERMC_HPP_ */ diff --git a/Protocols/DealerPrep.h b/Protocols/DealerPrep.h new file mode 100644 index 000000000..ae28ec691 --- /dev/null +++ b/Protocols/DealerPrep.h @@ -0,0 +1,33 @@ +/* + * DealerPrep.h + * + */ + +#ifndef PROTOCOLS_DEALERPREP_H_ +#define PROTOCOLS_DEALERPREP_H_ + +#include "ReplicatedPrep.h" + +template +class DealerPrep : virtual public BitPrep +{ + template + void buffer_edabits(int n_bits, true_type); + template + void buffer_edabits(int n_bits, false_type); + +public: + DealerPrep(SubProcessor* proc, DataPositions& usage) : + BufferPrep(usage), BitPrep(proc, usage) + { + } + + void buffer_triples(); + void buffer_bits(); + + void buffer_dabits(ThreadQueues* = 0); + void buffer_edabits(int n_bits, ThreadQueues*); + void buffer_sedabits(int n_bits, ThreadQueues*); +}; + +#endif /* PROTOCOLS_DEALERPREP_H_ */ diff --git a/Protocols/DealerPrep.hpp b/Protocols/DealerPrep.hpp new file mode 100644 index 000000000..d4a0a91dd --- /dev/null +++ b/Protocols/DealerPrep.hpp @@ -0,0 +1,196 @@ +/* + * DealerPrep.hpp + * + */ + +#ifndef PROTOCOLS_DEALERPREP_HPP_ +#define PROTOCOLS_DEALERPREP_HPP_ + +#include "DealerPrep.h" + +template +void DealerPrep::buffer_triples() +{ + assert(this->proc); + auto& P = this->proc->P; + vector senders(P.num_players()); + senders.back() = true; + octetStreams os(P), to_receive(P); + if (this->proc->input.is_dealer()) + { + SeededPRNG G; + vector> shares(P.num_players() - 1); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + { + T triples[3]; + for (int i = 0; i < 2; i++) + triples[i] = G.get(); + triples[2] = triples[0] * triples[1]; + for (auto& value : triples) + { + make_share(shares.data(), typename T::clear(value), + P.num_players() - 1, 0, G); + for (int i = 1; i < P.num_players(); i++) + shares.at(i - 1).pack(os[i - 1]); + } + this->triples.push_back({}); + } + P.send_receive_all(senders, os, to_receive); + } + else + { + P.send_receive_all(senders, os, to_receive); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + this->triples.push_back(to_receive.back().get>().get()); + } +} + +template +void DealerPrep::buffer_bits() +{ + assert(this->proc); + auto& P = this->proc->P; + vector senders(P.num_players()); + senders.back() = true; + octetStreams os(P), to_receive(P); + if (this->proc->input.is_dealer()) + { + SeededPRNG G; + vector> shares(P.num_players() - 1); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + { + T bit = G.get_bit(); + make_share(shares.data(), typename T::clear(bit), + P.num_players() - 1, 0, G); + for (int i = 1; i < P.num_players(); i++) + shares.at(i - 1).pack(os[i - 1]); + this->bits.push_back({}); + } + P.send_receive_all(senders, os, to_receive); + } + else + { + P.send_receive_all(senders, os, to_receive); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + this->bits.push_back(to_receive.back().get()); + } +} + +template +void DealerPrep::buffer_dabits(ThreadQueues*) +{ + assert(this->proc); + auto& P = this->proc->P; + vector senders(P.num_players()); + senders.back() = true; + octetStreams os(P), to_receive(P); + if (this->proc->input.is_dealer()) + { + SeededPRNG G; + vector> shares(P.num_players() - 1); + vector bit_shares(P.num_players() - 1); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + { + auto bit = G.get_bit(); + make_share(shares.data(), typename T::clear(bit), + P.num_players() - 1, 0, G); + make_share(bit_shares.data(), typename T::bit_type::clear(bit), + P.num_players() - 1, 0, G); + for (int i = 1; i < P.num_players(); i++) + { + shares.at(i - 1).pack(os[i - 1]); + bit_shares.at(i - 1).pack(os[i - 1]); + } + this->dabits.push_back({}); + } + P.send_receive_all(senders, os, to_receive); + } + else + { + P.send_receive_all(senders, os, to_receive); + for (int i = 0; i < OnlineOptions::singleton.batch_size; i++) + { + this->dabits.push_back({to_receive.back().get(), + to_receive.back().get()}); + } + } +} + +template +void DealerPrep::buffer_sedabits(int length, ThreadQueues*) +{ + auto& buffer = this->edabits[{false, length}]; + if (buffer.empty()) + buffer_edabits(length, 0); + this->edabits[{true, length}].push_back(buffer.back()); + buffer.pop_back(); +} + +template +void DealerPrep::buffer_edabits(int length, ThreadQueues*) +{ + buffer_edabits(length, T::clear::characteristic_two); +} + +template +template +void DealerPrep::buffer_edabits(int, true_type) +{ + throw not_implemented(); +} + +template +template +void DealerPrep::buffer_edabits(int length, false_type) +{ + assert(this->proc); + auto& P = this->proc->P; + vector senders(P.num_players()); + senders.back() = true; + octetStreams os(P), to_receive(P); + int n_vecs = OnlineOptions::singleton.batch_size / edabitvec::MAX_SIZE; + auto& buffer = this->edabits[{false, length}]; + if (this->proc->input.is_dealer()) + { + SeededPRNG G; + vector> shares(P.num_players() - 1); + vector bit_shares(P.num_players() - 1); + for (int i = 0; i < n_vecs; i++) + { + vector as; + vector bs; + plain_edabits(as, bs, length, G); + for (auto& a : as) + { + make_share(shares.data(), a, P.num_players() - 1, 0, G); + for (int i = 1; i < P.num_players(); i++) + shares.at(i - 1).pack(os[i - 1]); + } + for (auto& b : bs) + { + make_share(bit_shares.data(), b, P.num_players() - 1, 0, G); + for (int i = 1; i < P.num_players(); i++) + bit_shares.at(i - 1).pack(os[i - 1]); + } + buffer.push_back({}); + buffer.back().a.resize(edabitvec::MAX_SIZE); + buffer.back().b.resize(length); + } + P.send_receive_all(senders, os, to_receive); + } + else + { + P.send_receive_all(senders, os, to_receive); + for (int i = 0; i < n_vecs; i++) + { + buffer.push_back({}); + for (int j = 0; j < edabitvec::MAX_SIZE; j++) + buffer.back().a.push_back(to_receive.back().get()); + for (int j = 0; j < length; j++) + buffer.back().b.push_back( + to_receive.back().get()); + } + } +} + +#endif /* PROTOCOLS_DEALERPREP_HPP_ */ diff --git a/Protocols/DealerShare.h b/Protocols/DealerShare.h new file mode 100644 index 000000000..38900ff37 --- /dev/null +++ b/Protocols/DealerShare.h @@ -0,0 +1,76 @@ +/* + * DealerShare.h + * + */ + +#ifndef PROTOCOLS_DEALERSHARE_H_ +#define PROTOCOLS_DEALERSHARE_H_ + +#include "Math/Z2k.h" +#include "SemiShare.h" + +template class DealerPrep; +template class DealerInput; +template class DealerMC; +template class DirectDealerMC; + +namespace GC +{ +class DealerSecret; +} + +template +class DealerShare : public SemiShare +{ + typedef DealerShare This; + typedef SemiShare super; + +public: + typedef GC::DealerSecret bit_type; + + typedef DealerMC MAC_Check; + typedef DirectDealerMC Direct_MC; + typedef Beaver Protocol; + typedef DealerInput Input; + typedef DealerPrep LivePrep; + typedef ::PrivateOutput PrivateOutput; + + static false_type dishonest_majority; + const static bool needs_ot = false; + + static string type_short() + { + return "DD" + string(1, T::type_char()); + } + + static int threshold(int) + { + throw runtime_error("undefined threshold"); + } + + static This constant(const T& other, int my_num, + const typename super::mac_key_type& = {}, int = -1) + { + if (my_num == 1) + return other; + else + return {}; + } + + DealerShare() + { + } + + template + DealerShare(const U& other) : super(other) + { + } +}; + +template +using DealerRingShare = DealerShare>; + +template +false_type DealerShare::dishonest_majority; + +#endif /* PROTOCOLS_DEALERSHARE_H_ */ diff --git a/Protocols/FakeMC.h b/Protocols/FakeMC.h index d16dda1cf..b5876ec05 100644 --- a/Protocols/FakeMC.h +++ b/Protocols/FakeMC.h @@ -12,7 +12,7 @@ template class FakeMC : public MAC_Check_Base { public: - FakeMC(T, int = 0, int = 0) + FakeMC(typename T::mac_key_type, int = 0, int = 0) { } diff --git a/Protocols/FakeProtocol.h b/Protocols/FakeProtocol.h index fb55f0cf4..018ac3384 100644 --- a/Protocols/FakeProtocol.h +++ b/Protocols/FakeProtocol.h @@ -28,6 +28,7 @@ class FakeProtocol : public ProtocolBase vector trunc_stats; map cisc_stats; + map ltz_stats; public: Player& P; @@ -54,6 +55,8 @@ class FakeProtocol : public ProtocolBase { cerr << x.second << " " << x.first << endl; } + for (auto& x : ltz_stats) + cerr << "LTZ " << x.first << ": " << x.second << endl; } template @@ -219,6 +222,7 @@ class FakeProtocol : public ProtocolBase { for (size_t i = 0; i < args.size(); i += args[i]) { + ltz_stats[args[i + 4]] += args[i + 1]; assert(i + args[i] <= args.size()); assert(args[i] == 6); for (int j = 0; j < args[i + 1]; j++) diff --git a/Protocols/FakeShare.h b/Protocols/FakeShare.h index 569c136e6..c0a269d1a 100644 --- a/Protocols/FakeShare.h +++ b/Protocols/FakeShare.h @@ -19,7 +19,6 @@ class FakeShare : public T, public ShareInterface typedef FakeShare This; public: - typedef T mac_key_type; typedef T open_type; typedef T clear; @@ -45,7 +44,7 @@ class FakeShare : public T, public ShareInterface return 0; } - static T constant(T value, int = 0, T = 0) + static T constant(T value, int = 0, mac_key_type = {}) { return value; } diff --git a/Protocols/Hemi.h b/Protocols/Hemi.h index 8a00c793c..f43260ea1 100644 --- a/Protocols/Hemi.h +++ b/Protocols/Hemi.h @@ -16,6 +16,7 @@ template class Hemi : public Semi { map, HemiMatrixPrep*> matrix_preps; + DataPositions matrix_usage; ShareMatrix matrix_multiply(const ShareMatrix& A, const ShareMatrix& B, SubProcessor& processor); diff --git a/Protocols/Hemi.hpp b/Protocols/Hemi.hpp index 1eebd3b73..1b3d8f5ba 100644 --- a/Protocols/Hemi.hpp +++ b/Protocols/Hemi.hpp @@ -27,7 +27,8 @@ HemiMatrixPrep& Hemi::get_matrix_prep(const array& dims, if (matrix_preps.find(dims) == matrix_preps.end()) matrix_preps.insert({dims, new HemiMatrixPrep(dims[0], dims[1], dims[2], - dynamic_cast(processor.DataF))}); + dynamic_cast(processor.DataF), + matrix_usage)}); return *matrix_preps.at(dims); } diff --git a/Protocols/HemiMatrixPrep.h b/Protocols/HemiMatrixPrep.h index ea5a7211c..8038e8efc 100644 --- a/Protocols/HemiMatrixPrep.h +++ b/Protocols/HemiMatrixPrep.h @@ -22,15 +22,15 @@ class HemiMatrixPrep : public BufferPrep> int n_rows, n_inner, n_cols; bool swapped; - DataPositions* usage; LivePrep* prep; HemiMatrixPrep(const HemiMatrixPrep&) = delete; public: - HemiMatrixPrep(int n_rows, int n_inner, int n_cols, LivePrep& prep) : - super(*(usage = new DataPositions)), n_rows(n_rows), n_inner(n_inner), + HemiMatrixPrep(int n_rows, int n_inner, int n_cols, LivePrep& prep, + DataPositions& usage) : + super(usage), n_rows(n_rows), n_inner(n_inner), n_cols(n_cols), prep(&prep) { swapped = n_rows > n_cols; @@ -39,11 +39,6 @@ class HemiMatrixPrep : public BufferPrep> assert(this->n_cols >= this->n_rows); } - ~HemiMatrixPrep() - { - delete usage; - } - void set_protocol(typename ShareMatrix::Protocol&) { } diff --git a/Protocols/HemiMatrixPrep.hpp b/Protocols/HemiMatrixPrep.hpp index f42212995..b2dd92d21 100644 --- a/Protocols/HemiMatrixPrep.hpp +++ b/Protocols/HemiMatrixPrep.hpp @@ -5,6 +5,7 @@ #include "HemiMatrixPrep.h" #include "FHE/Diagonalizer.h" +#include "Tools/Bundle.h" class CipherPlainMultJob : public ThreadJob { diff --git a/Protocols/HemiPrep.hpp b/Protocols/HemiPrep.hpp index c456424e5..ce55bce75 100644 --- a/Protocols/HemiPrep.hpp +++ b/Protocols/HemiPrep.hpp @@ -30,7 +30,9 @@ void HemiPrep::basic_setup(Player& P) pairwise_machine = new PairwiseMachine(P); auto& machine = *pairwise_machine; auto& setup = machine.setup(); - setup.secure_init(P, machine, T::clear::length(), 40); + setup.params.set_matrix_dim_from_options(); + setup.params.set_sec(OnlineOptions::singleton.security_parameter); + setup.secure_init(P, machine, T::clear::length(), 0); T::clear::template init(); } diff --git a/Protocols/MAC_Check.h b/Protocols/MAC_Check.h index 2250417d0..19d5e72d5 100644 --- a/Protocols/MAC_Check.h +++ b/Protocols/MAC_Check.h @@ -122,7 +122,6 @@ template class MAC_Check_Z2k : public Tree_MAC_Check { protected: - vector shares; Preprocessing* prep; W get_random_element(); @@ -130,11 +129,11 @@ class MAC_Check_Z2k : public Tree_MAC_Check public: vector random_elements; - void AddToCheck(const W& share, const T& value, const Player& P); MAC_Check_Z2k(const T& ai, int opening_sum=10, int max_broadcast=10, int send_player=0); MAC_Check_Z2k(const T& ai, Names& Nms, int thread_num); void prepare_open(const W& secret); + void prepare_open_no_mask(const W& secret); virtual void Check(const Player& P); void set_random_element(const W& random_element); diff --git a/Protocols/MAC_Check.hpp b/Protocols/MAC_Check.hpp index fd71d5269..ca607fd76 100644 --- a/Protocols/MAC_Check.hpp +++ b/Protocols/MAC_Check.hpp @@ -14,6 +14,7 @@ #include #include "Protocols/MAC_Check_Base.hpp" +#include "mac_key.hpp" template const char* TreeSum::mc_timer_names[] = { @@ -118,6 +119,7 @@ template void MAC_Check_::Check(const Player& P) { assert(U::mac_type::invertible); + check_field_size(); if (this->WaitingForCheck() == 0) return; @@ -214,17 +216,15 @@ MAC_Check_Z2k::MAC_Check_Z2k(const T& ai, Names& Nms, } template -void MAC_Check_Z2k::AddToCheck(const W& share, const T& value, const Player& P) +void MAC_Check_Z2k::prepare_open(const W& secret) { - shares.push_back(share.get_share()); - Tree_MAC_Check::AddToCheck(share, value, P); + prepare_open_no_mask(secret + (get_random_element() << W::clear::N_BITS)); } template -void MAC_Check_Z2k::prepare_open(const W& secret) +void MAC_Check_Z2k::prepare_open_no_mask(const W& secret) { - shares.push_back(secret.get_share()); - this->values.push_back(V(secret.get_share())); + this->values.push_back(secret.get_share()); this->macs.push_back(secret.get_mac()); } @@ -269,7 +269,6 @@ void MAC_Check_Z2k::Check(const Player& P) cout << "Checking " << shares[0] << " " << this->vals[0] << " " << this->macs[0] << endl; #endif - int k = V::N_BITS; octet seed[SEED_SIZE]; Create_Random_Seed(seed,P,SEED_SIZE); PRNG G; @@ -290,30 +289,7 @@ void MAC_Check_Z2k::Check(const Player& P) chi.push_back(temp_chi); } - W r = get_random_element(); - T lj = r.get_mac(); - U pj; - pj.assign_zero(); - for (int i = 0; i < this->popen_cnt; ++i) - { - T xji = shares[i]; - V xbarji = xji; - U pji = U((xji - xbarji) >> k); - pj += chi[i] * pji; - } - pj += U(r.get_share()); - - U pbar(pj); - vector pj_stream(P.num_players()); - pj.pack(pj_stream[P.my_num()]); - P.unchecked_broadcast(pj_stream); - for (int j=0; jalphai * y) - (((this->alphai * pbar)) << k) + (lj << k); + T zj = mj - this->alphai * y; vector zjs(P.num_players()); zjs[P.my_num()] = zj; Commit_And_Open(zjs, P); @@ -325,7 +301,6 @@ void MAC_Check_Z2k::Check(const Player& P) this->vals.erase(this->vals.begin(), this->vals.begin() + this->popen_cnt); this->macs.erase(this->macs.begin(), this->macs.begin() + this->popen_cnt); - this->shares.erase(this->shares.begin(), this->shares.begin() + this->popen_cnt); this->popen_cnt=0; if (!zj_sum.is_zero()) { throw mac_fail(); } } diff --git a/Protocols/MAC_Check_Base.h b/Protocols/MAC_Check_Base.h index 5a60281c6..e855214fd 100644 --- a/Protocols/MAC_Check_Base.h +++ b/Protocols/MAC_Check_Base.h @@ -57,7 +57,8 @@ class MAC_Check_Base /// Run opening protocol virtual void exchange(const Player& P) = 0; /// Get next opened value - virtual typename T::open_type finalize_open(); + virtual typename T::clear finalize_open(); + virtual typename T::open_type finalize_raw(); /// Check whether all ``shares`` are ``value`` virtual void CheckFor(const typename T::open_type& value, const vector& shares, const Player& P); diff --git a/Protocols/MAC_Check_Base.hpp b/Protocols/MAC_Check_Base.hpp index 91e2ea86b..59c6c5dec 100644 --- a/Protocols/MAC_Check_Base.hpp +++ b/Protocols/MAC_Check_Base.hpp @@ -25,7 +25,7 @@ void MAC_Check_Base::POpen_End(vector& values, values.clear(); values.reserve(S.size()); for (size_t i = 0; i < S.size(); i++) - values.push_back(finalize_open()); + values.push_back(finalize_raw()); } template @@ -59,7 +59,13 @@ void MAC_Check_Base::prepare_open(const T& secret) } template -typename T::open_type MAC_Check_Base::finalize_open() +typename T::clear MAC_Check_Base::finalize_open() +{ + return finalize_raw(); +} + +template +typename T::open_type MAC_Check_Base::finalize_raw() { return values.next(); } diff --git a/Protocols/MalRepRingOptions.cpp b/Protocols/MalRepRingOptions.cpp index a2537da66..c5aafc18b 100644 --- a/Protocols/MalRepRingOptions.cpp +++ b/Protocols/MalRepRingOptions.cpp @@ -21,10 +21,10 @@ MalRepRingOptions::MalRepRingOptions(ez::ezOptionParser& opt, int argc, 0, // Number of args expected. 0, // Delimiter if expecting multiple args. "Shuffle sacrifice (default: disabled)", // Help description. - "-S", // Flag token. + "-SH", // Flag token. "--shuffle" // Flag token. ); opt.parse(argc, argv); - shuffle = opt.isSet("-S"); + shuffle = opt.isSet("-SH"); opt.resetArgs(); } diff --git a/Protocols/MalRepRingPrep.hpp b/Protocols/MalRepRingPrep.hpp index 96f2c8138..6ce2e2442 100644 --- a/Protocols/MalRepRingPrep.hpp +++ b/Protocols/MalRepRingPrep.hpp @@ -89,7 +89,7 @@ void MalRepRingPrep::simple_buffer_triples() template void MalRepRingPrep::shuffle_buffer_triples() { - assert(T::SECURITY <= 40); + assert(T::SECURITY <= OnlineOptions::singleton.security_parameter); assert(this->proc != 0); typename T::MAC_Check MC; shuffle_triple_generation(this->triples, this->proc->P, MC); diff --git a/Protocols/MaliciousRepMC.h b/Protocols/MaliciousRepMC.h index 87deaaa3b..e023945b1 100644 --- a/Protocols/MaliciousRepMC.h +++ b/Protocols/MaliciousRepMC.h @@ -49,11 +49,11 @@ class HashMaliciousRepMC : public MaliciousRepMC public: // emulate MAC_Check - HashMaliciousRepMC(const typename T::value_type& _, int __ = 0, int ___ = 0) : HashMaliciousRepMC() + HashMaliciousRepMC(const typename T::mac_key_type& _, int __ = 0, int ___ = 0) : HashMaliciousRepMC() { (void)_; (void)__; (void)___; } // emulate Direct_MAC_Check - HashMaliciousRepMC(const typename T::value_type& _, Names& ____, int __ = 0, int ___ = 0) : HashMaliciousRepMC() + HashMaliciousRepMC(const typename T::mac_key_type& _, Names& ____, int __ = 0, int ___ = 0) : HashMaliciousRepMC() { (void)_; (void)__; (void)___; (void)____; } HashMaliciousRepMC(); @@ -62,7 +62,7 @@ class HashMaliciousRepMC : public MaliciousRepMC void POpen(vector& values,const vector& S,const Player& P); void POpen_End(vector& values,const vector& S,const Player& P); - virtual typename T::open_type finalize_open(); + virtual typename T::open_type finalize_raw(); void CheckFor(const typename T::open_type& value, const vector& shares, const Player& P); diff --git a/Protocols/MaliciousRepMC.hpp b/Protocols/MaliciousRepMC.hpp index e64db21ad..17eec6f11 100644 --- a/Protocols/MaliciousRepMC.hpp +++ b/Protocols/MaliciousRepMC.hpp @@ -84,9 +84,9 @@ void HashMaliciousRepMC::POpen_End(vector& values, } template -typename T::open_type HashMaliciousRepMC::finalize_open() +typename T::open_type HashMaliciousRepMC::finalize_raw() { - auto res = ReplicatedMC::finalize_open(); + auto res = ReplicatedMC::finalize_raw(); os.reset_write_head(); res.pack(os); update(); diff --git a/Protocols/MaliciousRepPrep.hpp b/Protocols/MaliciousRepPrep.hpp index 8ffbff7bd..b4d83d1b9 100644 --- a/Protocols/MaliciousRepPrep.hpp +++ b/Protocols/MaliciousRepPrep.hpp @@ -7,6 +7,8 @@ #include "Tools/Subroutines.h" #include "Processor/OnlineOptions.h" +#include "mac_key.hpp" + template MaliciousBitOnlyRepPrep::MaliciousBitOnlyRepPrep(SubProcessor* proc, DataPositions& usage) : BufferPrep(usage), @@ -69,7 +71,7 @@ void MaliciousBitOnlyRepPrep::init_honest(Player& P) template void MaliciousRepPrep::buffer_triples() { - assert(T::open_type::length() >= 40); + check_field_size(); auto& triples = this->triples; auto buffer_size = this->buffer_size; auto& honest_proc = this->honest_proc; diff --git a/Protocols/MaliciousShamirMC.h b/Protocols/MaliciousShamirMC.h index a72c36b03..4efe07118 100644 --- a/Protocols/MaliciousShamirMC.h +++ b/Protocols/MaliciousShamirMC.h @@ -38,7 +38,7 @@ class MaliciousShamirMC : public ShamirMC { (void)_; (void)__; (void)___; (void)____; } void init_open(const Player& P, int n = 0); - typename T::open_type finalize_open(); + typename T::open_type finalize_raw(); typename T::open_type reconstruct(const vector& shares); }; diff --git a/Protocols/MaliciousShamirMC.hpp b/Protocols/MaliciousShamirMC.hpp index 41c6f208a..7f66215d5 100644 --- a/Protocols/MaliciousShamirMC.hpp +++ b/Protocols/MaliciousShamirMC.hpp @@ -33,7 +33,7 @@ void MaliciousShamirMC::init_open(const Player& P, int n) } template -typename T::open_type MaliciousShamirMC::finalize_open() +typename T::open_type MaliciousShamirMC::finalize_raw() { int threshold = ShamirMachine::s().threshold; shares.resize(2 * threshold + 1); diff --git a/Protocols/MaliciousShamirShare.h b/Protocols/MaliciousShamirShare.h index fee8e8292..ceedc9157 100644 --- a/Protocols/MaliciousShamirShare.h +++ b/Protocols/MaliciousShamirShare.h @@ -38,6 +38,9 @@ class MaliciousShamirShare : public ShamirShare typedef MaliciousRepPrep TriplePrep; typedef T random_type; + // indicate security relevance of field size + typedef T mac_key_type; + #ifndef NO_MIXED_CIRCUITS typedef GC::MaliciousCcdSecret bit_type; #endif diff --git a/Protocols/MamaPrep.hpp b/Protocols/MamaPrep.hpp index c9eb63cf6..11942825f 100644 --- a/Protocols/MamaPrep.hpp +++ b/Protocols/MamaPrep.hpp @@ -25,13 +25,15 @@ template void MamaPrep::buffer_triples() { int mac_security = T::N_MACS * T::clear::length(); + int sec = OnlineOptions::singleton.security_parameter; - if (mac_security < 40) + if (mac_security < sec) { - cerr << T::N_MACS << " MACs are not enough for 40-bit security with " - << T::clear::length() << "-bit primes." << endl; + cerr << T::N_MACS << " MACs are not enough for " << sec + << "-bit security with " << T::clear::length() << "-bit primes." + << endl; cerr << "Compile with -DN_MAMA_MACS=" - << DIV_CEIL(40, T::clear::length()) + << DIV_CEIL(sec, T::clear::length()) << " or remove this check in " << __FILE__ << endl; exit(1); } @@ -45,7 +47,7 @@ void MamaPrep::buffer_triples() size_t required = OnlineOptions::singleton.batch_size; // prefer shuffling if not loosing much security and bucket size is smaller - bool use_shuffling = mac_security <= 42 + bool use_shuffling = mac_security <= (sec + 2) and OnlineOptions::singleton.bucket_size < T::N_MACS; if (use_shuffling) required = sacrifice.minimum_n_inputs(); diff --git a/Protocols/MamaShare.h b/Protocols/MamaShare.h index c90a5e277..f27515185 100644 --- a/Protocols/MamaShare.h +++ b/Protocols/MamaShare.h @@ -23,6 +23,11 @@ class MamaMac : public FixedVec, N> public: static const true_type invertible; + static int length() + { + return N * T::length(); + } + MamaMac() { } diff --git a/Protocols/NoLivePrep.h b/Protocols/NoLivePrep.h index c53ec7e84..a1b89f9d9 100644 --- a/Protocols/NoLivePrep.h +++ b/Protocols/NoLivePrep.h @@ -32,6 +32,11 @@ class NoLivePrep : public BufferPrep { } + NoLivePrep(DataPositions& usage, int = -1) : + BufferPrep(usage) + { + } + // access to protocol instance if needed void set_protocol(typename T::Protocol&) { diff --git a/Protocols/NoProtocol.h b/Protocols/NoProtocol.h index d8259eb0f..f1ef3c02e 100644 --- a/Protocols/NoProtocol.h +++ b/Protocols/NoProtocol.h @@ -8,6 +8,7 @@ #include "Protocols/Replicated.h" #include "Protocols/MAC_Check_Base.h" +#include "Processor/Input.h" // opening facility template diff --git a/Protocols/NoShare.h b/Protocols/NoShare.h index d966f5867..0532200b6 100644 --- a/Protocols/NoShare.h +++ b/Protocols/NoShare.h @@ -25,9 +25,6 @@ class NoShare : public ShareInterface typedef T clear; typedef clear open_type; - // needs to be defined even if protocol doesn't use MACs - typedef clear mac_key_type; - // disable binary computation typedef GC::NoShare bit_type; diff --git a/Protocols/Rep3Share.h b/Protocols/Rep3Share.h index 44853b79a..afb456621 100644 --- a/Protocols/Rep3Share.h +++ b/Protocols/Rep3Share.h @@ -27,8 +27,6 @@ class RepShare : public FixedVec, public ShareInterface public: typedef T clear; typedef T open_type; - typedef T mac_type; - typedef T mac_key_type; const static bool needs_ot = false; const static bool dishonest_majority = false; @@ -138,9 +136,10 @@ class Rep3Share : public RepShare return T::type_char(); } - static Rep3Share constant(T value, int my_num, const T& alphai = {}) + static Rep3Share constant(T value, int my_num, + typename super::mac_key_type = {}) { - return Rep3Share(value, my_num, alphai); + return Rep3Share(value, my_num); } Rep3Share() diff --git a/Protocols/Replicated.h b/Protocols/Replicated.h index 2357d0f5e..ba5b85c8e 100644 --- a/Protocols/Replicated.h +++ b/Protocols/Replicated.h @@ -53,6 +53,8 @@ class ProtocolBase int trunc_pr_counter; int rounds, trunc_rounds; + int dot_counter; + int bit_counter; public: typedef T share_type; diff --git a/Protocols/Replicated.hpp b/Protocols/Replicated.hpp index 1a8a66b99..2d9eba572 100644 --- a/Protocols/Replicated.hpp +++ b/Protocols/Replicated.hpp @@ -20,7 +20,8 @@ template ProtocolBase::ProtocolBase() : - trunc_pr_counter(0), rounds(0), trunc_rounds(0), counter(0) + trunc_pr_counter(0), rounds(0), trunc_rounds(0), dot_counter(0), + bit_counter(0), counter(0) { } @@ -67,7 +68,11 @@ ProtocolBase::~ProtocolBase() { #ifdef VERBOSE_COUNT if (counter or rounds) - cerr << "Number of " << T::type_string() << " multiplications: " << counter << " in " << rounds << " rounds" << endl; + cerr << "Number of " << T::type_string() << " multiplications: " + << counter << " (" << bit_counter << " bits) in " << rounds + << " rounds" << endl; + if (counter or rounds) + cerr << "Number of " << T::type_string() << " dot products: " << dot_counter << endl; if (trunc_pr_counter or trunc_rounds) cerr << "Number of probabilistic truncations: " << trunc_pr_counter << " in " << trunc_rounds << " rounds" << endl; #endif @@ -126,6 +131,7 @@ template T ProtocolBase::finalize_dotprod(int length) { counter += length; + dot_counter++; T res; for (int i = 0; i < length; i++) res += finalize_mul(); @@ -199,6 +205,7 @@ template inline T Replicated::finalize_mul(int n) { this->counter++; + this->bit_counter += n; T result; result[0] = add_shares.next(); result[1].unpack(os[1], n); @@ -230,6 +237,7 @@ template inline T Replicated::finalize_dotprod(int length) { (void) length; + this->dot_counter++; return finalize_mul(); } @@ -316,6 +324,7 @@ void Replicated::trunc_pr(const vector& regs, int size, U& proc, for (auto info : infos) for (int i = 0; i < size; i++) { + this->trunc_pr_counter++; auto c_prime = input.finalize(comp_player); auto r_prime = input.finalize(gen_player); S[info.dest_base + i] = c_prime - r_prime; diff --git a/Protocols/ReplicatedMC.h b/Protocols/ReplicatedMC.h index bb6f36a20..17916a2e9 100644 --- a/Protocols/ReplicatedMC.h +++ b/Protocols/ReplicatedMC.h @@ -22,11 +22,11 @@ class ReplicatedMC : public MAC_Check_Base public: // emulate MAC_Check - ReplicatedMC(const typename T::value_type& _ = {}, int __ = 0, int ___ = 0) + ReplicatedMC(const typename T::mac_key_type& _ = {}, int __ = 0, int ___ = 0) { (void)_; (void)__; (void)___; } // emulate Direct_MAC_Check - ReplicatedMC(const typename T::value_type& _, Names& ____, int __ = 0, int ___ = 0) + ReplicatedMC(const typename T::mac_key_type& _, Names& ____, int __ = 0, int ___ = 0) { (void)_; (void)__; (void)___; (void)____; } void POpen(vector& values,const vector& S,const Player& P); @@ -34,7 +34,7 @@ class ReplicatedMC : public MAC_Check_Base void POpen_End(vector& values,const vector& S,const Player& P); virtual void exchange(const Player& P); - virtual typename T::open_type finalize_open(); + virtual typename T::open_type finalize_raw(); void Check(const Player& P) { (void)P; } diff --git a/Protocols/ReplicatedMC.hpp b/Protocols/ReplicatedMC.hpp index bbcf73e58..e72c0d839 100644 --- a/Protocols/ReplicatedMC.hpp +++ b/Protocols/ReplicatedMC.hpp @@ -65,7 +65,7 @@ void ReplicatedMC::finalize(vector& values, } template -typename T::open_type ReplicatedMC::finalize_open() +typename T::open_type ReplicatedMC::finalize_raw() { auto a = this->secrets.next().sum(); return a + o.get(); diff --git a/Protocols/SPDZ.h b/Protocols/SPDZ.h index fb2888c05..bd804ea0a 100644 --- a/Protocols/SPDZ.h +++ b/Protocols/SPDZ.h @@ -26,7 +26,8 @@ class SPDZ : public Beaver { } - static void assign(typename T::clear& share, const typename T::clear& clear, int my_num) + static void assign(typename T::open_type& share, + const typename T::open_type& clear, int my_num) { if (my_num == 0) share = clear; diff --git a/Protocols/SPDZ2k.h b/Protocols/SPDZ2k.h new file mode 100644 index 000000000..da128fee8 --- /dev/null +++ b/Protocols/SPDZ2k.h @@ -0,0 +1,28 @@ +/* + * SPDZ2k.h + * + */ + +#ifndef PROTOCOLS_SPDZ2K_H_ +#define PROTOCOLS_SPDZ2K_H_ + +#include "SPDZ.h" + +template +class SPDZ2k : public SPDZ +{ +public: + SPDZ2k(Player& P) : + SPDZ(P) + { + } + + void exchange() + { + for (size_t i = 0; i < this->shares.size(); i++) + this->MC->set_random_element({}); + SPDZ::exchange(); + } +}; + +#endif /* PROTOCOLS_SPDZ2K_H_ */ diff --git a/Protocols/Semi2kShare.h b/Protocols/Semi2kShare.h index ee5e83202..cc41d0236 100644 --- a/Protocols/Semi2kShare.h +++ b/Protocols/Semi2kShare.h @@ -21,8 +21,6 @@ class Semi2kShare : public SemiShare> typedef SignedZ2 T; public: - typedef Z2<64> mac_key_type; - typedef SemiMC MAC_Check; typedef DirectSemiMC Direct_MC; typedef SemiInput Input; diff --git a/Protocols/SemiInput.h b/Protocols/SemiInput.h index 4fc265b7c..c40d0c170 100644 --- a/Protocols/SemiInput.h +++ b/Protocols/SemiInput.h @@ -18,7 +18,7 @@ class SemiInput : public InputBase { vector send_prngs; vector recv_prngs; - Player& P; + PlayerBase& P; vector> shares; public: @@ -27,7 +27,7 @@ class SemiInput : public InputBase { } - SemiInput(SubProcessor* proc, Player& P); + SemiInput(SubProcessor* proc, PlayerBase& P); SemiInput(typename T::MAC_Check& MC, Preprocessing& prep, Player& P) : SemiInput(0, P) diff --git a/Protocols/SemiInput.hpp b/Protocols/SemiInput.hpp index 3ed1feefe..f0fefe137 100644 --- a/Protocols/SemiInput.hpp +++ b/Protocols/SemiInput.hpp @@ -11,7 +11,7 @@ #include "ShamirInput.hpp" template -SemiInput::SemiInput(SubProcessor* proc, Player& P) : +SemiInput::SemiInput(SubProcessor* proc, PlayerBase& P) : InputBase(proc), P(P) { shares.resize(P.num_players()); diff --git a/Protocols/SemiShare.h b/Protocols/SemiShare.h index c2dd90858..b306d5c3d 100644 --- a/Protocols/SemiShare.h +++ b/Protocols/SemiShare.h @@ -9,6 +9,7 @@ #include "Protocols/Beaver.h" #include "Protocols/Semi.h" #include "Processor/DummyProtocol.h" +#include "GC/NoShare.h" #include "ShareInterface.h" #include @@ -51,8 +52,6 @@ class SemiShare : public T, public ShareInterface typedef T super; public: - typedef T mac_key_type; - typedef T mac_type; typedef T open_type; typedef T clear; @@ -87,10 +86,10 @@ class SemiShare : public T, public ShareInterface return nplayers - 1; } - static SemiShare constant(const clear& other, int my_num, - const T& alphai = {}, int = -1) + static SemiShare constant(const open_type& other, int my_num, + mac_key_type = {}, int = -1) { - return SemiShare(other, my_num, alphai); + return SemiShare(other, my_num); } SemiShare() @@ -100,7 +99,7 @@ class SemiShare : public T, public ShareInterface SemiShare(const U& other) : T(other) { } - SemiShare(const clear& other, int my_num, const T& alphai = {}) + SemiShare(const open_type& other, int my_num, const T& alphai = {}) { (void) alphai; Protocol::assign(*this, other, my_num); diff --git a/Protocols/ShamirMC.h b/Protocols/ShamirMC.h index 6bda92dfc..c6a88f0ad 100644 --- a/Protocols/ShamirMC.h +++ b/Protocols/ShamirMC.h @@ -69,7 +69,7 @@ class ShamirMC : public IndirectShamirMC virtual void init_open(const Player& P, int n = 0); virtual void prepare_open(const T& secret); virtual void exchange(const Player& P); - virtual typename T::open_type finalize_open(); + virtual typename T::open_type finalize_raw(); void Check(const Player& P) { (void)P; } diff --git a/Protocols/ShamirMC.hpp b/Protocols/ShamirMC.hpp index e3e7cd3ac..7238aa5ef 100644 --- a/Protocols/ShamirMC.hpp +++ b/Protocols/ShamirMC.hpp @@ -112,11 +112,11 @@ void ShamirMC::finalize(vector& values, { values.clear(); for (size_t i = 0; i < S.size(); i++) - values.push_back(finalize_open()); + values.push_back(finalize_raw()); } template -typename T::open_type ShamirMC::finalize_open() +typename T::open_type ShamirMC::finalize_raw() { assert(reconstruction.size()); typename T::open_type res; diff --git a/Protocols/ShamirShare.h b/Protocols/ShamirShare.h index e7daabfcf..aea0bb97a 100644 --- a/Protocols/ShamirShare.h +++ b/Protocols/ShamirShare.h @@ -29,10 +29,7 @@ class ShamirShare : public T, public ShareInterface public: typedef T clear; typedef T open_type; - typedef T mac_key_type; typedef void sacri_type; - typedef GC::NoShare mac_type; - typedef GC::NoShare mac_share_type; typedef Shamir Protocol; typedef IndirectShamirMC MAC_Check; @@ -76,9 +73,9 @@ class ShamirShare : public T, public ShareInterface return Protocol::get_rec_factor(i, n); } - static ShamirShare constant(T value, int my_num, const T& alphai = {}) + static ShamirShare constant(T value, int, const mac_key_type& = {}) { - return ShamirShare(value, my_num, alphai); + return ShamirShare(value); } ShamirShare() @@ -89,42 +86,12 @@ class ShamirShare : public T, public ShareInterface { T::operator=(other); } - template - ShamirShare(const U& other, int my_num, T alphai = {}) : ShamirShare(other) - { - (void) my_num, (void) alphai; - } - // Share compatibility - void assign(clear other, int my_num, const T& alphai) - { - (void)alphai, (void)my_num; - *this = other; - } void assign(const char* buffer) { T::assign(buffer); } - void add(const ShamirShare& S, const clear aa, int my_num, - const T& alphai) - { - (void) my_num, (void) alphai; - *this = S + aa; - } - void sub(const ShamirShare& S, const clear& aa, int my_num, - const T& alphai) - { - (void) my_num, (void) alphai; - *this = S - aa; - } - void sub(const clear& aa, const ShamirShare& S, int my_num, - const T& alphai) - { - (void) my_num, (void) alphai; - *this = aa - S; - } - ShamirShare operator<<(int i) { return *this * (T(1) << i); diff --git a/Protocols/Share.h b/Protocols/Share.h index 92be4f144..e2a9f0bb5 100644 --- a/Protocols/Share.h +++ b/Protocols/Share.h @@ -73,7 +73,7 @@ class Share_ : public ShareInterface static void specification(octetStream& os) { T::specification(os); } - static Share_ constant(const clear& aa, int my_num, const typename V::Scalar& alphai) + static Share_ constant(const open_type& aa, int my_num, const typename V::Scalar& alphai) { return Share_(aa, my_num, alphai); } template @@ -85,12 +85,12 @@ class Share_ : public ShareInterface { a.assign_zero(); mac.assign_zero(); } - void assign(const clear& aa, int my_num, const typename V::Scalar& alphai); + void assign(const open_type& aa, int my_num, const typename V::Scalar& alphai); Share_() { assign_zero(); } template Share_(const Share_& S) { assign(S); } - Share_(const clear& aa, int my_num, const typename V::Scalar& alphai) + Share_(const open_type& aa, int my_num, const typename V::Scalar& alphai) { assign(aa, my_num, alphai); } Share_(const T& share, const V& mac) : a(share), mac(mac) {} @@ -128,6 +128,8 @@ class Share_ : public ShareInterface void force_to_bit() { a.force_to_bit(); } + void randomize(PRNG& G); + // Input and output from a stream // - Can do in human or machine only format (later should be faster) void output(ostream& s,bool human) const @@ -235,7 +237,7 @@ inline void Share_::mul(const Share_& S,const clear& aa) } template -inline void Share_::assign(const clear& aa, int my_num, +inline void Share_::assign(const open_type& aa, int my_num, const typename V::Scalar& alphai) { a = T::constant(aa, my_num); diff --git a/Protocols/Share.hpp b/Protocols/Share.hpp index 62f90e91d..c6f675f7f 100644 --- a/Protocols/Share.hpp +++ b/Protocols/Share.hpp @@ -23,6 +23,13 @@ void Share_::read_or_generate_mac_key(string directory, const Player& P, } } +template +void Share_::randomize(PRNG& G) +{ + a.randomize(G); + mac.randomize(G); +} + template inline void Share_::pack(octetStream& os, bool full) const { diff --git a/Protocols/ShareInterface.h b/Protocols/ShareInterface.h index 444214e47..e5af8dddd 100644 --- a/Protocols/ShareInterface.h +++ b/Protocols/ShareInterface.h @@ -20,6 +20,7 @@ class ValueInterface; namespace GC { class NoShare; +class NoValue; } class ShareInterface @@ -28,6 +29,10 @@ class ShareInterface typedef GC::NoShare part_type; typedef GC::NoShare bit_type; + typedef GC::NoValue mac_key_type; + typedef GC::NoShare mac_type; + typedef GC::NoShare mac_share_type; + static const bool needs_ot = false; static const bool expensive = false; static const bool expensive_triples = false; diff --git a/Protocols/ShareMatrix.h b/Protocols/ShareMatrix.h index b7fdf50be..7f84213e6 100644 --- a/Protocols/ShareMatrix.h +++ b/Protocols/ShareMatrix.h @@ -128,7 +128,7 @@ class ShareMatrix : public ValueMatrix, public ShareInterface typedef ValueMatrix clear; typedef clear open_type; - typedef typename T::clear mac_key_type; + typedef typename T::mac_key_type mac_key_type; static string type_string() { diff --git a/Protocols/ShuffleSacrifice.hpp b/Protocols/ShuffleSacrifice.hpp index 81e859319..4d03dd67e 100644 --- a/Protocols/ShuffleSacrifice.hpp +++ b/Protocols/ShuffleSacrifice.hpp @@ -14,7 +14,7 @@ inline ShuffleSacrifice::ShuffleSacrifice() : - B(OnlineOptions::singleton.bucket_size), C(this->B) + ShuffleSacrifice(OnlineOptions::singleton.bucket_size, 3) { } @@ -22,6 +22,9 @@ inline ShuffleSacrifice::ShuffleSacrifice(int B, int C) : B(B), C(C) { + if (OnlineOptions::singleton.security_parameter > 40) + throw runtime_error("shuffle sacrifice not implemented for more than " + "40-bit security"); } template diff --git a/Protocols/SohoPrep.hpp b/Protocols/SohoPrep.hpp index 48deeadc4..1dfd3ecb9 100644 --- a/Protocols/SohoPrep.hpp +++ b/Protocols/SohoPrep.hpp @@ -21,6 +21,7 @@ void SohoPrep::basic_setup(Player& P) assert(not setup); setup = new PartSetup; MachineBase machine; + setup->params.set_sec(OnlineOptions::singleton.security_parameter); setup->secure_init(P, machine, T::clear::length(), 0); read_or_generate_secrets(*setup, P, machine, 1, true_type()); T::clear::template init(); diff --git a/Protocols/Spdz2kPrep.h b/Protocols/Spdz2kPrep.h index 03a91ff25..d95a713d1 100644 --- a/Protocols/Spdz2kPrep.h +++ b/Protocols/Spdz2kPrep.h @@ -8,7 +8,8 @@ #include "MascotPrep.h" #include "RingOnlyPrep.h" -#include "Spdz2kShare.h" + +template class Spdz2kShare; template void bits_from_square_in_ring(vector& bits, int buffer_size, U* bit_prep); diff --git a/Protocols/Spdz2kShare.h b/Protocols/Spdz2kShare.h index 401070f84..762cd34df 100644 --- a/Protocols/Spdz2kShare.h +++ b/Protocols/Spdz2kShare.h @@ -18,6 +18,7 @@ template class Spdz2kMultiplier; template class Spdz2kTripleGenerator; +template class SPDZ2k; namespace GC { @@ -48,7 +49,7 @@ class Spdz2kShare : public Share> typedef MAC_Check Direct_MC; typedef ::Input Input; typedef ::PrivateOutput PrivateOutput; - typedef SPDZ Protocol; + typedef SPDZ2k Protocol; typedef Spdz2kPrep LivePrep; #ifndef NO_MIXED_CIRCUITS diff --git a/Protocols/SpdzWise.hpp b/Protocols/SpdzWise.hpp index 2ea08ba46..b7a8c741f 100644 --- a/Protocols/SpdzWise.hpp +++ b/Protocols/SpdzWise.hpp @@ -5,6 +5,8 @@ #include "SpdzWise.h" +#include "mac_key.hpp" + template SpdzWise::SpdzWise(Player& P) : internal(P), internal2(P), P(P) @@ -142,6 +144,7 @@ template void SpdzWise::zero_check(check_type t) { assert(T::clear::invertible); + check_field_size(); auto r = internal.get_random(); internal.init_mul(); internal.prepare_mul(t, r); diff --git a/Protocols/SpdzWiseMC.h b/Protocols/SpdzWiseMC.h index 9991dafb2..9ad761985 100644 --- a/Protocols/SpdzWiseMC.h +++ b/Protocols/SpdzWiseMC.h @@ -44,9 +44,9 @@ class SpdzWiseMC : public MAC_Check_Base { inner_MC.exchange(P); } - typename T::open_type finalize_open() + typename T::open_type finalize_raw() { - return inner_MC.finalize_open(); + return inner_MC.finalize_raw(); } void Check(const Player& P) { diff --git a/Protocols/SpdzWiseShare.hpp b/Protocols/SpdzWiseShare.hpp index 6401c083a..acd6fa298 100644 --- a/Protocols/SpdzWiseShare.hpp +++ b/Protocols/SpdzWiseShare.hpp @@ -13,14 +13,15 @@ template void SpdzWiseShare::read_or_generate_mac_key(string directory, Player& P, T& mac_key) { + bool fresh = false; + try { read_mac_key(directory, P.N, mac_key); } catch (mac_key_error&) { - SeededPRNG G; - mac_key.randomize(G); + fresh = true; } try @@ -33,11 +34,12 @@ void SpdzWiseShare::read_or_generate_mac_key(string directory, Player& P, T& } catch (mac_fail&) { -#ifdef VERBOSE - cerr << "Generating fresh MAC key for " << type_string() << endl; -#endif - mac_key = typename T::Honest::Protocol(P).get_random(); + fresh = true; + cerr << "Invalid " << type_string() << " MAC key, generating fresh one" << endl; } + + if (fresh) + mac_key = typename T::Honest::Protocol(P).get_random(); } template diff --git a/Protocols/TemiPrep.h b/Protocols/TemiPrep.h index de7406bba..ad12837a8 100644 --- a/Protocols/TemiPrep.h +++ b/Protocols/TemiPrep.h @@ -64,6 +64,8 @@ class TemiPrep : public SemiHonestRingPrep { } + ~TemiPrep(); + void buffer_triples(); vector*>& get_multipliers(); diff --git a/Protocols/TemiPrep.hpp b/Protocols/TemiPrep.hpp index 1088a99cc..1f2a415cc 100644 --- a/Protocols/TemiPrep.hpp +++ b/Protocols/TemiPrep.hpp @@ -24,6 +24,7 @@ void TemiPrep::basic_setup(Player& P) assert(not setup); setup = new TemiSetup; MachineBase machine; + setup->params.set_sec(OnlineOptions::singleton.security_parameter); setup->secure_init(P, T::clear::length()); read_or_generate_secrets(*setup, P, machine, 1, true_type()); T::clear::template init(); @@ -104,6 +105,13 @@ TemiMultiplier::TemiMultiplier(Player& P) : P(P) { } +template +TemiPrep::~TemiPrep() +{ + for (auto& x : multipliers) + delete x; +} + template vector& TemiMultiplier::get_multiplicands( vector >& ciphertexts, const FHE_PK& pk) diff --git a/Protocols/config.h b/Protocols/config.h new file mode 100644 index 000000000..f88c3aa8a --- /dev/null +++ b/Protocols/config.h @@ -0,0 +1,13 @@ +/* + * config.h + * + */ + +#ifndef PROTOCOLS_CONFIG_H_ +#define PROTOCOLS_CONFIG_H_ + +#ifndef DEFAULT_SECURITY +#define DEFAULT_SECURITY 40 +#endif + +#endif /* PROTOCOLS_CONFIG_H_ */ diff --git a/Protocols/fake-stuff.h b/Protocols/fake-stuff.h index d15581ebd..dc9414278 100644 --- a/Protocols/fake-stuff.h +++ b/Protocols/fake-stuff.h @@ -11,7 +11,7 @@ using namespace std; template void check_share(vector& Sa, typename T::clear& value, - typename T::value_type& mac, int N, const typename T::value_type& key); + typename T::mac_type& mac, int N, const typename T::mac_key_type& key); template class Share; diff --git a/Protocols/fake-stuff.hpp b/Protocols/fake-stuff.hpp index aeb516118..bae415c4a 100644 --- a/Protocols/fake-stuff.hpp +++ b/Protocols/fake-stuff.hpp @@ -20,6 +20,7 @@ template class FixedVec; template class Share_; template class SpdzWiseShare; template class MaliciousRep3Share; +template class DealerShare; namespace GC { @@ -115,7 +116,6 @@ void make_share(GC::TinierSecret* Sa, const U& a, int N, const V& key, PRNG& template void make_share(SemiShare* Sa,const T& a,int N,const U&,PRNG& G) { - insecure("share generation", false); T x, S = a; for (int i=0; i* Sa,const T& a,int N,const U&,PRNG& G) Sa[N-1]=S; } +template +void make_share(DealerShare* Sa, const T& a, int N, const U&, PRNG& G) +{ + make_share((SemiShare*) Sa, a, N - 1, U(), G); + Sa[N - 1] = {}; +} + template void make_share(FixedVec* Sa, const V& a, int N, const U& key, PRNG& G); @@ -234,7 +241,7 @@ void check_share(vector >& Sa, template void check_share(vector& Sa, typename T::clear& value, - typename T::value_type& mac, int N, const typename T::value_type& key) + typename T::mac_type& mac, int N, const typename T::mac_key_type& key) { assert(N == 3); value = 0; @@ -340,23 +347,27 @@ typename T::mac_key_type read_generate_write_mac_key(Player& P, { if (directory == "") directory = get_prep_sub_dir(P.num_players()); - typename T::mac_key_type res; + typename T::mac_key_type res, tmp; try { - read_mac_key(directory, P.my_num(), P.num_players(), res); + read_mac_key(directory, P.my_num(), P.num_players(), tmp); } catch (mac_key_error&) { - T::read_or_generate_mac_key(directory, P, res); - write_mac_key(directory, P.my_num(), P.num_players(), res); } + T::read_or_generate_mac_key(directory, P, res); + + // only write if changed + if (tmp != res) + write_mac_key(directory, P.my_num(), P.num_players(), res); + return res; } template -void read_global_mac_key(const string& directory, int nparties, U& key) +void read_global_mac_key(const string& directory, int nparties, U& key, false_type) { U pp; key.assign_zero(); @@ -372,6 +383,17 @@ void read_global_mac_key(const string& directory, int nparties, U& key) cout << "Final Keys : " << key << endl; } +template +void read_global_mac_key(const string&, int, U&, true_type) +{ +} + +template +void read_global_mac_key(const string& directory, int nparties, U& key) +{ + read_global_mac_key(directory, nparties, key, is_same()); +} + template T reconstruct(vector& shares) { @@ -548,4 +570,25 @@ void make_inverse(const typename T::mac_type& key, int N, int ntrip, bool zero, check_files(files.outf, N); } +template +void plain_edabits(vector& as, + vector& bs, int length, PRNG& G, + bool zero = false) +{ + int max_size = edabitvec::MAX_SIZE; + as.resize(max_size); + bs.clear(); + bs.resize(length); + bigint value; + for (int j = 0; j < max_size; j++) + { + if (not zero) + G.get_bigint(value, length, true); + as[j] = value; + for (int k = 0; k < length; k++) + bs[k] ^= BitVec(bigint((value >> k) & 1).get_si()) << j; + } + +} + #endif diff --git a/Protocols/mac_key.hpp b/Protocols/mac_key.hpp index 843e6d47f..3f1000b89 100644 --- a/Protocols/mac_key.hpp +++ b/Protocols/mac_key.hpp @@ -22,4 +22,12 @@ typename T::mac_key_type read_or_generate_mac_key(const Player& P, return res; } +template +void check_field_size() +{ + if (T::length() < OnlineOptions::singleton.security_parameter) + throw runtime_error("Field too small for chosen security. " + "Increase size with -lgp or decrease security with -S"); +} + #endif /* PROTOCOLS_MAC_KEY_HPP_ */ diff --git a/README.md b/README.md index 96aa0fd53..d44190e10 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ parties and malicious security. On Linux, this requires a working toolchain and [all requirements](#requirements). On Ubuntu, the following might suffice: ``` -apt-get install automake build-essential git libboost-dev libboost-thread-dev libntl-dev libsodium-dev libssl-dev libtool m4 python3 texinfo yasm +sudo apt-get install automake build-essential git libboost-dev libboost-thread-dev libntl-dev libsodium-dev libssl-dev libtool m4 python3 texinfo yasm ``` On MacOS, this requires [brew](https://brew.sh) to be installed, which will be used for all dependencies. @@ -103,6 +103,7 @@ The following table lists all protocols that are fully supported. | Semi-honest, dishonest majority | [Semi / Hemi / Temi / Soho](#secret-sharing) | [Semi2k](#secret-sharing) | [SemiBin](#secret-sharing) | [Yao's GC](#yaos-garbled-circuits) / [BMR](#bmr) | | Malicious, honest majority | [Shamir / Rep3 / PS / SY](#honest-majority) | [Brain / Rep[34] / PS / SY](#honest-majority) | [Rep3 / CCD / PS](#honest-majority) | [BMR](#bmr) | | Semi-honest, honest majority | [Shamir / ATLAS / Rep3](#honest-majority) | [Rep3](#honest-majority) | [Rep3 / CCD](#honest-majority) | [BMR](#bmr) | +| Semi-honest, dealer | [Dealer](#dealer-model) | [Dealer](#dealer-model) | [Dealer](#dealer-model) | N/A | Modulo prime and modulo 2^k are the two settings that allow integer-like computation. For k = 64, the latter corresponds to the @@ -174,6 +175,9 @@ there are a few things to consider: adding `program.use_trunc_pr = True` at the beginning of your high-level program. +- Larger number of parties: ATLAS scales better than the plain Shamir + protocol, and Temi scale better than Hemi or Semi. + - Minor variants: Some command-line options change aspects of the protocols such as: @@ -771,7 +775,23 @@ the number of parties with `-N` and the maximum number of corrupted parties with `-T`. The latter can be at most half the number of parties. -### BMR +## Dealer model + +This security model defines a special party that generates correlated +randomness such as multiplication triples, which is then used by all +other parties. MP-SPDZ implements the canonical protocol where the +other parties run the online phase of the semi-honest protocol in +Semi(2k/Bin) and the dealer provides all preprocessing. The security +assumption is that dealer doesn't collude with any other party, but +all but one of the other parties are allowed to collude. In our +implementation, the dealer is the party with the highest number, so +with three parties overall, Party 0 and 1 run the online phase. + +| Program | Sharing | Domain | Malicious | \# parties | Script | +| --- | --- | --- | --- | --- | --- | +| `dealer-ring-party.x` | Additive | Mod 2^k | N | 3+ | `dealer-ring.sh` | + +## BMR BMR (Bellare-Micali-Rogaway) is a method of generating a garbled circuit using another secure computation protocol. We have implemented BMR diff --git a/Scripts/dealer-ring.sh b/Scripts/dealer-ring.sh new file mode 100755 index 000000000..b0d6692a5 --- /dev/null +++ b/Scripts/dealer-ring.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +HERE=$(cd `dirname $0`; pwd) +SPDZROOT=$HERE/.. + +export PLAYERS=${PLAYERS:-3} + +. $HERE/run-common.sh + +run_player dealer-ring-party.x $* || exit 1 diff --git a/Scripts/memory-usage.py b/Scripts/memory-usage.py index 15959ee68..eaec677fd 100755 --- a/Scripts/memory-usage.py +++ b/Scripts/memory-usage.py @@ -12,7 +12,7 @@ print('Usage: %s ' % sys.argv[0]) res = collections.defaultdict(lambda: 0) -m = 0 +regs = collections.defaultdict(lambda: 0) for tapename in Program.read_tapes(sys.argv[1]): for inst in Tape.read_instructions(tapename): @@ -22,8 +22,9 @@ res[t.arg_format[0]]) for arg in inst.args: if isinstance(arg, RegisterArgFormat): - m = max(m, arg.i + inst.size) + regs[type(arg)] = max(regs[type(arg)], arg.i + inst.size) -print (res) -print (m) +reverse_formats = dict((v, k) for k, v in ArgFormats.items()) +print ('Memory:', dict(res)) +print ('Registers:', dict((reverse_formats[t], n) for t, n in regs.items())) diff --git a/Scripts/test_tutorial.sh b/Scripts/test_tutorial.sh index e8c02f6cb..3771383b7 100755 --- a/Scripts/test_tutorial.sh +++ b/Scripts/test_tutorial.sh @@ -52,7 +52,7 @@ for dabit in ${dabit:-0 1 2}; do ./compile.py -R 64 $compile_opts tutorial for i in ring rep4-ring semi2k brain mal-rep-ring ps-rep-ring sy-rep-ring \ - spdz2k; do + spdz2k dealer-ring; do test_vm $i $run_opts done @@ -65,7 +65,7 @@ for dabit in ${dabit:-0 1 2}; do done for i in cowgear chaigear; do - test_vm $i $run_opts -l 3 -c 2 + test_vm $i $run_opts -S 3 -c 2 done done @@ -83,7 +83,7 @@ fi ./compile.py tutorial for i in cowgear chaigear; do - test_vm $i $run_opts -l 3 -c 2 -J + test_vm $i $run_opts -S 3 -c 2 -J done if test $skip_binary; then diff --git a/Scripts/tldr.sh b/Scripts/tldr.sh index ed6c01441..ce906a3a3 100755 --- a/Scripts/tldr.sh +++ b/Scripts/tldr.sh @@ -27,7 +27,11 @@ if test "$flags"; then cpu=amd64 fi - cp -av bin/`uname`-$cpu/* . || { echo This only works with a release downloaded from https://github.com/data61/MP-SPDZ/releases 1>&2; exit 1; } + if ! cp -av bin/`uname`-$cpu/* .; then + echo This only works with a release downloaded from https://github.com/data61/MP-SPDZ/releases 1>&2 + echo Make sure NOT to download a source code only file 1>&2 + exit 1 + fi fi mkdir Player-Data 2> /dev/null diff --git a/Tools/Buffer.cpp b/Tools/Buffer.cpp index 9dd15804c..f3e67c82f 100644 --- a/Tools/Buffer.cpp +++ b/Tools/Buffer.cpp @@ -85,6 +85,11 @@ void BufferBase::try_rewind() void BufferBase::prune() { + // only prune in secure mode +#ifdef INSECURE + return; +#endif + if (is_pipe()) return; diff --git a/Tools/Exceptions.cpp b/Tools/Exceptions.cpp index f6f4ba2ec..c7f8c371f 100644 --- a/Tools/Exceptions.cpp +++ b/Tools/Exceptions.cpp @@ -83,3 +83,8 @@ not_enough_to_buffer::not_enough_to_buffer(const string& type, const string& fil "adding -DINSECURE to the compiler options.") { } + +gf2n_not_supported::gf2n_not_supported(int n) : + runtime_error("GF(2^" + to_string(n) + ") not supported") +{ +} diff --git a/Tools/Exceptions.h b/Tools/Exceptions.h index fff8b2de4..bb347c6a8 100644 --- a/Tools/Exceptions.h +++ b/Tools/Exceptions.h @@ -278,4 +278,10 @@ class insufficient_memory : public runtime_error insufficient_memory(size_t size, const string& type); }; +class gf2n_not_supported : public runtime_error +{ +public: + gf2n_not_supported(int n); +}; + #endif diff --git a/Tools/avx_memcpy.h b/Tools/avx_memcpy.h index 231dc99cf..a00a215e2 100644 --- a/Tools/avx_memcpy.h +++ b/Tools/avx_memcpy.h @@ -20,6 +20,7 @@ template inline void avx_memcpy(void* dest, const void* source) { size_t length = L; +#ifdef __SSE2__ __m256i* d = (__m256i*)dest, *s = (__m256i*)source; #ifdef __AVX__ while (length >= 32) @@ -35,6 +36,10 @@ inline void avx_memcpy(void* dest, const void* source) _mm_storeu_si128(d2++, _mm_loadu_si128(s2++)); length -= 16; } +#else + void* d2 = dest; + const void* s2 = source; +#endif switch (length) { case 0: @@ -53,14 +58,16 @@ inline void avx_memcpy(void* dest, const void* source) inline void avx_memzero(void* dest, size_t length) { - __m256i* d = (__m256i*)dest; #ifdef __AVX__ + __m256i* d = (__m256i*)dest; __m256i s = _mm256_setzero_si256(); while (length >= 32) { _mm256_storeu_si256(d++, s); length -= 32; } +#else + void* d = dest; #endif switch (length) { diff --git a/Tools/benchmarking.cpp b/Tools/benchmarking.cpp index e956f15ec..88eee709f 100644 --- a/Tools/benchmarking.cpp +++ b/Tools/benchmarking.cpp @@ -5,6 +5,25 @@ #include "benchmarking.h" +void insecure(string message, bool warning) +{ +#ifdef INSECURE + if (warning) + cerr << "WARNING: insecure " << message << endl; +#else + (void)warning; + string msg = "You are trying to use insecure benchmarking functionality for " + + message + ".\nYou can activate this at compile time " + "by adding -DINSECURE to the compiler options.\n" + "Make sure to run 'make clean' as well before compiling."; + cerr << msg << endl; +#ifdef INSECURE_EXCEPTION + throw exception(); +#endif + exit(1); +#endif +} + void insecure_fake() { #if defined(INSECURE) or defined(INSECURE_FAKE) diff --git a/Tools/benchmarking.h b/Tools/benchmarking.h index 13fa9c365..e54990ca7 100644 --- a/Tools/benchmarking.h +++ b/Tools/benchmarking.h @@ -12,20 +12,7 @@ using namespace std; // call before insecure benchmarking functionality -inline void insecure(string message, bool warning = true) -{ -#ifdef INSECURE - if (warning) - cerr << "WARNING: insecure " << message << endl; -#else - (void)warning; - string msg = "You are trying to use insecure benchmarking functionality for " - + message + ".\nYou can activate this at compile time " - "by adding -DINSECURE to the compiler options.\n" - "Make sure to run make clean as well."; - throw runtime_error(msg); -#endif -} +void insecure(string message, bool warning = true); void insecure_fake(); diff --git a/Tools/intrinsics.h b/Tools/intrinsics.h index 45664a72b..e7cb87dc5 100644 --- a/Tools/intrinsics.h +++ b/Tools/intrinsics.h @@ -10,6 +10,7 @@ #include #include #else +#ifdef __aarch64__ #define SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES #define SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES #define SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES @@ -18,5 +19,6 @@ #include "simde/simde/x86/clmul.h" #include "aes-arm.h" #endif +#endif #endif /* TOOLS_INTRINSICS_H_ */ diff --git a/Tools/parse.h b/Tools/parse.h index af5e6de4c..8ff0fee9e 100644 --- a/Tools/parse.h +++ b/Tools/parse.h @@ -23,6 +23,14 @@ inline int get_int(istream& s) return be32toh(n); } +// Read an 8-byte integer +inline int64_t get_long(istream& s) +{ + int64_t n; + s.read((char*) &n, 8); + return be64toh(n); +} + // Read several integers inline void get_ints(int* res, istream& s, int count) { diff --git a/Utils/Check-Offline.cpp b/Utils/Check-Offline.cpp index 3a3644144..203328f22 100644 --- a/Utils/Check-Offline.cpp +++ b/Utils/Check-Offline.cpp @@ -36,7 +36,8 @@ string PREP_DATA_PREFIX; template void check_mult_triples(const typename T::mac_key_type& key,int N,vector*>& dataF) { - typename T::clear a,b,c,mac; + typename T::clear a,b,c; + typename T::mac_type mac; vector Sa(N),Sb(N),Sc(N); int n = 0; @@ -99,7 +100,8 @@ void check_tuple(const T& a, const T& b, int n, Dtype type) template void check_tuples(const typename T::mac_key_type& key,int N,vector*>& dataF, Dtype type) { - typename T::clear a,b,c,mac,res; + typename T::clear a,b,c,res; + typename T::mac_type mac; vector Sa(N),Sb(N),Sc(N); int n = 0; @@ -127,7 +129,8 @@ void check_tuples(const typename T::mac_key_type& key,int N,vector void check_bits(const typename T::mac_key_type& key,int N,vector*>& dataF) { - typename T::clear a,b,c,mac,res; + typename T::clear a,b,c,res; + typename T::mac_type mac; vector Sa(N),Sb(N),Sc(N); int n = 0; @@ -157,7 +160,8 @@ void check_bits(const typename T::mac_key_type& key,int N,vector void check_inputs(const typename T::mac_key_type& key,int N,vector*>& dataF) { - typename T::clear a, mac, x; + typename T::clear a, x; + typename T::mac_type mac; vector Sa(N); for (int player = 0; player < N; player++) diff --git a/Utils/Fake-Offline.cpp b/Utils/Fake-Offline.cpp index f1158cfa6..823c318bb 100644 --- a/Utils/Fake-Offline.cpp +++ b/Utils/Fake-Offline.cpp @@ -154,16 +154,9 @@ void FakeParams::make_edabits(const typename T::mac_type& key, int N, int ntrip, int max_size = edabitvec::MAX_SIZE; for (int i = 0; i < ntrip / max_size; i++) { - vector as(max_size); - vector bs(length); - for (int j = 0; j < max_size; j++) - { - if (not zero) - G.get_bigint(value, length, true); - as[j] = value; - for (int k = 0; k < length; k++) - bs[k] ^= BitVec(bigint((value >> k) & 1).get_si()) << j; - } + vector as; + vector bs; + plain_edabits(as, bs, length, G, zero); for (auto& a : as) files.template output_shares(a); for (auto& b : bs) @@ -737,9 +730,12 @@ int FakeParams::generate() if (nplayers == 3) { make_bits>({}, nplayers, nbitsp, zero); - make_basic>({}, nplayers, default_num, zero); - make_basic>({}, nplayers, default_num, zero); - make_with_mac_key>(nplayers, default_num, zero); + make_basic>({}, nplayers, default_num, + zero); + make_basic>({}, nplayers, + default_num, zero); + make_with_mac_key>(nplayers, + default_num, zero); make_mult_triples({}, nplayers, ntrip2, zero, prep_data_prefix); make_bits({}, nplayers, nbits2, zero); @@ -748,17 +744,21 @@ int FakeParams::generate() make_basic>({}, nplayers, default_num, zero); make_basic>>({}, nplayers, default_num, zero); + make_basic>>({}, nplayers, default_num, zero); + make_minimal({}, nplayers, default_num, zero); make_mult_triples({}, nplayers, default_num, zero, prep_data_prefix); make_bits({}, nplayers, default_num, zero); gf2n_short::reset(); - gf2n_short::init_field(40); + gf2n_short::init_field(); - Z2<41> keyt; - generate_mac_keys>(keyt, nplayers, prep_data_prefix); + Z2 keyt; + generate_mac_keys>(keyt, nplayers, + prep_data_prefix); - make_minimal>(keyt, nplayers, default_num / 64, zero); + make_minimal>(keyt, nplayers, + default_num / 64, zero); gf2n_short keytt; generate_mac_keys>(keytt, nplayers, prep_data_prefix); diff --git a/Utils/binary-example.cpp b/Utils/binary-example.cpp index 962b27753..d00acd2af 100644 --- a/Utils/binary-example.cpp +++ b/Utils/binary-example.cpp @@ -20,6 +20,7 @@ #include "GC/Secret.hpp" #include "GC/TinyPrep.hpp" #include "GC/ThreadMaster.hpp" +#include "GC/SemiSecret.hpp" #include "Protocols/Atlas.hpp" #include "Protocols/MaliciousRepPrep.hpp" #include "Protocols/Share.hpp" diff --git a/Utils/l2h-example.cpp b/Utils/l2h-example.cpp new file mode 100644 index 000000000..475bcb8aa --- /dev/null +++ b/Utils/l2h-example.cpp @@ -0,0 +1,54 @@ +/* + * l2h-example.cpp + * + */ + +#include "Protocols/ProtocolSet.h" + +#include "Math/gfp.hpp" +#include "Machines/SPDZ.hpp" + +int main(int argc, char** argv) +{ + // need player number and number of players + if (argc < 2) + { + cerr << "Usage: " << argv[0] << " " << endl; + exit(1); + } + + // set up networking on localhost + int my_number = atoi(argv[1]); + int n_parties = atoi(argv[2]); + int port_base = 9999; + Names N(my_number, n_parties, "localhost", port_base); + + // template parameters are share types for integer and GF(2^n) computation + Machine, Share> machine(N); + + // protocols to be used directly + ProtocolSet> set(machine.get_player(), machine.get_sint_mac_key()); + + // data to be used in steps + set.input.reset_all(machine.get_player()); + set.input.add_from_all(2 + my_number); + set.input.exchange(); + machine.Mp.MS.resize(n_parties); + for (int i = 0; i < n_parties; i++) + machine.Mp.MS[i] = set.input.finalize(i); + + machine.run_step("l2h_multiplication"); + machine.run_step("l2h_comparison"); + + // check results + // multiplication + assert(set.output.open(machine.Mp.MS[2], machine.get_player()) == 6); + // comparison + assert(set.output.open(machine.Mp.MS[3], machine.get_player()) == 1); + + set.check(); + + // print usage + auto res = machine.stop_threads(); + res.first.print_cost(); +} diff --git a/Utils/mixed-example.cpp b/Utils/mixed-example.cpp index a36949d6f..6eda84e03 100644 --- a/Utils/mixed-example.cpp +++ b/Utils/mixed-example.cpp @@ -6,6 +6,7 @@ #include "Protocols/ProtocolSet.h" #include "Machines/SPDZ.hpp" +#include "Machines/SPDZ2k.hpp" #include "Machines/Semi2k.hpp" #include "Machines/Rep.hpp" #include "Machines/Rep4.hpp" diff --git a/Utils/paper-example.cpp b/Utils/paper-example.cpp index 83571c218..e5346ade6 100644 --- a/Utils/paper-example.cpp +++ b/Utils/paper-example.cpp @@ -9,6 +9,7 @@ #include "Math/gfp.hpp" #include "Machines/SPDZ.hpp" +#include "Machines/SPDZ2k.hpp" #include "Machines/MalRep.hpp" #include "Machines/ShamirMachine.hpp" #include "Machines/Semi2k.hpp" @@ -30,7 +31,9 @@ int main(int argc, char** argv) // need player number and number of players if (argc < 3) { - cerr << "Usage: " << argv[0] << " [protocol [threshold]]" << endl; + cerr << "Usage: " << argv[0] + << " [protocol [threshold]]" + << endl; exit(1); } diff --git a/Yao/YaoEvalWire.cpp b/Yao/YaoEvalWire.cpp index 38cdc922e..62896b3a3 100644 --- a/Yao/YaoEvalWire.cpp +++ b/Yao/YaoEvalWire.cpp @@ -250,7 +250,7 @@ void YaoEvalWire::convcbit2s(GC::Processor& processor, for (int i = 0; i < DIV_CEIL(instruction.get_n(), unit); i++) { auto& dest = processor.S[instruction.get_r(0) + i]; - dest.resize_regs(min(unsigned(unit), instruction.get_n() - i * unit)); + dest.resize_regs(min(size_t(unit), instruction.get_n() - i * unit)); for (auto& reg : dest.get_regs()) reg.set(0); } diff --git a/Yao/YaoGarbleWire.cpp b/Yao/YaoGarbleWire.cpp index 05a8646db..e50628086 100644 --- a/Yao/YaoGarbleWire.cpp +++ b/Yao/YaoGarbleWire.cpp @@ -238,7 +238,7 @@ void YaoGarbleWire::convcbit2s(GC::Processor& processor, for (int i = 0; i < DIV_CEIL(instruction.get_n(), unit); i++) { auto& dest = processor.S[instruction.get_r(0) + i]; - int n = min(unsigned(unit), instruction.get_n() - i * unit); + int n = min(size_t(unit), instruction.get_n() - i * unit); dest.resize_regs(n); for (int j = 0; j < n; j++) dest.get_reg(j).public_input( diff --git a/Yao/YaoPlayer.cpp b/Yao/YaoPlayer.cpp index a947b1f51..b1e0e0736 100644 --- a/Yao/YaoPlayer.cpp +++ b/Yao/YaoPlayer.cpp @@ -33,7 +33,7 @@ YaoPlayer::YaoPlayer(int argc, const char** argv) "--threshold" // Flag token. ); auto& online_opts = OnlineOptions::singleton; - online_opts = {opt, argc, argv, false_type()}; + online_opts = {opt, argc, argv, false}; NetworkOptionsWithNumber network_opts(opt, argc, argv, 2, false); online_opts.finalize(opt, argc, argv); diff --git a/Yao/YaoWire.hpp b/Yao/YaoWire.hpp index aa04fe357..984db38f1 100644 --- a/Yao/YaoWire.hpp +++ b/Yao/YaoWire.hpp @@ -55,7 +55,7 @@ void YaoWire::andm(GC::Processor& processor, for (int i = 0; i < DIV_CEIL(instruction.get_n(), unit); i++) { auto &dest = processor.S[instruction.get_r(0) + i]; - int n = min(unsigned(unit), instruction.get_n() - i * unit); + int n = min(size_t(unit), instruction.get_n() - i * unit); dest.resize_regs(n); for (int j = 0; j < n; j++) if (processor.C[instruction.get_r(2) + i].get_bit(j)) diff --git a/doc/Compiler.rst b/doc/Compiler.rst index df3e13f5c..db5c1e9c2 100644 --- a/doc/Compiler.rst +++ b/doc/Compiler.rst @@ -28,12 +28,16 @@ Compiler.GC.types module .. automodule:: Compiler.GC.types :members: :no-undoc-members: - :no-inherited-members: - :show-inheritance: + :inherited-members: :exclude-members: PreOp, cbit, dynamic_array, conv_cint_vec, bitdec, bit_type, bitcom, clear_type, conv_regint, default_type, mov, dyn_sbits, int_type, mul, vec, load_mem, - DynamicArray, get_raw_input_from + DynamicArray, get_raw_input_from, bits, + input_tensor_from, input_tensor_from_client, + input_tensor_via, dot_product, Matrix, Tensor, + from_sint, read_from_file, receive_from_client, + reveal_to_clients, write_shares_to_socket, + write_to_file Compiler.library module ----------------------- diff --git a/doc/non-linear.rst b/doc/non-linear.rst index e5df4c204..969e6d6c3 100644 --- a/doc/non-linear.rst +++ b/doc/non-linear.rst @@ -56,6 +56,10 @@ Power-of-two modulus mask-and-reveal approach above to the setting of computation modulo a power of two. +See also `this slide deck +`_ for an +introduction to non-linear computation in arithmetic MPC. + Mixed-Circuit Computation ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -70,6 +74,12 @@ more general methods such as `daBits `_ and `edaBits `_. +See also `this slide deck +`_ for an introduction to +mixed-circuit computation. + + +.. _protocol-pairs: Protocol Pairs ==============