Protocol in dealer model.

This commit is contained in:
Marcel Keller
2022-04-19 15:10:18 +02:00
parent eee886570a
commit 9ef15cc2f5
186 changed files with 2008 additions and 618 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -3,6 +3,9 @@ This modules contains basic types for binary circuits. The
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 @@ import math
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 @@ class sbits(bits):
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 @@ class sbitvec(_vec):
: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 @@ class sbitvec(_vec):
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 @@ class sbitfix(_fix):
: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 @@ class sbitfixvec(_fix):
: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):

View File

@@ -15,11 +15,11 @@ from functools import reduce
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]

View File

@@ -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):

View File

@@ -337,7 +337,7 @@ def gf2n(instruction):
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 @@ def gf2n(instruction):
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 @@ class IntArgFormat(ArgFormat):
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 @@ ArgFormats = {
'i': ImmediateModpAF,
'ig': ImmediateGF2NAF,
'int': IntArgFormat,
'long': LongArgFormat,
'p': PlayerNoAF,
'str': String,
}

View File

@@ -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 tree_reduce_multithread(n_threads, function, vector):
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/<progname>``. Example:

View File

@@ -1079,14 +1079,17 @@ class MaxPool(NoVariableLayer):
(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

View File

@@ -400,6 +400,9 @@ class Program(object):
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

View File

@@ -1710,7 +1710,12 @@ class personal(Tape._no_truth):
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 @@ class Array(_vectorizable):
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 @@ class Array(_vectorizable):
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 @@ class Array(_vectorizable):
: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 @@ class SubMultiArray(_vectorizable):
""" 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 @@ class SubMultiArray(_vectorizable):
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 @@ class SubMultiArray(_vectorizable):
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(

View File

@@ -28,6 +28,7 @@ public:
static const true_type invertible;
static int size() { return 0; }
static int length() { return 256; }
static string type_string() { return "P256"; }
static void init();

View File

@@ -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 <assert.h>

View File

@@ -49,8 +49,8 @@ public:
* @param n number of values
* @returns vector of integer-like values
*/
template<class T>
vector<T> receive_outputs(int n);
template<class T, class U = T>
vector<U> receive_outputs(int n);
};
#endif /* EXTERNALIO_CLIENT_H_ */

View File

@@ -91,8 +91,8 @@ void Client::send_private_inputs(const vector<T>& values)
// Receive shares of the result and sum together.
// Also receive authenticating values.
template<class T>
vector<T> Client::receive_outputs(int n)
template<class T, class U>
vector<U> Client::receive_outputs(int n)
{
vector<T> triples(3 * n);
octetStream os;
@@ -111,7 +111,7 @@ vector<T> Client::receive_outputs(int n)
}
}
vector<T> output_values;
vector<U> output_values;
for (int i = 0; i < 3 * n; i += 3)
{
if (T(triples[i] * triples[i + 1]) != triples[i + 2])

View File

@@ -46,7 +46,7 @@
#include <sstream>
#include <fstream>
template<class T>
template<class T, class U>
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<T>(1)[0];
U result = client.receive_outputs<T>(1)[0];
cout << "Winning client id is : " << result << endl;
}
template<class T>
template<class T, class U>
void run(double salary_value, Client& client)
{
// sint
one_run<T>(long(round(salary_value)), client);
one_run<T, U>(long(round(salary_value)), client);
// sfix with f = 16
one_run<T>(long(round(salary_value * exp2(16))), client);
one_run<T, U>(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<bigint>());
cerr << "using prime " << gfp::pr() << endl;
run<gfp>(salary_value, client);
run<gfp, gfp>(salary_value, client);
break;
}
case 'R':
@@ -134,13 +134,13 @@ int main(int argc, char** argv)
switch (R)
{
case 64:
run<Z2<64>>(salary_value, client);
run<Z2<64>, Z2<64>>(salary_value, client);
break;
case 104:
run<Z2<104>>(salary_value, client);
run<Z2<104>, Z2<64>>(salary_value, client);
break;
case 128:
run<Z2<128>>(salary_value, client);
run<Z2<128>, Z2<64>>(salary_value, client);
break;
default:
cerr << R << "-bit ring not implemented";

View File

@@ -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<<sec_p;
Bval=FFTData[0].get_prime()/(2*(1+Bval));
if (Bval == 0)
throw runtime_error("distributed decryption bound is zero");
}
void FHE_Params::set_min_sec(int sec)
{
set_sec(max(sec, sec_p));
}
void FHE_Params::set_matrix_dim(int matrix_dim)
@@ -37,6 +43,13 @@ void FHE_Params::set_matrix_dim(int matrix_dim)
this->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();

View File

@@ -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<bigint>& primes);
void set(const vector<bigint>& 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<FFT_Data>& FFTD() const { return FFTData; }

View File

@@ -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<n; j++)
{ if (H[i][j]!=0 && abs(H[i][j])<mn)
{ if (H[i][j]!=0 && (abs(H[i][j])<mn || mn == 0))
{ k=j; mn=abs(H[i][j]); }
}
if (k!=-1)
@@ -207,6 +211,11 @@ void SNF_Step(matrix& S,matrix& V)
void SNF(matrix& S,const matrix& A,matrix& V)
{
int m=A.size(),n=A[0].size();
#ifdef VERBOSE
cerr << "SNF m=" << m << ", n=" << n << endl;
#endif
S=A;
ident(V,n);

View File

@@ -100,11 +100,12 @@ int generate_semi_setup(int plaintext_length, int sec,
numBits(NonInteractiveProof::slack(sec, phi_N(m))), true, params);
int lgp0 = numBits(nb.min_p0(false, 0));
int extra_slack = common_semi_setup(params, m, 2, lgp0, -1, round_up);
assert(nb.min_phi_m(lgp0, false) * 2 <= m);
load_or_generate(P2D, params.get_ring());
return extra_slack;
}
int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, bool round_up)
int common_semi_setup(FHE_Params& params, int m, bigint p, int& lgp0, int lgp1, bool round_up)
{
cout << "Need ciphertext modulus of length " << lgp0;
if (params.n_mults() > 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<GF2X> Fi(Gord);
vector<GF2X> 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;

View File

@@ -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);

View File

@@ -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)

View File

@@ -11,35 +11,15 @@ void Subs(modp& ans,const vector<int>& 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);
}
}
}

View File

@@ -40,10 +40,9 @@ template <class FD>
void PartSetup<FD>::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<P2Data>::init_field()
}
template <class FD>
void PartSetup<FD>::check(int sec) const
void PartSetup<FD>::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());
}

View File

@@ -57,7 +57,7 @@ public:
void init_field();
void check(int sec) const;
void check() const;
bool operator!=(const PartSetup<FD>& other);
void secure_init(Player& P, MachineBase& machine, int plaintext_length,

View File

@@ -69,7 +69,7 @@ void Multiplier<FD>::add(Plaintext_<FD>& res, const Ciphertext& c,
product_share.randomize(G);
bigint B = 6 * machine.setup<FD>().params.get_R();
B *= machine.setup<FD>().FieldD.get_prime();
B <<= machine.drown_sec;
B <<= machine.setup<FD>().params.secp();
// slack
B *= NonInteractiveProof::slack(machine.sec,
machine.setup<FD>().params.phi_m());

View File

@@ -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<P2Data>();
}
@@ -67,7 +67,7 @@ void PairwiseMachine::setup_keys()
{
auto& N = P;
PairwiseSetup<FD>& s = setup<FD>();
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<FD>(P), P.my_num(), P.num_players(), s.alphai);
for (auto& x : other_pks)

View File

@@ -65,11 +65,12 @@ template <class T, class U>
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"

View File

@@ -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();

View File

@@ -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<T>& MC, int nm,
int output_thread, TripleSacriFactory< Share<T> >& 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<T>();
ofstream outf;
if (write_output)

View File

@@ -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<FD>& part_setup = setup.part<FD>();
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<PartSetup<FD> > 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<Share<typename FD::T>>(P);
Plaintext_<FD> m(part_setup.FieldD);

View File

@@ -26,7 +26,6 @@ protected:
public:
int sec;
int drown_sec;
int field_size;
int extra_slack;
bool produce_inputs;

View File

@@ -15,9 +15,7 @@ TemiSetup<FD>::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<class FD>

View File

@@ -40,7 +40,7 @@ public:
return "CCD";
}
static MAC_Check* new_mc(T)
static MAC_Check* new_mc(typename super::mac_key_type)
{
return new MAC_Check;
}

69
GC/DealerPrep.h Normal file
View File

@@ -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<DealerSecret>, ShiftableTripleBuffer<DealerSecret>
{
Player* P;
public:
DealerPrep(DataPositions& usage, int = -1) :
BufferPrep<DealerSecret>(usage), P(0)
{
}
void set_protocol(DealerSecret::Protocol& protocol)
{
P = &protocol.P;
}
void buffer_triples()
{
ProtocolSetup<DealerShare<BitVec>> setup(*P);
ProtocolSet<DealerShare<BitVec>> 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<DealerSecret>::get(type, data);
}
array<DealerSecret, 3> get_triple_no_count(int n_bits)
{
if (n_bits == -1)
n_bits = DealerSecret::default_length;
return ShiftableTripleBuffer<DealerSecret>::get_triple_no_count(n_bits);
}
};
}
#endif /* GC_DEALERPREP_H_ */

View File

@@ -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 @@ public:
typedef FakeSecret DynamicType;
typedef Memory<FakeSecret> DynamicMemory;
typedef BitVec mac_key_type;
typedef BitVec clear;
typedef BitVec open_type;

View File

@@ -44,7 +44,7 @@ public:
return "Malicious CCD";
}
static MAC_Check* new_mc(T)
static MAC_Check* new_mc(typename super::mac_key_type)
{
return new MAC_Check;
}

View File

@@ -30,7 +30,7 @@ public:
typedef MaliciousRepMC<This> MC;
typedef BitVec_<unsigned char> 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 @@ public:
static const bool expensive_triples = true;
static MC* new_mc(BitVec)
static MC* new_mc(typename super::mac_key_type)
{
try
{

View File

@@ -60,35 +60,43 @@ public:
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)

View File

@@ -340,7 +340,7 @@ void Processor<T>::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 <class T>

View File

@@ -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<BitVec>, public ShareSecret<SemiSecret>
template<class T, class V>
class SemiSecretBase : public V, public ShareSecret<T>
{
typedef V super;
public:
typedef Memory<SemiSecret> DynamicMemory;
typedef Memory<T> DynamicMemory;
typedef SemiMC<SemiSecret> MC;
typedef DirectSemiMC<SemiSecret> Direct_MC;
typedef Beaver<SemiSecret> Protocol;
typedef MC MAC_Check;
typedef SemiPrep LivePrep;
typedef SemiInput<SemiSecret> Input;
typedef Beaver<T> 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<class T>
static void generate_mac_key(mac_key_type, T)
{
}
static void trans(Processor<SemiSecret>& processor, int n_outputs,
static void trans(Processor<T>& processor, int n_outputs,
const vector<int>& args);
SemiSecret()
SemiSecretBase()
{
}
SemiSecret(long other) :
SemiShare<BitVec>(other)
SemiSecretBase(long other) :
V(other)
{
}
SemiSecret(const IntBase& other) :
SemiShare<BitVec>(other)
template<class U>
SemiSecretBase(const IntBase<U>& other) :
V(other)
{
}
template<int K>
SemiSecret(const Z2<K>& other) :
SemiShare<BitVec>(other)
SemiSecretBase(const Z2<K>& other) :
V(other)
{
}
void load_clear(int n, const Integer& x);
void bitcom(Memory<SemiSecret>& S, const vector<int>& regs);
void bitdec(Memory<SemiSecret>& S, const vector<int>& regs) const;
void bitcom(Memory<T>& S, const vector<int>& regs);
void bitdec(Memory<T>& S, const vector<int>& 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<SemiSecret, SemiShare<BitVec>>
{
typedef SemiSecret This;
public:
typedef SemiSecretBase<SemiSecret, SemiShare<BitVec>> super;
typedef SemiMC<This> MC;
typedef DirectSemiMC<This> Direct_MC;
typedef MC MAC_Check;
typedef SemiInput<This> Input;
typedef SemiPrep LivePrep;
static MC* new_mc(typename SemiShare<BitVec>::mac_key_type);
SemiSecret()
{
}
template<class T>
SemiSecret(const T& other) :
super(other)
{
}
};
class DealerSecret : public SemiSecretBase<DealerSecret, DealerShare<BitVec>>
{
typedef DealerSecret This;
public:
typedef SemiSecretBase<DealerSecret, DealerShare<BitVec>> super;
typedef DealerMC<This> MC;
typedef DirectDealerMC<This> Direct_MC;
typedef MC MAC_Check;
typedef DealerInput<This> Input;
typedef DealerPrep LivePrep;
static MC* new_mc(typename super::mac_key_type);
DealerSecret()
{
}
template<class T>
DealerSecret(const T& other) :
super(other)
{
}
};
} /* namespace GC */
#endif /* GC_SEMISECRET_H_ */

View File

@@ -4,17 +4,20 @@
*/
#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<class T, class V>
const int SemiSecretBase<T, V>::default_length;
SemiSecret::MC* SemiSecret::new_mc(mac_key_type)
inline
SemiSecret::MC* SemiSecret::new_mc(
typename super::mac_key_type)
{
if (OnlineOptions::singleton.direct)
return new Direct_MC;
@@ -22,7 +25,18 @@ SemiSecret::MC* SemiSecret::new_mc(mac_key_type)
return new MC;
}
void SemiSecret::trans(Processor<SemiSecret>& processor, int n_outputs,
inline
DealerSecret::MC* DealerSecret::new_mc(
typename super::mac_key_type)
{
if (OnlineOptions::singleton.direct)
return new Direct_MC;
else
return new MC;
}
template<class T, class V>
void SemiSecretBase<T, V>::trans(Processor<T>& processor, int n_outputs,
const vector<int>& args)
{
int N_BITS = default_length;
@@ -46,29 +60,33 @@ void SemiSecret::trans(Processor<SemiSecret>& processor, int n_outputs,
}
}
void SemiSecret::load_clear(int n, const Integer& x)
template<class T, class V>
void SemiSecretBase<T, V>::load_clear(int n, const Integer& x)
{
check_length(n, x);
*this = constant(x, ShareThread<SemiSecret>::s().P->my_num());
this->check_length(n, x);
*this = this->constant(x, ShareThread<T>::s().P->my_num());
}
void SemiSecret::bitcom(Memory<SemiSecret>& S, const vector<int>& regs)
template<class T, class V>
void SemiSecretBase<T, V>::bitcom(Memory<T>& S, const vector<int>& regs)
{
*this = 0;
for (unsigned int i = 0; i < regs.size(); i++)
*this ^= (S[regs[i]] << i);
}
void SemiSecret::bitdec(Memory<SemiSecret>& S,
template<class T, class V>
void SemiSecretBase<T, V>::bitdec(Memory<T>& S,
const vector<int>& 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<class T, class V>
void SemiSecretBase<T, V>::reveal(size_t n_bits, Clear& x)
{
auto& thread = ShareThread<SemiSecret>::s();
auto& thread = ShareThread<T>::s();
x = thread.MC->POpen(*this, *thread.P).mask(n_bits);
}

View File

@@ -112,8 +112,8 @@ public:
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 @@ public:
typedef ReplicatedMC<This> MC;
typedef BitVec_<unsigned char> open_type;
typedef open_type clear;
typedef BitVec mac_key_type;
typedef NoValue mac_key_type;
static MC* new_mc(mac_key_type)
{

View File

@@ -11,6 +11,8 @@
#include "instructions.h"
#include "Tools/benchmarking.h"
#include "Machine.hpp"
namespace GC
@@ -58,15 +60,10 @@ Thread<T>* ThreadMaster<T>::new_thread(int i)
template<class T>
void ThreadMaster<T>::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");

View File

@@ -48,12 +48,12 @@ public:
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;
}

View File

@@ -5,6 +5,7 @@
#include "Protocols/Spdz2kShare.h"
#include "Protocols/Spdz2kPrep.h"
#include "Protocols/SPDZ2k.h"
#include "GC/TinySecret.h"
#include "GC/TinyMC.h"

View File

@@ -19,3 +19,4 @@
#include "Protocols/SemiMC.hpp"
#include "Protocols/Beaver.hpp"
#include "Protocols/MalRepRingPrep.hpp"
#include "GC/SemiSecret.hpp"

View File

@@ -97,6 +97,5 @@ ShamirMachineSpec<T>::ShamirMachineSpec(int argc, const char** argv)
auto& opts = ShamirOptions::singleton;
ez::ezOptionParser opt;
opts = {opt, argc, argv};
T<gfp>::bit_type::part_type::open_type::init_field();
HonestMajorityFieldMachine<T>(argc, argv, opt, opts.nparties);
}

View File

@@ -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();

View File

@@ -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<DealerRingShare, DealerShare>(argc, argv, 0);
}

View File

@@ -54,9 +54,8 @@ int main(int argc, const char** argv)
{
#define X(L) \
case L: \
Machine<FakeShare<SignedZ2<L>>, FakeShare<gf2n>>(0, N, progname, \
online_opts.memtype, gf2n::default_degree(), 0, 0, 0, 0, false, \
online_opts.live_prep, online_opts).run(); \
Machine<FakeShare<SignedZ2<L>>, FakeShare<gf2n>>(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

View File

@@ -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)

View File

@@ -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<GC::MaliciousCcdSecret<gf2n_short>>(argc, argv, opt);
}

View File

@@ -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"

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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<GC::TinierSecret<gf2n_short>>(argc, argv, 1000);
}

View File

@@ -29,5 +29,5 @@
int main(int argc, const char** argv)
{
GC::simple_binary_main<GC::TinySecret<40>>(argc, argv, 1000);
GC::simple_binary_main<GC::TinySecret<DEFAULT_SECURITY>>(argc, argv, 1000);
}

View File

@@ -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

View File

@@ -37,8 +37,6 @@ public:
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; }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -18,7 +18,7 @@ bool gf2n_<U>::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_<U>::init_tables()
}
}
template<class U>
void gf2n_<U>::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_<U>::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_<U> gf2n_<U>::invert() const
if (n < 64)
return U(invert<word>(a));
else
return invert<bit_plus<U>>(a).get_lower();
{
gf2n_ res;
res.a = invert<int128>(a).get_lower();
return res;
}
}
template<>

View File

@@ -65,6 +65,7 @@ protected:
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 @@ public:
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);

View File

@@ -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<vector<bool>>& channels,
const vector<octetStream>& to_send,
vector<octetStream>& 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<octetStream>& os) const
{
vector<octetStream> to_send(P.num_players(), os[P.my_num()]);
vector<vector<bool>> channels(P.num_players(),
vector<bool>(P.num_players(), true));
for (auto& x: channels)
x.back() = false;
channels.back() = vector<bool>(P.num_players(), false);
vector<octetStream> 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

View File

@@ -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;

View File

@@ -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 @@ public:
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 @@ public:
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<octetStream>& 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<octetStream>&) const
{ throw not_implemented(); }
virtual void unchecked_broadcast(vector<octetStream>& o) const
{ Broadcast_Receive(o); }
virtual void send_receive_all(const vector<octetStream>&,
vector<octetStream>&) const
{ throw not_implemented(); }
void reset_stats();
};
/**
@@ -230,8 +240,8 @@ public:
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 @@ public:
* 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 @@ public:
* 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 @@ public:
* Assumes o[player_no] contains the data to be broadcast by me.
*/
virtual void Broadcast_Receive(vector<octetStream>& o) const;
virtual void Broadcast_Receive_no_stats(vector<octetStream>& o) const = 0;
virtual void Broadcast_Receive_no_stats(vector<octetStream>&) const
{ throw runtime_error("implement broadcast"); }
/**
* Run protocol to verify broadcast is correct

View File

@@ -15,6 +15,7 @@
#include "Protocols/MAC_Check.hpp"
#include "Protocols/SemiInput.hpp"
#include "Protocols/SemiMC.hpp"
#include "Protocols/mac_key.hpp"
#include <sstream>
#include <fstream>
@@ -274,9 +275,9 @@ void NPartyTripleGenerator<W>::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<T>::sacrifice(typename T::MAC_Check& MC, PRNG& G)
auto& outputFile = this->outputFile;
auto& uncheckedTriples = this->uncheckedTriples;
assert(T::clear::length() >= 40);
check_field_size<typename T::clear>();
vector<T> maskedAs(nTriplesPerLoop);
vector<TripleToSacrifice<T> > maskedTriples(nTriplesPerLoop);
@@ -744,6 +745,8 @@ void Spdz2kTripleGenerator<W>::sacrificeZ2k(U& MC, PRNG& G)
// and first part of [sigma], i.e., t * [c] - [chat]
maskedTriples[j].template prepare_sacrifice<W>(uncheckedTriples[j], G);
maskedAs[j] = maskedTriples[j].a[0];
// enough randomness in values
MC.set_random_element({});
}
vector<T> openedAs(nTriplesPerLoop);
@@ -754,6 +757,8 @@ void Spdz2kTripleGenerator<W>::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<T> open_sigmas;

View File

@@ -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<nprogs; i++)

View File

@@ -299,9 +299,7 @@ template<int>
void Sub_Data_Files<T>::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,

View File

@@ -26,7 +26,7 @@ class InputBase
typedef typename T::clear clear;
protected:
Player* P;
PlayerBase* P;
int my_num;
Buffer<typename T::clear, typename T::clear> buffer;
@@ -63,7 +63,7 @@ public:
/// 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;

View File

@@ -81,7 +81,7 @@ void InputBase<T>::reset(int player)
}
template<class T>
void InputBase<T>::reset_all(Player& P)
void InputBase<T>::reset_all(PlayerBase& P)
{
this->P = &P;
my_num = P.my_num();

View File

@@ -328,14 +328,14 @@ protected:
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<int> 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<int>& get_start() const { return start; }
int get_opcode() const { return opcode; }
int get_size() const { return size; }
@@ -350,7 +350,7 @@ public:
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;

View File

@@ -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<sint, sgf2n>& 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<sint, sgf2n>& 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<sint, sgf2n>& 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], {}, {});

View File

@@ -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<DataPositions, NamedCommStats> 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_ */

View File

@@ -24,28 +24,52 @@
using namespace std;
template<class sint, class sgf2n>
Machine<sint, sgf2n>::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<sint, sgf2n>::init_binary_domains(int security_parameter, int lg2)
{
sgf2n::clear::init_field(lg2);
if (not is_same<typename sgf2n::mac_key_type, GC::NoValue>())
{
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<typename sint::bit_type::mac_key_type, GC::NoValue>())
{
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<class sint, class sgf2n>
Machine<sint, sgf2n>::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<sint>(), 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<sint, sgf2n>::Machine(int my_number, Names& playerNames,
sint::clear::next::template init<typename sint::clear>(false);
// Initialize the global memory
auto memtype = opts.memtype;
if (memtype.compare("old")==0)
{
ifstream inpf;
@@ -92,9 +117,18 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
{ cerr << "Invalid memory argument" << endl;
exit(1);
}
}
template<class sint, class sgf2n>
void Machine<sint, sgf2n>::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<sint, sgf2n>::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<sint, sgf2n>::Machine(int my_number, Names& playerNames,
queues.resize(nthreads);
join_timer.resize(nthreads);
for (int i=0; i<nthreads; i++)
for (int i = old_n_threads; i < nthreads; i++)
{
queues[i] = new ThreadQueue;
// stand-in for initialization
@@ -146,7 +180,7 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
}
// synchronize with clients before starting timer
for (int i=0; i<nthreads; i++)
for (int i=old_n_threads; i<nthreads; i++)
{
queues[i]->result();
}
@@ -155,6 +189,9 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
template<class sint, class sgf2n>
Machine<sint, sgf2n>::~Machine()
{
sint::LivePrep::teardown();
sgf2n::LivePrep::teardown();
delete P;
for (auto& queue : queues)
delete queue;
@@ -308,14 +345,12 @@ DataPositions Machine<sint, sgf2n>::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<sint, sgf2n>::join_tape(int i)
}
template<class sint, class sgf2n>
void Machine<sint, sgf2n>::run()
void Machine<sint, sgf2n>::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<class sint, class sgf2n>
pair<DataPositions, NamedCommStats> Machine<sint, sgf2n>::stop_threads()
{
// Tell all C-threads to stop
for (int i=0; i<nthreads; i++)
{
//printf("Send kill signal to client\n");
//printf("Send kill signal to client\n");
queues[i]->schedule(-1);
}
@@ -369,6 +401,40 @@ void Machine<sint, sgf2n>::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<class sint, class sgf2n>
void Machine<sint, sgf2n>::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<sint, sgf2n>::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<sint, sgf2n>::run()
stats.print();
}
#ifndef INSECURE
if (not opts.file_prep_per_thread)
{
Data_Files<sint, sgf2n> df(*this);
df.seekg(pos);
df.prune();
}
#endif
sint::LivePrep::teardown();
sgf2n::LivePrep::teardown();
suggest_optimizations();

View File

@@ -37,13 +37,16 @@ template<class T, class U>
int OfflineMachine<W>::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<T, U>::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<typename T::bit_type> thread(bit_prep, P, binary_mac_key);
// setup before generation to fix prime
T::LivePrep::basic_setup(P);
generate<T>();
generate<typename T::bit_type::part_type>();
generate<U>();

View File

@@ -100,6 +100,9 @@ void thread_info<sint, sgf2n>::Sub_Main_Func()
processor = new Processor<sint, sgf2n>(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<sint, sgf2n>::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();

View File

@@ -17,11 +17,11 @@ protected:
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;

View File

@@ -18,7 +18,7 @@ template<class T, class U>
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<T, U>();
@@ -28,8 +28,7 @@ template<class V>
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<T, U>(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<T, U>(playerNames, use_encryption, online_opts, lg2).run(
online_opts.progname);
if (online_opts.verbose)
{

View File

@@ -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] [<playerno>] <progname>";
@@ -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<string> 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)

View File

@@ -26,21 +26,26 @@ public:
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<class T>
OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv, T,
bool default_live_prep = true);
template<class T>
OnlineOptions(T);
~OnlineOptions() {}
void finalize(ez::ezOptionParser& opt, int argc, const char** argv);

View File

@@ -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<class T>
OnlineOptions::OnlineOptions(T) : OnlineOptions()
{
if (T::dishonest_majority)
batch_size = 1000;
}
#endif /* PROCESSOR_ONLINEOPTIONS_HPP_ */

View File

@@ -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);

View File

@@ -65,7 +65,7 @@ HonestMajorityRingMachineWithSecurity<U, V>::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<U, V>::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)

View File

@@ -9,8 +9,7 @@
#include <iostream>
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)

View File

@@ -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);
};

View File

@@ -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),) \

View File

@@ -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())

View File

@@ -0,0 +1 @@
(sint.load_mem(0) * sint.load_mem(1)).store_in_mem(2)

View File

@@ -23,6 +23,7 @@ class Player;
template<class T>
class Beaver : public ProtocolBase<T>
{
protected:
vector<T> shares;
vector<typename T::open_type> opened;
vector<array<T, 3>> triples;

View File

@@ -43,15 +43,16 @@ void ChaiGearPrep<T>::basic_setup(Player& P)
assert(machine == 0);
machine = new MultiplicativeMachine;
auto& setup = machine->setup.part<FD>();
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<typename FD::T>();
#ifdef VERBOSE
cerr << T::type_string() << " parameter setup took " << timer.elapsed()

View File

@@ -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"))

View File

@@ -16,7 +16,6 @@ public:
static CowGearOptions singleton;
int covert_security;
int lowgear_security;
CowGearOptions(bool covert = true);
CowGearOptions(ez::ezOptionParser& opt, int argc, const char** argv,

View File

@@ -38,14 +38,15 @@ void CowGearPrep<T>::basic_setup(Player& P)
pairwise_machine = new PairwiseMachine(P);
auto& machine = *pairwise_machine;
auto& setup = machine.setup<FD>();
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<typename FD::T>();
#ifdef VERBOSE
cerr << T::type_string() << " parameter setup took " << timer.elapsed()

View File

@@ -9,10 +9,12 @@
template<class T>
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;

View File

@@ -11,6 +11,12 @@
#include <math.h>
template<class T>
DabitSacrifice<T>::DabitSacrifice() :
S(OnlineOptions::singleton.security_parameter)
{
}
template<class T>
dabit<T>& operator+=(dabit<T>& x, const dabit<T>& y)
{

38
Protocols/DealerInput.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* DealerInput.h
*
*/
#ifndef PROTOCOLS_DEALERINPUT_H_
#define PROTOCOLS_DEALERINPUT_H_
#include "../Networking/AllButLastPlayer.h"
#include "Processor/Input.h"
template<class T>
class DealerInput : public InputBase<T>
{
Player& P;
octetStreams to_send, to_receive;
SeededPRNG G;
vector<SemiShare<typename T::clear>> shares;
bool from_dealer;
AllButLastPlayer sub_player;
SemiInput<SemiShare<typename T::clear>>* internal;
public:
DealerInput(SubProcessor<T>& proc, typename T::MAC_Check&);
DealerInput(typename T::MAC_Check&, Preprocessing<T>&, 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_ */

115
Protocols/DealerInput.hpp Normal file
View File

@@ -0,0 +1,115 @@
/*
* DealerInput.hpp
*
*/
#ifndef PROTOCOLS_DEALERINPUT_HPP_
#define PROTOCOLS_DEALERINPUT_HPP_
#include "DealerInput.h"
template<class T>
DealerInput<T>::DealerInput(SubProcessor<T>& proc, typename T::MAC_Check&) :
DealerInput(proc.P)
{
}
template<class T>
DealerInput<T>::DealerInput(typename T::MAC_Check&, Preprocessing<T>&,
Player& P) :
DealerInput(P)
{
}
template<class T>
DealerInput<T>::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<SemiShare<typename T::clear>>(0, sub_player);
}
template<class T>
DealerInput<T>::~DealerInput()
{
if (internal)
delete internal;
}
template<class T>
bool DealerInput<T>::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<class T>
void DealerInput<T>::reset(int player)
{
if (player == 0)
{
to_send.reset(P);
from_dealer = false;
}
else if (not is_dealer())
internal->reset(player - 1);
}
template<class T>
void DealerInput<T>::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<class T>
void DealerInput<T>::add_other(int player, int)
{
if (is_dealer(player))
from_dealer = true;
else if (not is_dealer())
internal->add_other(player);
}
template<class T>
void DealerInput<T>::exchange()
{
if (from_dealer)
{
vector<bool> senders(P.num_players());
senders.back() = true;
P.send_receive_all(senders, to_send, to_receive);
}
else if (not is_dealer())
internal->exchange();
}
template<class T>
T DealerInput<T>::finalize(int player, int)
{
if (is_dealer())
return {};
else
{
if (is_dealer(player))
return to_receive.back().template get<T>();
else
return internal->finalize(player);
}
}
#endif /* PROTOCOLS_DEALERINPUT_HPP_ */

Some files were not shown because too many files have changed in this diff Show More