mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-01-09 05:27:56 -05:00
Distributed key generation for homomorphic encryption with active security.
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,6 +1,14 @@
|
||||
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.2.2 (Jan 21, 2020)
|
||||
## 0.2.3 (Feb 23, 2021)
|
||||
|
||||
- Distributed key generation for homomorphic encryption with active security similar to [Rotaru et al.](https://eprint.iacr.org/2019/1300)
|
||||
- Homomorphic encryption parameters more similar to SCALE-MAMBA
|
||||
- Fixed security bug: all-zero secret keys in homomorphic encryption
|
||||
- Fixed security bug: missing check in binary Rep4
|
||||
- Fixed security bug: insufficient "blaming" (covert security) in CowGear and HighGear due to low default security parameter
|
||||
|
||||
## 0.2.2 (Jan 21, 2021)
|
||||
|
||||
- Infrastructure for random element generation
|
||||
- Programs generating as much preprocessing data as required by a particular high-level program
|
||||
|
||||
@@ -490,6 +490,9 @@ class bitb(NonVectorInstruction):
|
||||
code = opcodes['BITB']
|
||||
arg_format = ['sbw']
|
||||
|
||||
def add_usage(self, req_node):
|
||||
req_node.increment(('bit', 'bit'), 1)
|
||||
|
||||
class reveal(BinaryVectorInstruction, base.VarArgsInstruction, base.Mergeable):
|
||||
""" Reveal secret bit register vectors and copy result to clear bit
|
||||
register vectors.
|
||||
@@ -519,6 +522,10 @@ class inputb(base.DoNotEliminateInstruction, base.VarArgsInstruction):
|
||||
arg_format = tools.cycle(['p','int','int','sbw'])
|
||||
is_vec = lambda self: True
|
||||
|
||||
def add_usage(self, req_node):
|
||||
for i in range(0, len(self.args), 4):
|
||||
req_node.increment(('bit', 'input', self.args[0]), self.args[1])
|
||||
|
||||
class inputbvec(base.DoNotEliminateInstruction, base.VarArgsInstruction,
|
||||
base.Mergeable):
|
||||
""" Copy private input to secret bit registers bit by bit. The input is
|
||||
@@ -538,17 +545,26 @@ class inputbvec(base.DoNotEliminateInstruction, base.VarArgsInstruction,
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.arg_format = []
|
||||
for x in self.get_arg_tuples(args):
|
||||
self.arg_format += ['int', 'int', 'p'] + ['sbw'] * (x[0] - 3)
|
||||
super(inputbvec, self).__init__(*args, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def get_arg_tuples(args):
|
||||
i = 0
|
||||
while i < len(args):
|
||||
self.arg_format += ['int', 'int', 'p'] + ['sbw'] * (args[i] - 3)
|
||||
yield args[i:i+args[i]]
|
||||
i += args[i]
|
||||
assert i == len(args)
|
||||
super(inputbvec, self).__init__(*args, **kwargs)
|
||||
|
||||
def merge(self, other):
|
||||
self.args += other.args
|
||||
self.arg_format += other.arg_format
|
||||
|
||||
def add_usage(self, req_node):
|
||||
for x in self.get_arg_tuples(self.args):
|
||||
req_node.increment(('bit', 'input', x[2]), x[0] - 3)
|
||||
|
||||
class print_regb(base.VectorInstruction, base.IOInstruction):
|
||||
""" Debug output of clear bit register.
|
||||
|
||||
|
||||
@@ -371,6 +371,14 @@ class Merger:
|
||||
# hack
|
||||
warned_about_mem.append(True)
|
||||
|
||||
def strict_mem_access(n, last_this_kind, last_other_kind):
|
||||
if last_other_kind and last_this_kind and \
|
||||
last_other_kind[-1] > last_this_kind[-1]:
|
||||
last_this_kind[:] = []
|
||||
last_this_kind.append(n)
|
||||
for i in last_other_kind:
|
||||
add_edge(i, n)
|
||||
|
||||
def keep_order(instr, n, t, arg_index=None):
|
||||
if arg_index is None:
|
||||
player = None
|
||||
@@ -444,26 +452,17 @@ class Merger:
|
||||
|
||||
if isinstance(instr, ReadMemoryInstruction):
|
||||
if options.preserve_mem_order:
|
||||
if last_mem_write and last_mem_read and last_mem_write[-1] > last_mem_read[-1]:
|
||||
last_mem_read[:] = []
|
||||
last_mem_read.append(n)
|
||||
for i in last_mem_write:
|
||||
add_edge(i, n)
|
||||
strict_mem_access(n, last_mem_read, last_mem_write)
|
||||
else:
|
||||
mem_access(n, instr, last_mem_read_of, last_mem_write_of)
|
||||
elif isinstance(instr, WriteMemoryInstruction):
|
||||
if options.preserve_mem_order:
|
||||
if last_mem_write and last_mem_read and last_mem_write[-1] < last_mem_read[-1]:
|
||||
last_mem_write[:] = []
|
||||
last_mem_write.append(n)
|
||||
for i in last_mem_read:
|
||||
add_edge(i, n)
|
||||
strict_mem_access(n, last_mem_write, last_mem_read)
|
||||
else:
|
||||
mem_access(n, instr, last_mem_write_of, last_mem_read_of)
|
||||
elif isinstance(instr, matmulsm):
|
||||
if options.preserve_mem_order:
|
||||
for i in last_mem_write:
|
||||
add_edge(i, n)
|
||||
strict_mem_access(n, last_mem_read, last_mem_write)
|
||||
else:
|
||||
for i in last_mem_write_of.values():
|
||||
for j in i:
|
||||
|
||||
@@ -452,6 +452,11 @@ def CarryOutRaw(a, b, c=0):
|
||||
assert len(a) == len(b)
|
||||
k = len(a)
|
||||
from . import types
|
||||
if program.linear_rounds():
|
||||
carry = 0
|
||||
for (ai, bi) in zip(a, b):
|
||||
carry = bi.carry_out(ai, carry)
|
||||
return carry
|
||||
d = [program.curr_block.new_reg('s') for i in range(k)]
|
||||
s = [program.curr_block.new_reg('s') for i in range(3)]
|
||||
for i in range(k):
|
||||
|
||||
112
Compiler/ml.py
112
Compiler/ml.py
@@ -627,15 +627,14 @@ class Dense(DenseBase):
|
||||
:param d_out: output dimension
|
||||
"""
|
||||
def __init__(self, N, d_in, d_out, d=1, activation='id', debug=False):
|
||||
self.activation = activation
|
||||
if activation == 'id':
|
||||
self.f = lambda x: x
|
||||
self.activation_layer = None
|
||||
elif activation == 'relu':
|
||||
self.f = relu
|
||||
self.f_prime = relu_prime
|
||||
elif activation == 'sigmoid':
|
||||
self.f = sigmoid
|
||||
self.f_prime = sigmoid_prime
|
||||
self.activation_layer = Relu([N, d, d_out])
|
||||
elif activation == 'square':
|
||||
self.activation_layer = Square([N, d, d_out])
|
||||
else:
|
||||
raise CompilerError('activation not supported: %s', activation)
|
||||
|
||||
self.N = N
|
||||
self.d_in = d_in
|
||||
@@ -652,10 +651,16 @@ class Dense(DenseBase):
|
||||
self.nabla_W = sfix.Matrix(d_in, d_out)
|
||||
self.nabla_b = sfix.Array(d_out)
|
||||
|
||||
self.f_input = MultiArray([N, d, d_out], sfix)
|
||||
|
||||
self.debug = debug
|
||||
|
||||
l = self.activation_layer
|
||||
if l:
|
||||
self.f_input = l.X
|
||||
l.Y = self.Y
|
||||
l.nabla_Y = self.nabla_Y
|
||||
else:
|
||||
self.f_input = self.Y
|
||||
|
||||
def reset(self):
|
||||
d_in = self.d_in
|
||||
d_out = self.d_out
|
||||
@@ -699,10 +704,8 @@ class Dense(DenseBase):
|
||||
|
||||
def forward(self, batch=None):
|
||||
self.compute_f_input(batch=batch)
|
||||
@multithread(self.n_threads, len(batch), 128)
|
||||
def _(base, size):
|
||||
self.Y.assign_part_vector(self.f(
|
||||
self.f_input.get_part_vector(base, size)), base)
|
||||
if self.activation_layer:
|
||||
self.activation_layer.forward(batch)
|
||||
if self.debug:
|
||||
limit = self.debug
|
||||
@for_range_opt(len(batch))
|
||||
@@ -731,26 +734,11 @@ class Dense(DenseBase):
|
||||
nabla_W = self.nabla_W
|
||||
nabla_b = self.nabla_b
|
||||
|
||||
if self.activation == 'id':
|
||||
f_schur_Y = nabla_Y
|
||||
if self.activation_layer:
|
||||
self.activation_layer.backward(batch)
|
||||
f_schur_Y = self.activation_layer.nabla_X
|
||||
else:
|
||||
f_prime_bit = MultiArray([N, d, d_out], sint)
|
||||
f_schur_Y = MultiArray([N, d, d_out], sfix)
|
||||
|
||||
@multithread(self.n_threads, f_prime_bit.total_size())
|
||||
def _(base, size):
|
||||
f_prime_bit.assign_vector(
|
||||
self.f_prime(self.f_input.get_vector(base, size)), base)
|
||||
|
||||
progress('f prime')
|
||||
|
||||
@multithread(self.n_threads, f_prime_bit.total_size())
|
||||
def _(base, size):
|
||||
f_schur_Y.assign_vector(nabla_Y.get_vector(base, size) *
|
||||
f_prime_bit.get_vector(base, size),
|
||||
base)
|
||||
|
||||
progress('f prime schur Y')
|
||||
f_schur_Y = nabla_Y
|
||||
|
||||
if compute_nabla_X:
|
||||
@multithread(self.n_threads, N)
|
||||
@@ -841,35 +829,55 @@ class Dropout:
|
||||
def backward(self):
|
||||
self.nabla_X = self.nabla_Y.schur(self.B)
|
||||
|
||||
class Relu(NoVariableLayer):
|
||||
class ElementWiseLayer(NoVariableLayer):
|
||||
def __init__(self, shape, inputs=None):
|
||||
self.X = Tensor(shape, sfix)
|
||||
self.Y = Tensor(shape, sfix)
|
||||
self.nabla_X = Tensor(shape, sfix)
|
||||
self.nabla_Y = Tensor(shape, sfix)
|
||||
self.inputs = inputs
|
||||
|
||||
def forward(self, batch=[0]):
|
||||
@multithread(self.n_threads, len(batch), 128)
|
||||
def _(base, size):
|
||||
self.Y.assign_part_vector(self.f(
|
||||
self.X.get_part_vector(base, size)), base)
|
||||
|
||||
def backward(self, batch):
|
||||
f_prime_bit = MultiArray(self.X.sizes, self.prime_type)
|
||||
|
||||
@multithread(self.n_threads, f_prime_bit.total_size())
|
||||
def _(base, size):
|
||||
f_prime_bit.assign_vector(
|
||||
self.f_prime(self.X.get_vector(base, size)), base)
|
||||
|
||||
progress('f prime')
|
||||
|
||||
@multithread(self.n_threads, f_prime_bit.total_size())
|
||||
def _(base, size):
|
||||
self.nabla_X.assign_vector(self.nabla_Y.get_vector(base, size) *
|
||||
f_prime_bit.get_vector(base, size),
|
||||
base)
|
||||
|
||||
progress('f prime schur Y')
|
||||
|
||||
class Relu(ElementWiseLayer):
|
||||
""" Fixed-point ReLU layer.
|
||||
|
||||
:param shape: input/output shape (tuple/list of int)
|
||||
"""
|
||||
def __init__(self, shape, inputs=None):
|
||||
self.X = Tensor(shape, sfix)
|
||||
self.Y = Tensor(shape, sfix)
|
||||
self.inputs = inputs
|
||||
f = staticmethod(relu)
|
||||
f_prime = staticmethod(relu_prime)
|
||||
prime_type = sint
|
||||
|
||||
def forward(self, batch=[0]):
|
||||
assert len(batch) == 1
|
||||
@multithread(self.n_threads, self.X[batch[0]].total_size())
|
||||
def _(base, size):
|
||||
tmp = relu(self.X[batch[0]].get_vector(base, size))
|
||||
self.Y[batch[0]].assign_vector(tmp, base)
|
||||
|
||||
class Square(NoVariableLayer):
|
||||
class Square(ElementWiseLayer):
|
||||
""" Fixed-point square layer.
|
||||
|
||||
:param shape: input/output shape (tuple/list of int)
|
||||
"""
|
||||
def __init__(self, shape):
|
||||
self.X = MultiArray(shape, sfix)
|
||||
self.Y = MultiArray(shape, sfix)
|
||||
|
||||
def forward(self, batch=[0]):
|
||||
assert len(batch) == 1
|
||||
self.Y.assign_vector(self.X.get_part_vector(batch[0]) ** 2)
|
||||
f = staticmethod(lambda x: x ** 2)
|
||||
f_prime = staticmethod(lambda x: cfix(2, size=x.size) * x)
|
||||
prime_type = sfix
|
||||
|
||||
class MaxPool(NoVariableLayer):
|
||||
""" Fixed-point MaxPool layer.
|
||||
|
||||
@@ -150,6 +150,7 @@ class Program(object):
|
||||
self.use_split(int(options.split))
|
||||
self._square = False
|
||||
self._always_raw = False
|
||||
self._linear_rounds = False
|
||||
self.warn_about_mem = [True]
|
||||
Program.prog = self
|
||||
from . import instructions_base, instructions, types, comparison
|
||||
@@ -461,6 +462,12 @@ class Program(object):
|
||||
else:
|
||||
self._always_raw = change
|
||||
|
||||
def linear_rounds(self, change=None):
|
||||
if change is None:
|
||||
return self._linear_rounds
|
||||
else:
|
||||
self._linear_rounds = change
|
||||
|
||||
def options_from_args(self):
|
||||
""" Set a number of options from the command-line arguments. """
|
||||
if 'trunc_pr' in self.args:
|
||||
@@ -475,6 +482,8 @@ class Program(object):
|
||||
self.always_raw(True)
|
||||
if 'edabit' in self.args:
|
||||
self.use_edabit(True)
|
||||
if 'linear_rounds' in self.args:
|
||||
self.linear_rounds(True)
|
||||
|
||||
def disable_memory_warnings(self):
|
||||
self.warn_about_mem.append(False)
|
||||
@@ -855,7 +864,9 @@ class Tape:
|
||||
filename = self.program.programs_dir + '/Bytecode/' + filename
|
||||
print('Writing to', filename)
|
||||
f = open(filename, 'wb')
|
||||
f.write(self.get_bytes())
|
||||
for i in self._get_instructions():
|
||||
if i is not None:
|
||||
f.write(i.get_bytes())
|
||||
f.close()
|
||||
|
||||
def new_reg(self, reg_type, size=None):
|
||||
|
||||
@@ -267,7 +267,7 @@ class _number(object):
|
||||
def __pow__(self, exp):
|
||||
""" Exponentation through square-and-multiply.
|
||||
|
||||
:param exp: compile-time (int) """
|
||||
:param exp: any type allowing bit decomposition """
|
||||
if isinstance(exp, int) and exp >= 0:
|
||||
if exp == 0:
|
||||
return self.__class__(1)
|
||||
@@ -425,6 +425,10 @@ class _bit(object):
|
||||
:rtype: depending on inputs (secret if any of them is) """
|
||||
return self ^ other, self & other
|
||||
|
||||
def carry_out(self, a, b):
|
||||
s = a ^ b
|
||||
return a ^ (s & (self ^ a))
|
||||
|
||||
class _gf2n(_bit):
|
||||
""" :math:`\mathrm{GF}(2^n)` functionality. """
|
||||
|
||||
@@ -5247,6 +5251,7 @@ class MemValue(_mem):
|
||||
bit_decompose = lambda self,*args,**kwargs: self.read().bit_decompose(*args, **kwargs)
|
||||
|
||||
if_else = lambda self,*args,**kwargs: self.read().if_else(*args, **kwargs)
|
||||
bit_and = lambda self,other: self.read().bit_and(other)
|
||||
|
||||
def expand_to_vector(self, size=None):
|
||||
if program.curr_block == self.last_write_block:
|
||||
|
||||
@@ -35,13 +35,14 @@ int DiscreteGauss::sample(PRNG &G, int stretch) const
|
||||
void RandomVectors::set(int nn,int hh,double R)
|
||||
{
|
||||
n=nn;
|
||||
if (hh > 0)
|
||||
h=hh;
|
||||
h=hh;
|
||||
DG.set(R);
|
||||
assert(h > 0);
|
||||
}
|
||||
|
||||
|
||||
void RandomVectors::set_n(int nn)
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
|
||||
vector<bigint> RandomVectors::sample_Gauss(PRNG& G, int stretch) const
|
||||
{
|
||||
@@ -54,8 +55,7 @@ vector<bigint> RandomVectors::sample_Gauss(PRNG& G, int stretch) const
|
||||
|
||||
vector<bigint> RandomVectors::sample_Hwt(PRNG& G) const
|
||||
{
|
||||
assert(h > 0);
|
||||
if (h>n/2) { return sample_Gauss(G); }
|
||||
if (h > n/2 or h <= 0) { return sample_Gauss(G); }
|
||||
vector<bigint> ans(n);
|
||||
for (int i=0; i<n; i++) { ans[i]=0; }
|
||||
int cnt=0,j=0;
|
||||
|
||||
@@ -48,10 +48,11 @@ class RandomVectors
|
||||
public:
|
||||
|
||||
void set(int nn,int hh,double R); // R is input STANDARD DEVIATION
|
||||
void set_n(int nn);
|
||||
|
||||
void pack(octetStream& o) const { o.store(n); o.store(h); DG.pack(o); }
|
||||
void unpack(octetStream& o)
|
||||
{ o.get(n); o.get(h); DG.unpack(o); if(h <= 0) throw exception(); }
|
||||
{ o.get(n); o.get(h); DG.unpack(o); }
|
||||
|
||||
RandomVectors(int h, double R) : RandomVectors(0, h, R) {}
|
||||
RandomVectors(int nn,int hh,double R) : DG(R) { set(nn,hh,R); }
|
||||
@@ -61,6 +62,7 @@ class RandomVectors
|
||||
|
||||
double get_R() const { return DG.get_R(); }
|
||||
DiscreteGauss get_DG() const { return DG; }
|
||||
int get_h() const { return h; }
|
||||
|
||||
// Sample from Discrete Gauss distribution
|
||||
vector<bigint> sample_Gauss(PRNG& G, int stretch = 1) const;
|
||||
|
||||
@@ -191,6 +191,13 @@ void FFT2(vector<modp>& a, int N, const modp& alpha, const Zp_Data& PrD)
|
||||
}
|
||||
|
||||
|
||||
void FFT_non_power_of_two(vector<modp>& res, const vector<modp>& input, const FFT_Data& FFTD)
|
||||
{
|
||||
vector<modp> tmp(FFTD.m());
|
||||
BFFT(tmp, input, FFTD);
|
||||
for (int i = 0; i < (FFTD).phi_m(); i++)
|
||||
res[i] = tmp[(FFTD).p(i)];
|
||||
}
|
||||
|
||||
void BFFT(vector<modp>& ans,const vector<modp>& a,const FFT_Data& FFTD,bool forward)
|
||||
{
|
||||
|
||||
@@ -50,6 +50,8 @@ void FFT_Iter2(vector<modp>& a,int N,const modp& theta,const Zp_Data& PrD);
|
||||
|
||||
void BFFT(vector<modp>& ans,const vector<modp>& a,const FFT_Data& FFTD,bool forward=true);
|
||||
|
||||
void FFT_non_power_of_two(vector<modp>& res, const vector<modp>& input,
|
||||
const FFT_Data& FFTD);
|
||||
|
||||
/* Computes the FFT via Horner's Rule
|
||||
theta is assumed to be an Nth root of unity
|
||||
|
||||
@@ -13,12 +13,16 @@ FHE_SK::FHE_SK(const FHE_PK& pk) : FHE_SK(pk.get_params(), pk.p())
|
||||
}
|
||||
|
||||
|
||||
void add(FHE_SK& a,const FHE_SK& b,const FHE_SK& c)
|
||||
FHE_SK& FHE_SK::operator+=(const FHE_SK& c)
|
||||
{
|
||||
if (a.params!=b.params) { throw params_mismatch(); }
|
||||
auto& a = *this;
|
||||
auto& b = *this;
|
||||
|
||||
if (a.params!=c.params) { throw params_mismatch(); }
|
||||
|
||||
add(a.sk,b.sk,c.sk);
|
||||
::add(a.sk,b.sk,c.sk);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +88,7 @@ void FHE_PK::KeyGen(Rq_Element& sk, PRNG& G, int noise_boost)
|
||||
}
|
||||
}
|
||||
|
||||
void FHE_PK::check_noise(const FHE_SK& SK)
|
||||
void FHE_PK::check_noise(const FHE_SK& SK) const
|
||||
{
|
||||
Rq_Element sk = SK.s();
|
||||
if (params->n_mults() > 0)
|
||||
@@ -92,7 +96,7 @@ void FHE_PK::check_noise(const FHE_SK& SK)
|
||||
check_noise(b0 - a0 * sk);
|
||||
}
|
||||
|
||||
void FHE_PK::check_noise(const Rq_Element& x, bool check_modulo)
|
||||
void FHE_PK::check_noise(const Rq_Element& x, bool check_modulo) const
|
||||
{
|
||||
assert(pr != 0);
|
||||
vector<bigint> noise = x.to_vec_bigint();
|
||||
@@ -162,6 +166,7 @@ void FHE_PK::quasi_encrypt(Ciphertext& c,
|
||||
{
|
||||
if (&c.get_params()!=params) { throw params_mismatch(); }
|
||||
if (&rc.get_params()!=params) { throw params_mismatch(); }
|
||||
assert(pr != 0);
|
||||
|
||||
Rq_Element ed,edd,c0,c1,aa;
|
||||
|
||||
@@ -332,8 +337,11 @@ void FHE_PK::pack(octetStream& o) const
|
||||
o.append((octet*) "PKPKPKPK", 8);
|
||||
a0.pack(o);
|
||||
b0.pack(o);
|
||||
Sw_a.pack(o);
|
||||
Sw_b.pack(o);
|
||||
if (params->n_mults() > 0)
|
||||
{
|
||||
Sw_a.pack(o);
|
||||
Sw_b.pack(o);
|
||||
}
|
||||
pr.pack(o);
|
||||
}
|
||||
|
||||
@@ -345,8 +353,11 @@ void FHE_PK::unpack(octetStream& o)
|
||||
throw runtime_error("invalid serialization of public key");
|
||||
a0.unpack(o);
|
||||
b0.unpack(o);
|
||||
Sw_a.unpack(o);
|
||||
Sw_b.unpack(o);
|
||||
if (params->n_mults() > 0)
|
||||
{
|
||||
Sw_a.unpack(o);
|
||||
Sw_b.unpack(o);
|
||||
}
|
||||
pr.unpack(o);
|
||||
}
|
||||
|
||||
@@ -376,14 +387,30 @@ void FHE_SK::check(const FHE_Params& params, const FHE_PK& pk,
|
||||
}
|
||||
|
||||
|
||||
template<class FD>
|
||||
void FHE_SK::check(const FHE_PK& pk, const FD& FieldD)
|
||||
{
|
||||
check(*params, pk, pr);
|
||||
pk.check_noise(*this);
|
||||
if (decrypt(pk.encrypt(Plaintext_<FD>(FieldD)), FieldD) !=
|
||||
Plaintext_<FD>(FieldD))
|
||||
throw runtime_error("incorrect key pair");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FHE_PK::check(const FHE_Params& params, const bigint& pr) const
|
||||
{
|
||||
if (this->pr != pr)
|
||||
throw pr_mismatch();
|
||||
a0.check(params);
|
||||
b0.check(params);
|
||||
Sw_a.check(params);
|
||||
Sw_b.check(params);
|
||||
|
||||
if (params.n_mults() > 0)
|
||||
{
|
||||
Sw_a.check(params);
|
||||
Sw_b.check(params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -402,3 +429,6 @@ template void FHE_SK::decrypt_any(Plaintext_<FFT_Data>& res,
|
||||
const Ciphertext& c);
|
||||
template void FHE_SK::decrypt_any(Plaintext_<P2Data>& res,
|
||||
const Ciphertext& c);
|
||||
|
||||
template void FHE_SK::check(const FHE_PK& pk, const FFT_Data&);
|
||||
template void FHE_SK::check(const FHE_PK& pk, const P2Data&);
|
||||
|
||||
@@ -20,6 +20,8 @@ class FHE_SK
|
||||
|
||||
public:
|
||||
|
||||
static int size() { return 0; }
|
||||
|
||||
const FHE_Params& get_params() const { return *params; }
|
||||
|
||||
bigint p() const { return pr; }
|
||||
@@ -63,18 +65,24 @@ class FHE_SK
|
||||
|
||||
friend void KeyGen(FHE_PK& PK,FHE_SK& SK,PRNG& G);
|
||||
|
||||
/* Add secret key onto the existing one
|
||||
/* Add secret keys
|
||||
* Used for adding distributed keys together
|
||||
* a,b,c must have same params otherwise an error
|
||||
*/
|
||||
friend void add(FHE_SK& a,const FHE_SK& b,const FHE_SK& c);
|
||||
|
||||
FHE_SK operator+(const FHE_SK& x) { FHE_SK res(*params, pr); add(res, *this, x); return res; }
|
||||
FHE_SK& operator+=(const FHE_SK& x) { add(*this, *this, x); return *this; }
|
||||
FHE_SK operator+(const FHE_SK& x) const { FHE_SK res = *this; res += x; return res; }
|
||||
FHE_SK& operator+=(const FHE_SK& x);
|
||||
|
||||
bool operator!=(const FHE_SK& x) { return pr != x.pr or sk != x.sk; }
|
||||
bool operator!=(const FHE_SK& x) const { return pr != x.pr or sk != x.sk; }
|
||||
|
||||
void add(octetStream& os) { FHE_SK tmp(*this); tmp.unpack(os); *this += tmp; }
|
||||
|
||||
void check(const FHE_Params& params, const FHE_PK& pk, const bigint& pr) const;
|
||||
|
||||
template<class FD>
|
||||
void check(const FHE_PK& pk, const FD& FieldD);
|
||||
|
||||
friend ostream& operator<<(ostream& o, const FHE_SK&) { throw not_implemented(); return o; }
|
||||
};
|
||||
|
||||
|
||||
@@ -92,7 +100,7 @@ class FHE_PK
|
||||
bigint p() const { return pr; }
|
||||
|
||||
void assign(const Rq_Element& a,const Rq_Element& b,
|
||||
const Rq_Element& sa,const Rq_Element& sb
|
||||
const Rq_Element& sa = {},const Rq_Element& sb = {}
|
||||
)
|
||||
{ a0=a; b0=b; Sw_a=sa; Sw_b=sb; }
|
||||
|
||||
@@ -143,8 +151,8 @@ class FHE_PK
|
||||
Rq_Element sample_secret_key(PRNG& G);
|
||||
void KeyGen(Rq_Element& sk, PRNG& G, int noise_boost = 1);
|
||||
|
||||
void check_noise(const FHE_SK& sk);
|
||||
void check_noise(const Rq_Element& x, bool check_modulo = false);
|
||||
void check_noise(const FHE_SK& sk) const;
|
||||
void check_noise(const Rq_Element& x, bool check_modulo = false) const;
|
||||
|
||||
// params setting is done out of these IO/pack/unpack functions
|
||||
void pack(octetStream& o) const;
|
||||
|
||||
@@ -3,9 +3,16 @@
|
||||
#include "FHE/Ring_Element.h"
|
||||
#include "Tools/Exceptions.h"
|
||||
|
||||
|
||||
void FHE_Params::set(const Ring& R,
|
||||
const vector<bigint>& primes,double r,int hwt)
|
||||
{
|
||||
set(R, primes);
|
||||
|
||||
Chi.set(R.phi_m(),hwt,r);
|
||||
}
|
||||
|
||||
void FHE_Params::set(const Ring& R,
|
||||
const vector<bigint>& primes)
|
||||
{
|
||||
if (primes.size() != FFTData.size())
|
||||
throw runtime_error("wrong number of primes");
|
||||
@@ -13,8 +20,7 @@ void FHE_Params::set(const Ring& R,
|
||||
for (size_t i = 0; i < FFTData.size(); i++)
|
||||
FFTData[i].init(R,primes[i]);
|
||||
|
||||
Chi.set(R.phi_m(),hwt,r);
|
||||
|
||||
Chi.set_n(R.phi_m());
|
||||
set_sec(40);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +29,16 @@ class FHE_Params
|
||||
|
||||
public:
|
||||
|
||||
FHE_Params(int n_mults = 1) : FFTData(n_mults + 1), Chi(64, 0.7), sec_p(-1) {}
|
||||
FHE_Params(int n_mults = 1) : FFTData(n_mults + 1), Chi(-1, 0.7), sec_p(-1) {}
|
||||
|
||||
int n_mults() const { return FFTData.size() - 1; }
|
||||
|
||||
// Rely on default copy assignment/constructor (not that they should
|
||||
// ever be needed)
|
||||
|
||||
void set(const Ring& R,const vector<bigint>& primes,double r=-1,int hwt=-1);
|
||||
void set(const Ring& R,const vector<bigint>& primes,double r,int hwt);
|
||||
void set(const Ring& R,const vector<bigint>& primes);
|
||||
void set(const vector<bigint>& primes);
|
||||
void set_sec(int sec);
|
||||
|
||||
vector<bigint> sampleGaussian(PRNG& G, int noise_boost = 1) const
|
||||
@@ -57,7 +59,9 @@ class FHE_Params
|
||||
int secp() const { return sec_p; }
|
||||
const bigint& B() const { return Bval; }
|
||||
double get_R() const { return Chi.get_R(); }
|
||||
void set_R(double R) const { return Chi.get_DG().set(R); }
|
||||
DiscreteGauss get_DG() const { return Chi.get_DG(); }
|
||||
int get_h() const { return Chi.get_h(); }
|
||||
|
||||
int phi_m() const { return FFTData[0].phi_m(); }
|
||||
const Ring& get_ring() { return FFTData[0].get_R(); }
|
||||
|
||||
@@ -55,13 +55,14 @@ int generate_semi_setup(int plaintext_length, int sec,
|
||||
while (true)
|
||||
{
|
||||
SemiHomomorphicNoiseBounds nb(p, phi_N(m), 1, sec,
|
||||
numBits(NonInteractiveProof::slack(sec, phi_N(m))), true);
|
||||
numBits(NonInteractiveProof::slack(sec, phi_N(m))), true, params);
|
||||
bigint p1 = 2 * p * m, p0 = p;
|
||||
while (nb.min_p0(params.n_mults() > 0, p1) > p0)
|
||||
{
|
||||
p0 *= 2;
|
||||
}
|
||||
if (phi_N(m) < nb.min_phi_m(2 + numBits(p0 * (params.n_mults() > 0 ? p1 : 1))))
|
||||
if (phi_N(m) < nb.min_phi_m(2 + numBits(p0 * (params.n_mults() > 0 ? p1 : 1)),
|
||||
params.get_R()))
|
||||
{
|
||||
m *= 2;
|
||||
generate_prime(p, lgp, m);
|
||||
@@ -91,7 +92,7 @@ int generate_semi_setup(int plaintext_length, int sec,
|
||||
int m;
|
||||
char_2_dimension(m, plaintext_length);
|
||||
SemiHomomorphicNoiseBounds nb(2, phi_N(m), 1, sec,
|
||||
numBits(NonInteractiveProof::slack(sec, phi_N(m))), true);
|
||||
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);
|
||||
load_or_generate(P2D, params.get_ring());
|
||||
@@ -111,7 +112,7 @@ int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, b
|
||||
int i;
|
||||
for (i = 0; i <= 20; i++)
|
||||
{
|
||||
if (SemiHomomorphicNoiseBounds::min_phi_m(lgp0 + i) > phi_N(m))
|
||||
if (SemiHomomorphicNoiseBounds::min_phi_m(lgp0 + i, params) > phi_N(m))
|
||||
break;
|
||||
if (not same_word_length(lgp0, lgp0 + i))
|
||||
break;
|
||||
@@ -138,7 +139,8 @@ int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, b
|
||||
return extra_slack;
|
||||
}
|
||||
|
||||
int finalize_lengths(int& lg2p0, int& lg2p1, int n, int m, int* lg2pi, bool round_up)
|
||||
int finalize_lengths(int& lg2p0, int& lg2p1, int n, int m, int* lg2pi,
|
||||
bool round_up, FHE_Params& params)
|
||||
{
|
||||
if (n >= 2 and n <= 10)
|
||||
cout << "Difference to suggestion for p0: " << lg2p0 - lg2pi[n - 2]
|
||||
@@ -152,7 +154,7 @@ int finalize_lengths(int& lg2p0, int& lg2p1, int n, int m, int* lg2pi, bool roun
|
||||
int i = 0;
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if (phi_N(m) < NoiseBounds::min_phi_m(lg2p0 + lg2p1 + 2 * i))
|
||||
if (phi_N(m) < NoiseBounds::min_phi_m(lg2p0 + lg2p1 + 2 * i, params))
|
||||
break;
|
||||
if (not same_word_length(lg2p0 + i, lg2p0))
|
||||
break;
|
||||
@@ -183,7 +185,8 @@ int finalize_lengths(int& lg2p0, int& lg2p1, int n, int m, int* lg2pi, bool roun
|
||||
/*
|
||||
* Subroutine for creating the FHE parameters
|
||||
*/
|
||||
int Parameters::SPDZ_Data_Setup_Char_p_Sub(int idx, int& m, bigint& p)
|
||||
int Parameters::SPDZ_Data_Setup_Char_p_Sub(int idx, int& m, bigint& p,
|
||||
FHE_Params& params)
|
||||
{
|
||||
int n = n_parties;
|
||||
int lg2pi[5][2][9]
|
||||
@@ -211,7 +214,7 @@ int Parameters::SPDZ_Data_Setup_Char_p_Sub(int idx, int& m, bigint& p)
|
||||
while (sec != -1)
|
||||
{
|
||||
double phi_m_bound =
|
||||
NoiseBounds(p, phi_N(m), n, sec, slack).optimize(lg2p0, lg2p1);
|
||||
NoiseBounds(p, phi_N(m), n, sec, slack, params).optimize(lg2p0, lg2p1);
|
||||
cout << "Trying primes of length " << lg2p0 << " and " << lg2p1 << endl;
|
||||
if (phi_N(m) < phi_m_bound)
|
||||
{
|
||||
@@ -226,7 +229,7 @@ int Parameters::SPDZ_Data_Setup_Char_p_Sub(int idx, int& m, bigint& p)
|
||||
|
||||
init(R,m);
|
||||
int extra_slack = finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[idx][0],
|
||||
round_up);
|
||||
round_up, params);
|
||||
generate_moduli(pr0, pr1, m, p, lg2p0, lg2p1);
|
||||
return extra_slack;
|
||||
}
|
||||
@@ -241,8 +244,6 @@ void generate_moduli(bigint& pr0, bigint& pr1, const int m, const bigint p,
|
||||
void generate_modulus(bigint& pr, const int m, const bigint p, const int lg2pr,
|
||||
const string& i, const bigint& pr0)
|
||||
{
|
||||
int ex;
|
||||
|
||||
if (lg2pr==0) { throw invalid_params(); }
|
||||
|
||||
bigint step=m;
|
||||
@@ -250,15 +251,20 @@ void generate_modulus(bigint& pr, const int m, const bigint p, const int lg2pr,
|
||||
bigint gc=gcd(step,twop);
|
||||
step=step*twop/gc;
|
||||
|
||||
ex=lg2pr-numBits(p)-numBits(step)+1;
|
||||
if (ex<0) { cout << "Something wrong in lg2p" << i << " = " << lg2pr << endl; abort(); }
|
||||
pr=1; pr=(pr<<ex)*p*step+1;
|
||||
while (!probPrime(pr) || pr==pr0 || numBits(pr)<lg2pr) { pr=pr+p*step; }
|
||||
step *= p;
|
||||
pr = (bigint(1) << lg2pr) / step * step + 1;
|
||||
|
||||
while (pr == pr0 || !probPrime(pr))
|
||||
{
|
||||
pr -= step;
|
||||
assert(numBits(pr) == lg2pr);
|
||||
}
|
||||
|
||||
cout << "\t pr" << i << " = " << pr << " : " << numBits(pr) << endl;
|
||||
|
||||
cout << "\t\tFollowing should be both 1" << endl;
|
||||
cout << "\t\tpr" << i << " mod m = " << pr%m << endl;
|
||||
cout << "\t\tpr" << i << " mod p = " << pr%p << endl;
|
||||
assert(pr % m == 1);
|
||||
assert(pr % p == 1);
|
||||
assert(numBits(pr) == lg2pr);
|
||||
|
||||
cout << "Minimal MAX_MOD_SZ = " << int(ceil(1. * lg2pr / 64)) << endl;
|
||||
}
|
||||
@@ -267,12 +273,12 @@ void generate_modulus(bigint& pr, const int m, const bigint p, const int lg2pr,
|
||||
* Create the char p FHE parameters
|
||||
*/
|
||||
template <>
|
||||
void Parameters::SPDZ_Data_Setup(FFT_Data& FTD)
|
||||
void Parameters::SPDZ_Data_Setup(FHE_Params& params, FFT_Data& FTD)
|
||||
{
|
||||
bigint p;
|
||||
int idx, m;
|
||||
SPDZ_Data_Setup_Primes(p, plaintext_length, idx, m);
|
||||
SPDZ_Data_Setup_Char_p_Sub(idx, m, p);
|
||||
SPDZ_Data_Setup_Char_p_Sub(idx, m, p, params);
|
||||
|
||||
Zp_Data Zp(p);
|
||||
gfp::init_field(p);
|
||||
@@ -569,7 +575,7 @@ void char_2_dimension(int& m, int& lg2)
|
||||
}
|
||||
|
||||
template <>
|
||||
void Parameters::SPDZ_Data_Setup(P2Data& P2D)
|
||||
void Parameters::SPDZ_Data_Setup(FHE_Params& params, P2Data& P2D)
|
||||
{
|
||||
int n = n_parties;
|
||||
int lg2 = plaintext_length;
|
||||
@@ -593,11 +599,11 @@ void Parameters::SPDZ_Data_Setup(P2Data& P2D)
|
||||
}
|
||||
else
|
||||
{
|
||||
NoiseBounds(2, phi_N(m), n, sec, slack).optimize(lg2p0, lg2p1);
|
||||
finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[0], round_up);
|
||||
NoiseBounds(2, phi_N(m), n, sec, slack, params).optimize(lg2p0, lg2p1);
|
||||
finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[0], round_up, params);
|
||||
}
|
||||
|
||||
if (NoiseBounds::min_phi_m(lg2p0 + lg2p1) > phi_N(m))
|
||||
if (NoiseBounds::min_phi_m(lg2p0 + lg2p1, params) > phi_N(m))
|
||||
throw runtime_error("number of slots too small");
|
||||
|
||||
cout << "m = " << m << endl;
|
||||
@@ -651,7 +657,7 @@ void load_or_generate(P2Data& P2D, const Ring& R)
|
||||
* Basically this is for general large primes only
|
||||
*/
|
||||
void SPDZ_Data_Setup_Char_p_General(Ring& R, PPData& PPD, bigint& pr0,
|
||||
bigint& pr1, int n, int sec, bigint& p)
|
||||
bigint& pr1, int n, int sec, bigint& p, FHE_Params& params)
|
||||
{
|
||||
cout << "Setting up parameters" << endl;
|
||||
|
||||
@@ -758,7 +764,7 @@ void SPDZ_Data_Setup_Char_p_General(Ring& R, PPData& PPD, bigint& pr0,
|
||||
cout << "Chosen value of m=" << m << "\t\t phi(m)=" << bphi_m << " : " << min_hwt << " : " << bmx << endl;
|
||||
|
||||
Parameters parameters(n, lgp, sec);
|
||||
parameters.SPDZ_Data_Setup_Char_p_Sub(idx,m,p);
|
||||
parameters.SPDZ_Data_Setup_Char_p_Sub(idx,m,p,params);
|
||||
int mx=0;
|
||||
for (int i=0; i<R.phi_m(); i++)
|
||||
{ if (mx<R.Phi()[i]) { mx=R.Phi()[i]; } }
|
||||
|
||||
@@ -35,14 +35,15 @@ public:
|
||||
template<class FD>
|
||||
void generate_setup(FHE_Params& params, FD& FTD)
|
||||
{
|
||||
SPDZ_Data_Setup(FTD);
|
||||
SPDZ_Data_Setup(params, FTD);
|
||||
params.set(R, {pr0, pr1});
|
||||
}
|
||||
|
||||
template<class FD>
|
||||
void SPDZ_Data_Setup(FD& FTD);
|
||||
void SPDZ_Data_Setup(FHE_Params& params, FD& FTD);
|
||||
|
||||
int SPDZ_Data_Setup_Char_p_Sub(int idx, int& m, bigint& p);
|
||||
int SPDZ_Data_Setup_Char_p_Sub(int idx, int& m, bigint& p,
|
||||
FHE_Params& params);
|
||||
|
||||
};
|
||||
|
||||
@@ -65,7 +66,7 @@ void init(P2Data& P2D,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);
|
||||
bigint& pr1, int n, int sec, bigint& p, FHE_Params& params);
|
||||
|
||||
// generate moduli according to lengths and other parameters
|
||||
void generate_moduli(bigint& pr0, bigint& pr1, const int m,
|
||||
|
||||
@@ -8,52 +8,51 @@
|
||||
#include "Protocols/CowGearOptions.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
SemiHomomorphicNoiseBounds::SemiHomomorphicNoiseBounds(const bigint& p,
|
||||
int phi_m, int n, int sec, int slack_param, bool extra_h, double sigma, int h) :
|
||||
int phi_m, int n, int sec, int slack_param, bool extra_h,
|
||||
const FHE_Params& params) :
|
||||
p(p), phi_m(phi_m), n(n), sec(sec),
|
||||
slack(numBits(Proof::slack(slack_param, sec, phi_m))), sigma(sigma), h(h)
|
||||
slack(numBits(Proof::slack(slack_param, sec, phi_m))),
|
||||
sigma(params.get_R()), h(params.get_h())
|
||||
{
|
||||
if (sigma <= 0)
|
||||
this->sigma = sigma = FHE_Params().get_R();
|
||||
#ifdef VERBOSE
|
||||
cerr << "Standard deviation: " << this->sigma << endl;
|
||||
#endif
|
||||
h += extra_h * sec;
|
||||
if (h > 0)
|
||||
h += extra_h * sec;
|
||||
else if (extra_h)
|
||||
{
|
||||
sigma *= 1.4;
|
||||
params.set_R(params.get_R() * 1.4);
|
||||
}
|
||||
|
||||
produce_epsilon_constants();
|
||||
|
||||
if (CowGearOptions::singleton.top_gear())
|
||||
{
|
||||
// according to documentation of SCALE-MAMBA 1.7
|
||||
// excluding a factor of n because we don't always add up n ciphertexts
|
||||
B_clean = (bigint(phi_m) << (sec + 2)) * p
|
||||
* (20.5 + c1 * sigma * sqrt(phi_m) + 20 * c1 * sqrt(h));
|
||||
mpf_class V_s;
|
||||
if (h > 0)
|
||||
V_s = sqrt(h);
|
||||
else
|
||||
V_s = sigma * sqrt(phi_m);
|
||||
B_scale = (c1 + c2 * V_s) * p * sqrt(phi_m / 12.0);
|
||||
#ifdef NOISY
|
||||
cout << "p * sqrt(phi(m) / 12): " << p * sqrt(phi_m / 12.0) << endl;
|
||||
cout << "V_s: " << V_s << endl;
|
||||
cout << "c1: " << c1 << endl;
|
||||
cout << "c2: " << c2 << endl;
|
||||
cout << "c1 + c2 * V_s: " << c1 + c2 * V_s << endl;
|
||||
cout << "B_scale: " << B_scale << endl;
|
||||
#endif
|
||||
}
|
||||
// according to documentation of SCALE-MAMBA 1.7
|
||||
// excluding a factor of n because we don't always add up n ciphertexts
|
||||
if (h > 0)
|
||||
V_s = sqrt(h);
|
||||
else
|
||||
{
|
||||
B_clean = (phi_m * p / 2
|
||||
+ p * sigma
|
||||
* (16 * phi_m * sqrt(n / 2) + 6 * sqrt(phi_m)
|
||||
+ 16 * sqrt(n * h * phi_m))) << slack;
|
||||
B_scale = p * sqrt(3 * phi_m) * (1 + 8 * sqrt(n * h) / 3);
|
||||
#ifdef VERBOSE
|
||||
cout << "log(slack): " << slack << endl;
|
||||
V_s = sigma * sqrt(phi_m);
|
||||
B_clean = (bigint(phi_m) << (sec + 1)) * 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.));
|
||||
B_clean = max(B_clean_not_top_gear, B_clean_top_gear);
|
||||
B_scale = (c1 + c2 * V_s) * p * sqrt(phi_m / 12.0);
|
||||
#ifdef NOISY
|
||||
cout << "p * sqrt(phi(m) / 12): " << p * sqrt(phi_m / 12.0) << endl;
|
||||
cout << "V_s: " << V_s << endl;
|
||||
cout << "c1: " << c1 << endl;
|
||||
cout << "c2: " << c2 << endl;
|
||||
cout << "c1 + c2 * V_s: " << c1 + c2 * V_s << endl;
|
||||
cout << "log(slack): " << slack << endl;
|
||||
cout << "B_clean: " << B_clean << endl;
|
||||
cout << "B_scale: " << B_scale << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
drown = 1 + n * (bigint(1) << sec);
|
||||
}
|
||||
@@ -77,6 +76,11 @@ double SemiHomomorphicNoiseBounds::min_phi_m(int log_q, double sigma)
|
||||
return 37.8 * (log_q - log2(sigma));
|
||||
}
|
||||
|
||||
double SemiHomomorphicNoiseBounds::min_phi_m(int log_q, const FHE_Params& params)
|
||||
{
|
||||
return min_phi_m(log_q, params.get_R());
|
||||
}
|
||||
|
||||
void SemiHomomorphicNoiseBounds::produce_epsilon_constants()
|
||||
{
|
||||
double C[3];
|
||||
@@ -104,21 +108,10 @@ void SemiHomomorphicNoiseBounds::produce_epsilon_constants()
|
||||
}
|
||||
|
||||
NoiseBounds::NoiseBounds(const bigint& p, int phi_m, int n, int sec, int slack,
|
||||
double sigma, int h) :
|
||||
SemiHomomorphicNoiseBounds(p, phi_m, n, sec, slack, false, sigma, h)
|
||||
const FHE_Params& params) :
|
||||
SemiHomomorphicNoiseBounds(p, phi_m, n, sec, slack, false, params)
|
||||
{
|
||||
if (CowGearOptions::singleton.top_gear())
|
||||
{
|
||||
B_KS = p * c2 * this->sigma * phi_m / sqrt(12);
|
||||
}
|
||||
else
|
||||
{
|
||||
B_KS = p * phi_m * mpf_class(this->sigma)
|
||||
* (pow(n, 2.5) * (1.49 * sqrt(h * phi_m) + 2.11 * h)
|
||||
+ 2.77 * n * n * sqrt(h)
|
||||
+ pow(n, 1.5) * (1.96 * sqrt(phi_m) * 2.77 * sqrt(h))
|
||||
+ 4.62 * n);
|
||||
}
|
||||
B_KS = p * c2 * this->sigma * phi_m / sqrt(12);
|
||||
#ifdef NOISY
|
||||
cout << "p size: " << numBits(p) << endl;
|
||||
cout << "phi(m): " << phi_m << endl;
|
||||
@@ -197,5 +190,5 @@ double NoiseBounds::optimize(int& lg2p0, int& lg2p1)
|
||||
}
|
||||
lg2p1 = numBits(min_p1);
|
||||
lg2p0 = numBits(min_p0);
|
||||
return min_phi_m(lg2p0 + lg2p1);
|
||||
return min_phi_m(lg2p0 + lg2p1, sigma.get_d());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Math/bigint.h"
|
||||
|
||||
int phi_N(int N);
|
||||
class FHE_Params;
|
||||
|
||||
class SemiHomomorphicNoiseBounds
|
||||
{
|
||||
@@ -21,25 +22,27 @@ protected:
|
||||
const int sec;
|
||||
int slack;
|
||||
mpf_class sigma;
|
||||
const int h;
|
||||
int h;
|
||||
|
||||
bigint B_clean;
|
||||
bigint B_scale;
|
||||
bigint drown;
|
||||
|
||||
mpf_class c1, c2;
|
||||
mpf_class V_s;
|
||||
|
||||
void produce_epsilon_constants();
|
||||
|
||||
public:
|
||||
SemiHomomorphicNoiseBounds(const bigint& p, int phi_m, int n, int sec,
|
||||
int slack, bool extra_h = false, double sigma = -1, int h = 64);
|
||||
int slack, bool extra_h, const FHE_Params& params);
|
||||
// with scaling
|
||||
bigint min_p0(const bigint& p1);
|
||||
// without scaling
|
||||
bigint min_p0();
|
||||
bigint min_p0(bool scale, const bigint& p1) { return scale ? min_p0(p1) : min_p0(); }
|
||||
static double min_phi_m(int log_q, double sigma = -1);
|
||||
static double min_phi_m(int log_q, double sigma);
|
||||
static double min_phi_m(int log_q, const FHE_Params& params);
|
||||
};
|
||||
|
||||
// as per ePrint 2012:642 for slack = 0
|
||||
@@ -49,7 +52,7 @@ class NoiseBounds : public SemiHomomorphicNoiseBounds
|
||||
|
||||
public:
|
||||
NoiseBounds(const bigint& p, int phi_m, int n, int sec, int slack,
|
||||
double sigma = -1, int h = 64);
|
||||
const FHE_Params& params);
|
||||
bigint U1(const bigint& p0, const bigint& p1);
|
||||
bigint U2(const bigint& p0, const bigint& p1);
|
||||
bigint min_p0(const bigint& p0, const bigint& p1);
|
||||
|
||||
@@ -286,15 +286,21 @@ void Plaintext_<FFT_Data>::randomize(PRNG& G, bigint B, bool Diag, bool binary,
|
||||
template<class T,class FD,class S>
|
||||
void Plaintext<T,FD,S>::randomize(PRNG& G, int n_bits, bool Diag, bool binary, PT_Type t)
|
||||
{
|
||||
if (Diag or binary)
|
||||
if (binary)
|
||||
throw not_implemented();
|
||||
|
||||
allocate(t);
|
||||
switch(t)
|
||||
{
|
||||
case Polynomial:
|
||||
for (int i = 0; i < n_slots; i++)
|
||||
b[i].generateUniform(G, n_bits, false);
|
||||
if (Diag)
|
||||
{
|
||||
assign_zero(t);
|
||||
b[0].generateUniform(G, n_bits, false);
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < n_slots; i++)
|
||||
b[i].generateUniform(G, n_bits, false);
|
||||
break;
|
||||
default:
|
||||
throw not_implemented();
|
||||
@@ -638,6 +644,41 @@ bool Plaintext<T,FD,S>::equals(const Plaintext& x) const
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Plaintext<gfp, FFT_Data, bigint>::is_diagonal() const
|
||||
{
|
||||
if (type != Evaluation)
|
||||
{
|
||||
for (size_t i = 1; i < b.size(); i++)
|
||||
if (b[i] != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type != Polynomial)
|
||||
{
|
||||
auto first = a[0];
|
||||
for (auto& x : a)
|
||||
if (x != first)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool Plaintext<gf2n_short, P2Data, int>::is_diagonal() const
|
||||
{
|
||||
if (type == Polynomial)
|
||||
from_poly();
|
||||
|
||||
auto first = a[0];
|
||||
for (auto& x : a)
|
||||
if (x != first)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T,class FD,class S>
|
||||
|
||||
@@ -176,7 +176,7 @@ class Plaintext
|
||||
bool equals(const Plaintext& x) const;
|
||||
bool operator!=(const Plaintext& x) { return !equals(x); }
|
||||
|
||||
bool is_diagonal() const { throw not_implemented(); }
|
||||
bool is_diagonal() const;
|
||||
bool is_binary() const { throw not_implemented(); }
|
||||
|
||||
/* Pack and unpack into an octetStream
|
||||
|
||||
@@ -222,10 +222,7 @@ void Ring_Element::change_rep(RepType r)
|
||||
}
|
||||
else
|
||||
{ // Non m power of two variant and FFT enabled
|
||||
vector<modp> fft((*FFTD).m());
|
||||
BFFT(fft,element,*FFTD);
|
||||
for (int i=0; i<(*FFTD).phi_m(); i++)
|
||||
{ element[i]=fft[(*FFTD).p(i)]; }
|
||||
FFT_non_power_of_two(element, element, *FFTD);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -70,6 +70,16 @@ class Ring_Element
|
||||
|
||||
Ring_Element(const FFT_Data& prd,RepType r=polynomial);
|
||||
|
||||
template<class T>
|
||||
Ring_Element(const FFT_Data& prd, RepType r, const vector<T>& other)
|
||||
{
|
||||
assert(size_t(prd.num_slots()) == other.size());
|
||||
FFTD = &prd;
|
||||
rep = r;
|
||||
for (auto& x : other)
|
||||
element.push_back(x);
|
||||
}
|
||||
|
||||
// Copy Constructor
|
||||
Ring_Element(const Ring_Element& e)
|
||||
{ assign(e); }
|
||||
|
||||
@@ -66,6 +66,9 @@ protected:
|
||||
Rq_Element(const Ring_Element& b0,const Ring_Element& b1) :
|
||||
a({b0, b1}), lev(n_mults()) {}
|
||||
|
||||
Rq_Element(const Ring_Element& b0) :
|
||||
a({b0}), lev(n_mults()) {}
|
||||
|
||||
template<class T, class FD, class S>
|
||||
Rq_Element(const FHE_Params& params, const Plaintext<T, FD, S>& plaintext) :
|
||||
Rq_Element(params)
|
||||
@@ -73,6 +76,15 @@ protected:
|
||||
from(plaintext.get_iterator());
|
||||
}
|
||||
|
||||
template<class U, class V>
|
||||
Rq_Element(const vector<FFT_Data>& prd, const vector<U>& b0,
|
||||
const vector<V>& b1, RepType r = evaluation) :
|
||||
Rq_Element(prd, r, r)
|
||||
{
|
||||
a[0] = Ring_Element(prd[0], r, b0);
|
||||
a[1] = Ring_Element(prd[1], r, b1);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
~Rq_Element()
|
||||
{ ; }
|
||||
@@ -107,6 +119,7 @@ protected:
|
||||
void Scale(const bigint& p);
|
||||
|
||||
bool equals(const Rq_Element& a) const;
|
||||
bool operator==(const Rq_Element& a) const { return equals(a); }
|
||||
bool operator!=(const Rq_Element& a) const { return !equals(a); }
|
||||
|
||||
int level() const { return lev; }
|
||||
|
||||
@@ -241,67 +241,12 @@ void PartSetup<FD>::covert_mac_generation(Player& P, MachineBase&, int num_runs)
|
||||
}
|
||||
|
||||
template<class FD>
|
||||
void PartSetup<FD>::covert_secrets_generation(Player& P, MachineBase& machine,
|
||||
int num_runs)
|
||||
void PartSetup<FD>::key_and_mac_generation(Player& P,
|
||||
MachineBase& machine, int num_runs, true_type)
|
||||
{
|
||||
read_or_generate_covert_secrets(*this, P, machine, num_runs);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void read_or_generate_covert_secrets(T& setup, Player& P, U& machine,
|
||||
int num_runs)
|
||||
{
|
||||
octetStream os;
|
||||
setup.params.pack(os);
|
||||
setup.FieldD.pack(os);
|
||||
string filename = PREP_DIR + setup.covert_name() + "-Secrets-"
|
||||
+ to_string(num_runs) + "-"
|
||||
+ os.check_sum(20).get_str(16) + "-P" + to_string(P.my_num()) + "-"
|
||||
+ to_string(P.num_players());
|
||||
|
||||
string error;
|
||||
|
||||
try
|
||||
{
|
||||
ifstream input(filename);
|
||||
os.input(input);
|
||||
setup.unpack(os);
|
||||
machine.unpack(os);
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
error = e.what();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
setup.check(P, machine);
|
||||
machine.check(P);
|
||||
}
|
||||
catch (mismatch_among_parties& e)
|
||||
{
|
||||
error = e.what();
|
||||
}
|
||||
|
||||
if (not error.empty())
|
||||
{
|
||||
cerr << "Running secrets generation because " << error << endl;
|
||||
setup.covert_key_generation(P, machine, num_runs);
|
||||
setup.covert_mac_generation(P, machine, num_runs);
|
||||
ofstream output(filename);
|
||||
octetStream os;
|
||||
setup.pack(os);
|
||||
machine.pack(os);
|
||||
os.output(output);
|
||||
}
|
||||
covert_key_generation(P, machine, num_runs);
|
||||
covert_mac_generation(P, machine, num_runs);
|
||||
}
|
||||
|
||||
template class PartSetup<FFT_Data>;
|
||||
template class PartSetup<P2Data>;
|
||||
|
||||
template void read_or_generate_covert_secrets<PairwiseSetup<FFT_Data>,
|
||||
PairwiseMachine>(PairwiseSetup<FFT_Data>&, Player&, PairwiseMachine&,
|
||||
int);
|
||||
template void read_or_generate_covert_secrets<PairwiseSetup<P2Data>,
|
||||
PairwiseMachine>(PairwiseSetup<P2Data>&, Player&, PairwiseMachine&,
|
||||
int);
|
||||
|
||||
@@ -16,10 +16,6 @@ class DataSetup;
|
||||
class MachineBase;
|
||||
class MultiplicativeMachine;
|
||||
|
||||
template<class T, class U>
|
||||
void read_or_generate_covert_secrets(T& setup, Player& P, U& machine,
|
||||
int num_runs);
|
||||
|
||||
template <class FD>
|
||||
class PartSetup
|
||||
{
|
||||
@@ -38,9 +34,12 @@ public:
|
||||
return "GlobalParams-" + T::type_string();
|
||||
}
|
||||
|
||||
static string covert_name()
|
||||
static string protocol_name(bool covert)
|
||||
{
|
||||
return "ChaiGear";
|
||||
if (covert)
|
||||
return "ChaiGear";
|
||||
else
|
||||
return "HighGear";
|
||||
}
|
||||
|
||||
PartSetup();
|
||||
@@ -69,7 +68,11 @@ public:
|
||||
|
||||
void covert_key_generation(Player& P, MachineBase&, int num_runs);
|
||||
void covert_mac_generation(Player& P, MachineBase&, int num_runs);
|
||||
void covert_secrets_generation(Player& P, MachineBase& machine, int num_runs);
|
||||
|
||||
void key_and_mac_generation(Player& P, MachineBase& machine, int num_runs,
|
||||
false_type);
|
||||
void key_and_mac_generation(Player& P, MachineBase& machine, int num_runs,
|
||||
true_type);
|
||||
|
||||
void output(Names& N);
|
||||
};
|
||||
|
||||
63
FHEOffline/DataSetup.hpp
Normal file
63
FHEOffline/DataSetup.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* DataSetup.hpp
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FHEOFFLINE_DATASETUP_HPP_
|
||||
#define FHEOFFLINE_DATASETUP_HPP_
|
||||
|
||||
#include "Networking/Player.h"
|
||||
#include "Tools/Bundle.h"
|
||||
|
||||
template<class T, class U, class V>
|
||||
void read_or_generate_secrets(T& setup, Player& P, U& machine,
|
||||
int num_runs, V)
|
||||
{
|
||||
octetStream os;
|
||||
setup.params.pack(os);
|
||||
setup.FieldD.pack(os);
|
||||
bool covert = num_runs > 0;
|
||||
assert(covert == V());
|
||||
string filename = PREP_DIR + setup.protocol_name(covert) + "-Secrets-"
|
||||
+ (covert ? to_string(num_runs) : to_string(machine.sec)) + "-"
|
||||
+ os.check_sum(20).get_str(16) + "-P" + to_string(P.my_num()) + "-"
|
||||
+ to_string(P.num_players());
|
||||
|
||||
string error;
|
||||
|
||||
try
|
||||
{
|
||||
ifstream input(filename);
|
||||
os.input(input);
|
||||
setup.unpack(os);
|
||||
machine.unpack(os);
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
error = e.what();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
setup.check(P, machine);
|
||||
machine.check(P);
|
||||
}
|
||||
catch (mismatch_among_parties& e)
|
||||
{
|
||||
error = e.what();
|
||||
}
|
||||
|
||||
if (not error.empty())
|
||||
{
|
||||
cerr << "Running secrets generation because " << error << endl;
|
||||
setup.key_and_mac_generation(P, machine, num_runs, V());
|
||||
|
||||
ofstream output(filename);
|
||||
octetStream os;
|
||||
setup.pack(os);
|
||||
machine.pack(os);
|
||||
os.output(output);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FHEOFFLINE_DATASETUP_HPP_ */
|
||||
@@ -120,7 +120,7 @@ void PairwiseMachine::pack(octetStream& os) const
|
||||
|
||||
void PairwiseMachine::unpack(octetStream& os)
|
||||
{
|
||||
os.get(other_pks, {setup_p.params, 0});
|
||||
os.get_no_resize(other_pks);
|
||||
os.get(enc_alphas, {pk});
|
||||
sk.unpack(os);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Tools/Commit.h"
|
||||
#include "Tools/Bundle.h"
|
||||
#include "Processor/OnlineOptions.h"
|
||||
#include "Protocols/LowGearKeyGen.h"
|
||||
|
||||
#include "Protocols/Share.hpp"
|
||||
#include "Protocols/mac_key.hpp"
|
||||
@@ -189,6 +190,14 @@ void PairwiseSetup<FD>::covert_mac_generation(Player& P,
|
||||
alphai = alpha.element(0);
|
||||
}
|
||||
|
||||
template <class FD>
|
||||
void PairwiseSetup<FD>::key_and_mac_generation(Player& P,
|
||||
PairwiseMachine& machine, int num_runs, true_type)
|
||||
{
|
||||
covert_key_generation(P, machine, num_runs);
|
||||
covert_mac_generation(P, machine, num_runs);
|
||||
}
|
||||
|
||||
template <class FD>
|
||||
void PairwiseSetup<FD>::set_alphai(T alphai)
|
||||
{
|
||||
|
||||
@@ -33,9 +33,12 @@ public:
|
||||
return "PairwiseParams-" + FD::T::type_string();
|
||||
}
|
||||
|
||||
static string covert_name()
|
||||
static string protocol_name(bool covert)
|
||||
{
|
||||
return "CowGear";
|
||||
if (covert)
|
||||
return "CowGear";
|
||||
else
|
||||
return "LowGear";
|
||||
}
|
||||
|
||||
PairwiseSetup() : params(0), alpha(FieldD) {}
|
||||
@@ -48,6 +51,11 @@ public:
|
||||
void covert_key_generation(Player& P, PairwiseMachine& machine, int num_runs);
|
||||
void covert_mac_generation(Player& P, PairwiseMachine& machine, int num_runs);
|
||||
|
||||
void key_and_mac_generation(Player& P, PairwiseMachine& machine,
|
||||
int num_runs, false_type);
|
||||
void key_and_mac_generation(Player& P, PairwiseMachine& machine,
|
||||
int num_runs, true_type);
|
||||
|
||||
void pack(octetStream& os) const;
|
||||
void unpack(octetStream& os);
|
||||
|
||||
|
||||
@@ -588,8 +588,8 @@ void InputProducer<FD>::run(const Player& P, const FHE_PK& pk,
|
||||
P.receive_player(j, ciphertexts);
|
||||
P.receive_player(j, cleartexts);
|
||||
C.resize(personal_EC.machine->sec, pk.get_params());
|
||||
Verifier<FD>(personal_EC.proof).NIZKPoK(C, ciphertexts,
|
||||
cleartexts, pk, false, false);
|
||||
Verifier<FD>(personal_EC.proof, FieldD).NIZKPoK(C, ciphertexts,
|
||||
cleartexts, pk, false);
|
||||
}
|
||||
|
||||
inputs[j].clear();
|
||||
|
||||
@@ -24,6 +24,8 @@ class Proof
|
||||
{
|
||||
unsigned int sec;
|
||||
|
||||
bool diagonal;
|
||||
|
||||
Proof(); // Private to avoid default
|
||||
|
||||
public:
|
||||
@@ -72,7 +74,8 @@ class Proof
|
||||
typedef AddableMatrix<typename Int_Random_Coins::rand_type> X;
|
||||
|
||||
Proof(int sc, const bigint& Tau, const bigint& Rho, const FHE_PK& pk,
|
||||
int n_proofs = 1) :
|
||||
int n_proofs = 1, bool diagonal = false) :
|
||||
diagonal(diagonal),
|
||||
B_plain_length(0), B_rand_length(0), pk(&pk), n_proofs(n_proofs)
|
||||
{ sec=sc;
|
||||
tau=Tau; rho=Rho;
|
||||
@@ -95,19 +98,25 @@ class Proof
|
||||
}
|
||||
}
|
||||
|
||||
Proof(int sec, const FHE_PK& pk, int n_proofs = 1) :
|
||||
Proof(int sec, const FHE_PK& pk, int n_proofs = 1, bool diagonal = false) :
|
||||
Proof(sec, pk.p() / 2,
|
||||
pk.get_params().get_DG().get_NewHopeB(), pk,
|
||||
n_proofs) {}
|
||||
n_proofs, diagonal) {}
|
||||
|
||||
virtual ~Proof() {}
|
||||
|
||||
public:
|
||||
static bigint slack(int slack, int sec, int phim);
|
||||
|
||||
static bool use_top_gear(const FHE_PK& pk)
|
||||
bool use_top_gear(const FHE_PK& pk)
|
||||
{
|
||||
return CowGearOptions::singleton.top_gear() and pk.p() > 2;
|
||||
return CowGearOptions::singleton.top_gear() and pk.p() > 2 and
|
||||
not diagonal;
|
||||
}
|
||||
|
||||
bool get_diagonal() const
|
||||
{
|
||||
return diagonal;
|
||||
}
|
||||
|
||||
static int n_ciphertext_per_proof(int sec, const FHE_PK& pk)
|
||||
@@ -147,8 +156,8 @@ public:
|
||||
{ return bigint(phim * sec * sec) << (sec / 2 + 8); }
|
||||
|
||||
NonInteractiveProof(int sec, const FHE_PK& pk,
|
||||
int extra_slack) :
|
||||
Proof(sec, pk, 1)
|
||||
int extra_slack, bool diagonal = false) :
|
||||
Proof(sec, pk, 1, diagonal)
|
||||
{
|
||||
bigint B;
|
||||
B=128*sec*sec;
|
||||
@@ -167,8 +176,8 @@ public:
|
||||
{ (void)phim; return pow(2, 1.5 * sec + 1); }
|
||||
|
||||
InteractiveProof(int sec, const FHE_PK& pk,
|
||||
int n_proofs = 1) :
|
||||
Proof(sec, pk, n_proofs)
|
||||
int n_proofs = 1, bool diagonal = false) :
|
||||
Proof(sec, pk, n_proofs, diagonal)
|
||||
{
|
||||
bigint B;
|
||||
B = bigint(1) << sec;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#include "Prover.h"
|
||||
#include "Verifier.h"
|
||||
|
||||
#include "FHE/P2Data.h"
|
||||
#include "Tools/random.h"
|
||||
@@ -27,7 +28,7 @@ Prover<FD,U>::Prover(Proof& proof, const FD& FieldD) :
|
||||
template <class FD, class U>
|
||||
void Prover<FD,U>::Stage_1(const Proof& P, octetStream& ciphertexts,
|
||||
const AddableVector<Ciphertext>& c,
|
||||
const FHE_PK& pk, bool Diag, bool binary)
|
||||
const FHE_PK& pk, bool binary)
|
||||
{
|
||||
size_t allocate = 3 * c.size() * c[0].report_size(USED);
|
||||
ciphertexts.resize_precise(allocate);
|
||||
@@ -50,7 +51,9 @@ void Prover<FD,U>::Stage_1(const Proof& P, octetStream& ciphertexts,
|
||||
// AE.randomize(Diag,binary);
|
||||
// rd=RandPoly(phim,bd<<1);
|
||||
// y[i]=AE.plaintext()+pr*rd;
|
||||
y[i].randomize(G, P.B_plain_length, Diag, binary);
|
||||
y[i].randomize(G, P.B_plain_length, P.get_diagonal(), binary);
|
||||
if (P.get_diagonal())
|
||||
assert(y[i].is_diagonal());
|
||||
s[i].resize(3, P.phim);
|
||||
s[i].generateUniform(G, P.B_rand_length);
|
||||
rc.assign(s[i][0], s[i][1], s[i][2]);
|
||||
@@ -78,10 +81,14 @@ bool Prover<FD,U>::Stage_2(Proof& P, octetStream& cleartexts,
|
||||
#endif
|
||||
cleartexts.reset_write_head();
|
||||
cleartexts.store(P.V);
|
||||
if (P.get_diagonal())
|
||||
for (auto& xx : x)
|
||||
assert(xx.is_diagonal());
|
||||
for (i=0; i<P.V; i++)
|
||||
{ z=y[i];
|
||||
t=s[i];
|
||||
P.apply_challenge(i, z, x, pk);
|
||||
Check_Decoding(z, P.get_diagonal(), x[0].get_field());
|
||||
P.apply_challenge(i, t, r, pk);
|
||||
if (not P.check_bounds(z, t, i))
|
||||
return false;
|
||||
@@ -108,7 +115,7 @@ size_t Prover<FD,U>::NIZKPoK(Proof& P, octetStream& ciphertexts, octetStream& cl
|
||||
const AddableVector<Ciphertext>& c,
|
||||
const vector<U>& x,
|
||||
const Proof::Randomness& r,
|
||||
bool Diag,bool binary)
|
||||
bool binary)
|
||||
{
|
||||
// AElement<T> AE;
|
||||
// for (i=0; i<P.sec; i++)
|
||||
@@ -123,7 +130,7 @@ size_t Prover<FD,U>::NIZKPoK(Proof& P, octetStream& ciphertexts, octetStream& cl
|
||||
int cnt=0;
|
||||
while (!ok)
|
||||
{ cnt++;
|
||||
Stage_1(P,ciphertexts,c,pk,Diag,binary);
|
||||
Stage_1(P,ciphertexts,c,pk,binary);
|
||||
P.set_challenge(ciphertexts);
|
||||
// Check check whether we are OK, or whether we should abort
|
||||
ok = Stage_2(P,cleartexts,x,r,pk);
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
Prover(Proof& proof, const FD& FieldD);
|
||||
|
||||
void Stage_1(const Proof& P, octetStream& ciphertexts, const AddableVector<Ciphertext>& c,
|
||||
const FHE_PK& pk, bool Diag,
|
||||
const FHE_PK& pk,
|
||||
bool binary = false);
|
||||
|
||||
bool Stage_2(Proof& P, octetStream& cleartexts,
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
const AddableVector<Ciphertext>& c,
|
||||
const vector<U>& x,
|
||||
const Proof::Randomness& r,
|
||||
bool Diag,bool binary=false);
|
||||
bool binary=false);
|
||||
|
||||
size_t report_size(ReportType type);
|
||||
void report_size(ReportType type, MemoryUsage& res);
|
||||
|
||||
@@ -22,8 +22,9 @@ SimpleEncCommitBase<T, FD, S>::SimpleEncCommitBase(const MachineBase& machine) :
|
||||
template<class T,class FD,class S>
|
||||
SimpleEncCommit<T, FD, S>::SimpleEncCommit(const PlayerBase& P, const FHE_PK& pk,
|
||||
const FD& FTD, map<string, Timer>& timers, const MachineBase& machine,
|
||||
int thread_num) :
|
||||
NonInteractiveProofSimpleEncCommit<FD>(P, pk, FTD, timers, machine),
|
||||
int thread_num, bool diagonal) :
|
||||
NonInteractiveProofSimpleEncCommit<FD>(P, pk, FTD, timers, machine,
|
||||
diagonal),
|
||||
SimpleEncCommitFactory<FD>(pk, FTD, machine)
|
||||
{
|
||||
(void)thread_num;
|
||||
@@ -32,13 +33,14 @@ SimpleEncCommit<T, FD, S>::SimpleEncCommit(const PlayerBase& P, const FHE_PK& pk
|
||||
template <class FD>
|
||||
NonInteractiveProofSimpleEncCommit<FD>::NonInteractiveProofSimpleEncCommit(
|
||||
const PlayerBase& P, const FHE_PK& pk, const FD& FTD,
|
||||
map<string, Timer>& timers, const MachineBase& machine) :
|
||||
map<string, Timer>& timers, const MachineBase& machine,
|
||||
bool diagonal) :
|
||||
SimpleEncCommitBase_<FD>(machine),
|
||||
P(P), pk(pk), FTD(FTD),
|
||||
proof(machine.sec, pk, machine.extra_slack),
|
||||
proof(machine.sec, pk, machine.extra_slack, diagonal),
|
||||
#ifdef LESS_ALLOC_MORE_MEM
|
||||
r(proof.U, this->pk.get_params()), prover(proof, FTD),
|
||||
verifier(proof),
|
||||
verifier(proof, FTD),
|
||||
#endif
|
||||
timers(timers)
|
||||
{
|
||||
@@ -72,7 +74,7 @@ void SimpleEncCommitFactory<FD>::next(Plaintext_<FD>& mess, Ciphertext& C)
|
||||
mess = m[cnt];
|
||||
C = c[cnt];
|
||||
|
||||
if (Proof::use_top_gear(pk))
|
||||
if (get_proof().use_top_gear(pk))
|
||||
{
|
||||
mess = mess + mess;
|
||||
C = C + C;
|
||||
@@ -86,7 +88,10 @@ template <class FD>
|
||||
void SimpleEncCommitFactory<FD>::prepare_plaintext(PRNG& G)
|
||||
{
|
||||
for (auto& mess : m)
|
||||
mess.randomize(G);
|
||||
if (get_proof().get_diagonal())
|
||||
mess.randomize(G, Diagonal);
|
||||
else
|
||||
mess.randomize(G);
|
||||
}
|
||||
|
||||
template<class T,class FD,class S>
|
||||
@@ -126,7 +131,7 @@ size_t NonInteractiveProofSimpleEncCommit<FD>::generate_proof(AddableVector<Ciph
|
||||
Prover<FD, Plaintext_<FD> > prover(proof, FTD);
|
||||
#endif
|
||||
size_t prover_memory = prover.NIZKPoK(proof, ciphertexts, cleartexts,
|
||||
pk, c, m, r, false, false);
|
||||
pk, c, m, r, false);
|
||||
timers["Proving"].stop();
|
||||
|
||||
if (proof.top_gear)
|
||||
@@ -187,7 +192,7 @@ size_t NonInteractiveProofSimpleEncCommit<FD>::create_more(octetStream& cipherte
|
||||
#endif
|
||||
timers["Verifying"].start();
|
||||
verifier.NIZKPoK(others_ciphertexts, ciphertexts,
|
||||
cleartexts, get_pk_for_verification(i), false, false);
|
||||
cleartexts, get_pk_for_verification(i), false);
|
||||
timers["Verifying"].stop();
|
||||
add_ciphertexts(others_ciphertexts, i);
|
||||
this->memory_usage.update("verifier", verifier.report_size(CAPACITY));
|
||||
@@ -214,12 +219,12 @@ void SimpleEncCommit<T, FD, S>::add_ciphertexts(
|
||||
template<class FD>
|
||||
SummingEncCommit<FD>::SummingEncCommit(const Player& P, const FHE_PK& pk,
|
||||
const FD& FTD, map<string, Timer>& timers, const MachineBase& machine,
|
||||
int thread_num) :
|
||||
int thread_num, bool diagonal) :
|
||||
SimpleEncCommitFactory<FD>(pk, FTD, machine), SimpleEncCommitBase_<FD>(
|
||||
machine), proof(machine.sec, pk, P.num_players()), pk(pk), FTD(
|
||||
machine), proof(machine.sec, pk, P.num_players(), diagonal), pk(pk), FTD(
|
||||
FTD), P(P), thread_num(thread_num),
|
||||
#ifdef LESS_ALLOC_MORE_MEM
|
||||
prover(proof, FTD), verifier(proof), preimages(proof.V,
|
||||
prover(proof, FTD), verifier(proof, FTD), preimages(proof.V,
|
||||
this->pk, FTD.get_prime(), P.num_players()),
|
||||
#endif
|
||||
timers(timers)
|
||||
@@ -246,7 +251,7 @@ void SummingEncCommit<FD>::create_more()
|
||||
#endif
|
||||
this->generate_ciphertexts(this->c, this->m, r, pk, timers, proof);
|
||||
this->timers["Stage 1 of proof"].start();
|
||||
prover.Stage_1(proof, ciphertexts, this->c, this->pk, false, false);
|
||||
prover.Stage_1(proof, ciphertexts, this->c, this->pk, false);
|
||||
this->timers["Stage 1 of proof"].stop();
|
||||
|
||||
this->c.unpack(ciphertexts, this->pk);
|
||||
@@ -307,7 +312,7 @@ void SummingEncCommit<FD>::create_more()
|
||||
Verifier<FD> verifier(proof);
|
||||
#endif
|
||||
verifier.Stage_2(this->c, ciphertexts, cleartexts,
|
||||
this->pk, false, false);
|
||||
this->pk, false);
|
||||
this->timers["Verifying"].stop();
|
||||
this->cnt = proof.U - 1;
|
||||
|
||||
@@ -362,9 +367,9 @@ size_t SummingEncCommit<FD>::report_size(ReportType type)
|
||||
template <class FD>
|
||||
MultiEncCommit<FD>::MultiEncCommit(const Player& P, const vector<FHE_PK>& pks,
|
||||
const FD& FTD, map<string, Timer>& timers, MachineBase& machine,
|
||||
PairwiseGenerator<FD>& generator) :
|
||||
PairwiseGenerator<FD>& generator, bool diagonal) :
|
||||
NonInteractiveProofSimpleEncCommit<FD>(P, pks[P.my_real_num()], FTD,
|
||||
timers, machine), pks(pks), P(P), generator(generator)
|
||||
timers, machine, diagonal), pks(pks), P(P), generator(generator)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -65,13 +65,15 @@ public:
|
||||
|
||||
NonInteractiveProofSimpleEncCommit(const PlayerBase& P, const FHE_PK& pk,
|
||||
const FD& FTD, map<string, Timer>& timers,
|
||||
const MachineBase& machine);
|
||||
const MachineBase& machine, bool diagonal = false);
|
||||
virtual ~NonInteractiveProofSimpleEncCommit() {}
|
||||
size_t generate_proof(AddableVector<Ciphertext>& c, vector<Plaintext_<FD> >& m,
|
||||
octetStream& ciphertexts, octetStream& cleartexts);
|
||||
size_t generate_proof(AddableVector<Ciphertext>& c,
|
||||
vector<Plaintext_<FD> >& m, octetStream& ciphertexts,
|
||||
octetStream& cleartexts);
|
||||
size_t create_more(octetStream& my_ciphertext, octetStream& my_cleartext);
|
||||
virtual size_t report_size(ReportType type);
|
||||
using SimpleEncCommitBase_<FD>::report_size;
|
||||
Proof& get_proof() { return proof; }
|
||||
};
|
||||
|
||||
template <class FD>
|
||||
@@ -96,6 +98,7 @@ public:
|
||||
void next(Plaintext_<FD>& mess, Ciphertext& C);
|
||||
virtual size_t report_size(ReportType type);
|
||||
void report_size(ReportType type, MemoryUsage& res);
|
||||
virtual Proof& get_proof() = 0;
|
||||
};
|
||||
|
||||
template<class T,class FD,class S>
|
||||
@@ -111,13 +114,15 @@ protected:
|
||||
|
||||
public:
|
||||
SimpleEncCommit(const PlayerBase& P, const FHE_PK& pk, const FD& FTD,
|
||||
map<string, Timer>& timers, const MachineBase& machine, int thread_num);
|
||||
map<string, Timer>& timers, const MachineBase& machine,
|
||||
int thread_num, bool diagonal = false);
|
||||
void next(Plaintext_<FD>& mess, Ciphertext& C) { SimpleEncCommitFactory<FD>::next(mess, C); }
|
||||
void create_more();
|
||||
size_t report_size(ReportType type)
|
||||
{ return SimpleEncCommitFactory<FD>::report_size(type) + EncCommitBase_<FD>::report_size(type); }
|
||||
void report_size(ReportType type, MemoryUsage& res)
|
||||
{ SimpleEncCommitFactory<FD>::report_size(type, res); SimpleEncCommitBase_<FD>::report_size(type, res); }
|
||||
Proof& get_proof() { return NonInteractiveProofSimpleEncCommit<FD>::get_proof(); }
|
||||
};
|
||||
|
||||
template <class FD>
|
||||
@@ -146,13 +151,15 @@ public:
|
||||
map<string, Timer>& timers;
|
||||
|
||||
SummingEncCommit(const Player& P, const FHE_PK& pk, const FD& FTD,
|
||||
map<string, Timer>& timers, const MachineBase& machine, int thread_num);
|
||||
map<string, Timer>& timers, const MachineBase& machine,
|
||||
int thread_num, bool diagonal = false);
|
||||
|
||||
void next(Plaintext_<FD>& mess, Ciphertext& C) { SimpleEncCommitFactory<FD>::next(mess, C); }
|
||||
void create_more();
|
||||
size_t report_size(ReportType type);
|
||||
void report_size(ReportType type, MemoryUsage& res)
|
||||
{ SimpleEncCommitFactory<FD>::report_size(type, res); SimpleEncCommitBase_<FD>::report_size(type, res); }
|
||||
Proof& get_proof() { return proof; }
|
||||
};
|
||||
|
||||
template <class FD>
|
||||
@@ -179,7 +186,7 @@ public:
|
||||
MultiEncCommit(const Player& P, const vector<FHE_PK>& pks,
|
||||
const FD& FTD,
|
||||
map<string, Timer>& timers, MachineBase& machine,
|
||||
PairwiseGenerator<FD>& generator);
|
||||
PairwiseGenerator<FD>& generator, bool diagonal = false);
|
||||
};
|
||||
|
||||
#endif /* FHEOFFLINE_SIMPLEENCCOMMIT_H_ */
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#include "Math/modp.hpp"
|
||||
|
||||
template <class FD>
|
||||
Verifier<FD>::Verifier(Proof& proof) : P(proof)
|
||||
Verifier<FD>::Verifier(Proof& proof, const FD& FieldD) :
|
||||
P(proof), FieldD(FieldD)
|
||||
{
|
||||
#ifdef LESS_ALLOC_MORE_MEM
|
||||
z.resize(proof.phim);
|
||||
@@ -30,12 +31,28 @@ bool Check_Decoding(const Plaintext<T,FD,S>& AE,bool Diag)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class S>
|
||||
bool Check_Decoding(const vector<S>& AE, bool Diag)
|
||||
template <>
|
||||
bool Check_Decoding(const vector<Proof::bound_type>& AE, bool Diag, const FFT_Data&)
|
||||
{
|
||||
(void)AE;
|
||||
if (Diag)
|
||||
throw not_implemented();
|
||||
{
|
||||
for (size_t i = 1; i < AE.size(); i++)
|
||||
if (AE[i] != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Check_Decoding(const vector<Proof::bound_type>& AE, bool Diag, const P2Data& p2d)
|
||||
{
|
||||
if (Diag)
|
||||
{
|
||||
Plaintext_<P2Data> tmp(p2d);
|
||||
for (size_t i = 0; i < AE.size(); i++)
|
||||
tmp.set_coeff(i, AE[i].get_limb(0) % 2);
|
||||
return tmp.is_diagonal();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,7 +62,7 @@ template <class FD>
|
||||
void Verifier<FD>::Stage_2(
|
||||
AddableVector<Ciphertext>& c,octetStream& ciphertexts,
|
||||
octetStream& cleartexts,
|
||||
const FHE_PK& pk,bool Diag,bool binary)
|
||||
const FHE_PK& pk,bool binary)
|
||||
{
|
||||
unsigned int i, V;
|
||||
|
||||
@@ -76,12 +93,7 @@ void Verifier<FD>::Stage_2(
|
||||
{ cout << "Fail Check 6 " << i << endl;
|
||||
throw runtime_error("ciphertexts don't match");
|
||||
}
|
||||
}
|
||||
|
||||
// Now check decoding z[i]
|
||||
for (i=0; i<V; i++)
|
||||
{
|
||||
if (!Check_Decoding(z,Diag))
|
||||
if (!Check_Decoding(z,P.get_diagonal(),FieldD))
|
||||
{ cout << "\tCheck : " << i << endl;
|
||||
throw runtime_error("cleartext isn't diagonal");
|
||||
}
|
||||
@@ -100,16 +112,16 @@ void Verifier<FD>::Stage_2(
|
||||
template <class FD>
|
||||
void Verifier<FD>::NIZKPoK(AddableVector<Ciphertext>& c,
|
||||
octetStream& ciphertexts, octetStream& cleartexts,
|
||||
const FHE_PK& pk,bool Diag,
|
||||
const FHE_PK& pk,
|
||||
bool binary)
|
||||
{
|
||||
P.set_challenge(ciphertexts);
|
||||
|
||||
Stage_2(c,ciphertexts,cleartexts,pk,Diag,binary);
|
||||
Stage_2(c,ciphertexts,cleartexts,pk,binary);
|
||||
|
||||
if (P.top_gear)
|
||||
{
|
||||
assert(not Diag);
|
||||
assert(not P.get_diagonal());
|
||||
assert(not binary);
|
||||
c += c;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include "Proof.h"
|
||||
|
||||
template <class FD>
|
||||
bool Check_Decoding(const vector<Proof::bound_type>& AE, bool Diag, FD& FieldD);
|
||||
|
||||
/* Defines the Verifier */
|
||||
template <class FD>
|
||||
class Verifier
|
||||
@@ -11,20 +14,21 @@ class Verifier
|
||||
AddableMatrix<Int_Random_Coins::value_type::value_type> t;
|
||||
|
||||
Proof& P;
|
||||
const FD& FieldD;
|
||||
|
||||
public:
|
||||
Verifier(Proof& proof);
|
||||
Verifier(Proof& proof, const FD& FieldD);
|
||||
|
||||
void Stage_2(
|
||||
AddableVector<Ciphertext>& c, octetStream& ciphertexts,
|
||||
octetStream& cleartexts,const FHE_PK& pk,bool Diag,bool binary=false);
|
||||
octetStream& cleartexts,const FHE_PK& pk,bool binary=false);
|
||||
|
||||
/* This is the non-interactive version using the ROM
|
||||
- Creates space for all output values
|
||||
- Diag flag mirrors that in Prover
|
||||
*/
|
||||
void NIZKPoK(AddableVector<Ciphertext>& c,octetStream& ciphertexts,octetStream& cleartexts,
|
||||
const FHE_PK& pk,bool Diag,bool binary=false);
|
||||
const FHE_PK& pk,bool binary=false);
|
||||
|
||||
size_t report_size(ReportType type) { return z.report_size(type) + t.report_size(type); }
|
||||
};
|
||||
|
||||
@@ -136,6 +136,7 @@
|
||||
X(RUN_TAPE, MACH->run_tapes(EXTRA)) \
|
||||
X(JOIN_TAPE, MACH->join_tape(R0)) \
|
||||
X(USE, ) \
|
||||
X(USE_INP, ) \
|
||||
|
||||
#define INSTRUCTIONS BIT_INSTRUCTIONS GC_INSTRUCTIONS
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "Processor/Data_Files.hpp"
|
||||
#include "Processor/Instruction.hpp"
|
||||
#include "Processor/Machine.hpp"
|
||||
#include "Processor/FieldMachine.hpp"
|
||||
|
||||
#include "Protocols/MAC_Check.hpp"
|
||||
#include "Protocols/fake-stuff.hpp"
|
||||
#include "Protocols/Beaver.hpp"
|
||||
@@ -26,4 +28,6 @@
|
||||
#include "GC/ShareSecret.hpp"
|
||||
#include "GC/TinierSharePrep.hpp"
|
||||
|
||||
#include "Math/gfp.hpp"
|
||||
|
||||
#endif /* MACHINES_SPDZ_HPP_ */
|
||||
|
||||
16
Machines/highgear-party.cpp
Normal file
16
Machines/highgear-party.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* highgear-party.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Protocols/HighGearShare.h"
|
||||
|
||||
#include "SPDZ.hpp"
|
||||
#include "Protocols/ChaiGearPrep.hpp"
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
ez::ezOptionParser opt;
|
||||
CowGearOptions::singleton = CowGearOptions(opt, argc, argv, false);
|
||||
DishonestMajorityFieldMachine<HighGearShare, HighGearShare, gf2n_short>(argc, argv, opt);
|
||||
}
|
||||
16
Machines/lowgear-party.cpp
Normal file
16
Machines/lowgear-party.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* lowgear-party.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Protocols/LowGearShare.h"
|
||||
|
||||
#include "SPDZ.hpp"
|
||||
#include "Protocols/CowGearPrep.hpp"
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
ez::ezOptionParser opt;
|
||||
CowGearOptions::singleton = CowGearOptions(opt, argc, argv, false);
|
||||
DishonestMajorityFieldMachine<LowGearShare, LowGearShare, gf2n_short>(argc, argv, opt);
|
||||
}
|
||||
6
Makefile
6
Makefile
@@ -47,7 +47,7 @@ binary: rep-bin yao semi-bin-party.x tinier-party.x tiny-party.x ccd-party.x mal
|
||||
|
||||
ifeq ($(USE_NTL),1)
|
||||
all: overdrive she-offline
|
||||
gear: cowgear-party.x chaigear-party.x
|
||||
gear: cowgear-party.x chaigear-party.x lowgear-party.x highgear-party.x
|
||||
arithmetic: hemi-party.x soho-party.x gear
|
||||
endif
|
||||
|
||||
@@ -186,10 +186,14 @@ hemi-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT)
|
||||
soho-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT)
|
||||
cowgear-party.x: $(FHEOFFLINE) Protocols/CowGearOptions.o $(OT)
|
||||
chaigear-party.x: $(FHEOFFLINE) Protocols/CowGearOptions.o $(OT)
|
||||
lowgear-party.x: $(FHEOFFLINE) $(OT) Protocols/CowGearOptions.o Protocols/LowGearKeyGen.o
|
||||
highgear-party.x: $(FHEOFFLINE) $(OT) Protocols/CowGearOptions.o Protocols/HighGearKeyGen.o
|
||||
static/hemi-party.x: $(FHEOFFLINE)
|
||||
static/soho-party.x: $(FHEOFFLINE)
|
||||
static/cowgear-party.x: $(FHEOFFLINE)
|
||||
static/chaigear-party.x: $(FHEOFFLINE)
|
||||
static/lowgear-party.x: $(FHEOFFLINE) Protocols/CowGearOptions.o Protocols/LowGearKeyGen.o
|
||||
static/highgear-party.x: $(FHEOFFLINE) Protocols/CowGearOptions.o Protocols/HighGearKeyGen.o
|
||||
mascot-party.x: Machines/SPDZ.o $(OT)
|
||||
static/mascot-party.x: Machines/SPDZ.o
|
||||
Player-Online.x: Machines/SPDZ.o $(OT)
|
||||
|
||||
@@ -34,6 +34,11 @@ public:
|
||||
{
|
||||
return L * T::size();
|
||||
}
|
||||
static int size_in_bits()
|
||||
{
|
||||
return L * T::size_in_bits();
|
||||
}
|
||||
|
||||
static string type_string()
|
||||
{
|
||||
return T::type_string() + "^" + to_string(L);
|
||||
|
||||
@@ -146,8 +146,10 @@ void check_setup(string dir, bigint pr)
|
||||
bigint p;
|
||||
string filename = dir + "Params-Data";
|
||||
ifstream(filename) >> p;
|
||||
if (p == 0)
|
||||
throw runtime_error("no modulus in " + filename);
|
||||
if (p != pr)
|
||||
throw runtime_error("wrong modulus in " + dir);
|
||||
throw runtime_error("wrong modulus in " + filename);
|
||||
}
|
||||
|
||||
string get_prep_sub_dir(const string& prep_dir, int nparties, int log2mod,
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
template<class T>
|
||||
static void init(bool mont = true) { (void) mont; }
|
||||
static void init_default(int, bool = true) {}
|
||||
static void init_field() {}
|
||||
static void init_field(const bigint& = {}) {}
|
||||
|
||||
static void read_or_generate_setup(const string&, const OnlineOptions&) {}
|
||||
template<class T>
|
||||
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
bigint& operator=(int n);
|
||||
bigint& operator=(long n);
|
||||
bigint& operator=(word n);
|
||||
bigint& operator=(double f);
|
||||
template<int X, int L>
|
||||
bigint& operator=(const gfp_<X, L>& other);
|
||||
template<int K>
|
||||
@@ -138,6 +139,12 @@ inline bigint& bigint::operator=(word n)
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bigint& bigint::operator=(double f)
|
||||
{
|
||||
mpz_class::operator=(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<int K>
|
||||
bigint::bigint(const Z2<K>& x)
|
||||
{
|
||||
|
||||
@@ -45,6 +45,14 @@ class modp_
|
||||
inline_mpn_zero(x + M, L - M);
|
||||
}
|
||||
|
||||
template<int X, int M>
|
||||
modp_(const gfp_<X, M>& other) :
|
||||
modp_()
|
||||
{
|
||||
assert(M <= L);
|
||||
inline_mpn_copyi(x, other.get().get(), M);
|
||||
}
|
||||
|
||||
const mp_limb_t* get() const { return x; }
|
||||
|
||||
void assign(const void* buffer, int t) { memcpy(x, buffer, t * sizeof(mp_limb_t)); }
|
||||
|
||||
@@ -11,7 +11,15 @@
|
||||
template<int L>
|
||||
void modp_<L>::randomize(PRNG& G, const Zp_Data& ZpD)
|
||||
{
|
||||
G.randomBnd(x, ZpD.get_prA(), ZpD.pr_byte_length, ZpD.overhang_mask());
|
||||
const int M = sizeof(mp_limb_t) * L;
|
||||
switch (ZpD.pr_byte_length)
|
||||
{
|
||||
#define X(LL) case LL: G.randomBnd<LL>(x, ZpD.get_prA(), ZpD.overhang_mask()); break;
|
||||
X(M) X(M-1) X(M-2) X(M-3) X(M-4) X(M-5) X(M-6) X(M-7)
|
||||
#undef X
|
||||
default:
|
||||
G.randomBnd(x, ZpD.get_prA(), ZpD.pr_byte_length, ZpD.overhang_mask());
|
||||
}
|
||||
}
|
||||
|
||||
template<int L>
|
||||
|
||||
@@ -155,25 +155,28 @@ void CryptoPlayer::send_receive_all_no_stats(const vector<vector<bool>>& channel
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoPlayer::partial_broadcast(const vector<bool>& senders,
|
||||
void CryptoPlayer::partial_broadcast(const vector<bool>& my_senders,
|
||||
const vector<bool>& my_receivers,
|
||||
vector<octetStream>& os) const
|
||||
{
|
||||
TimeScope ts(comm_stats["Partial broadcasting"].add(os[my_num()]));
|
||||
sent += os[my_num()].get_length() * (num_players() - 1);
|
||||
for (int offset = 1; offset < num_players(); offset++)
|
||||
{
|
||||
int other = get_player(offset);
|
||||
bool receive = senders[other];
|
||||
if (senders[my_num()])
|
||||
bool receive = my_senders[other];
|
||||
if (my_receivers[other])
|
||||
{
|
||||
this->senders[other]->request(os[my_num()]);
|
||||
sent += os[my_num()].get_length();
|
||||
}
|
||||
if (receive)
|
||||
this->receivers[other]->request(os[other]);
|
||||
}
|
||||
for (int offset = 1; offset < num_players(); offset++)
|
||||
{
|
||||
int other = get_player(offset);
|
||||
bool receive = senders[other];
|
||||
if (senders[my_num()])
|
||||
bool receive = my_senders[other];
|
||||
if (my_receivers[other])
|
||||
this->senders[other]->wait(os[my_num()]);
|
||||
if (receive)
|
||||
this->receivers[other]->wait(os[other]);
|
||||
|
||||
@@ -42,8 +42,8 @@ public:
|
||||
const vector<octetStream>& to_send,
|
||||
vector<octetStream>& to_receive) const;
|
||||
|
||||
void partial_broadcast(const vector<bool>& senders,
|
||||
vector<octetStream>& os) const;
|
||||
void partial_broadcast(const vector<bool>& my_senders,
|
||||
const vector<bool>& my_receivers, vector<octetStream>& os) const;
|
||||
|
||||
void Broadcast_Receive_no_stats(vector<octetStream>& os) const;
|
||||
};
|
||||
|
||||
@@ -522,12 +522,24 @@ void Player::send_receive_all(const vector<vector<bool>>& channels,
|
||||
size_t data = 0;
|
||||
for (int i = 0; i < num_players(); i++)
|
||||
if (i != my_num() and channels.at(my_num()).at(i))
|
||||
data += to_send.at(i).get_length();
|
||||
{
|
||||
data += to_send.at(i).get_length();
|
||||
#ifdef VERBOSE_COMM
|
||||
cerr << "Send " << to_send.at(i).get_length() << " to " << i << endl;
|
||||
#endif
|
||||
}
|
||||
TimeScope ts(comm_stats["Sending/receiving"].add(data));
|
||||
sent += data;
|
||||
send_receive_all_no_stats(channels, to_send, to_receive);
|
||||
}
|
||||
|
||||
void Player::partial_broadcast(const vector<bool>& senders,
|
||||
vector<octetStream>& os) const
|
||||
{
|
||||
partial_broadcast(senders, vector<bool>(num_players(), senders[my_num()]),
|
||||
os);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void MultiPlayer<T>::send_receive_all_no_stats(
|
||||
const vector<vector<bool>>& channels, const vector<octetStream>& to_send,
|
||||
|
||||
@@ -218,7 +218,9 @@ public:
|
||||
const vector<octetStream>& to_send,
|
||||
vector<octetStream>& to_receive) const = 0;
|
||||
|
||||
virtual void partial_broadcast(const vector<bool>&,
|
||||
virtual void partial_broadcast(const vector<bool>& senders,
|
||||
vector<octetStream>& os) const;
|
||||
virtual void partial_broadcast(const vector<bool>&, const vector<bool>&,
|
||||
vector<octetStream>& os) const { unchecked_broadcast(os); }
|
||||
|
||||
// dummy functions for compatibility
|
||||
|
||||
@@ -113,7 +113,8 @@ void set_up_client_socket(int& mysocket,const char* hostname,int Portnum)
|
||||
|
||||
if (fl < 0)
|
||||
{
|
||||
cout << attempts << " attempts" << endl;
|
||||
cout << attempts << " attempts to " << hostname << ":" << Portnum
|
||||
<< endl;
|
||||
error("set_up_socket:connect:", hostname);
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ void NPartyTripleGenerator<W>::generateInputs(int player)
|
||||
mac_sum = (ot_multipliers[i_thread])->input_macs[j];
|
||||
}
|
||||
inputs[j] = {{share, mac_sum}, secrets[j]};
|
||||
auto r = G.get<typename W::mac_key_type>();
|
||||
auto r = G.get<typename W::input_check_type::share_type>();
|
||||
check_sum += typename W::input_check_type(r * share, r * mac_sum);
|
||||
}
|
||||
inputs.resize(nTriplesPerLoop);
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
map<pair<bool, int>, long long> edabits;
|
||||
|
||||
DataPositions(int num_players = 0);
|
||||
DataPositions(const Player& P) : DataPositions(P.num_players()) {}
|
||||
~DataPositions();
|
||||
|
||||
void reset();
|
||||
|
||||
@@ -16,7 +16,13 @@ void FixInput_<Integer>::read(std::istream& in, const int* params)
|
||||
template<>
|
||||
void FixInput_<bigint>::read(std::istream& in, const int* params)
|
||||
{
|
||||
#ifdef HIGH_PREC_INPUT
|
||||
mpf_class x;
|
||||
in >> x;
|
||||
items[0] = x << *params;
|
||||
#else
|
||||
double x;
|
||||
in >> x;
|
||||
items[0] = x * (1 << *params);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ void Machine<sint, sgf2n>::fill_buffers(int thread_number, int tape_number,
|
||||
dynamic_cast<BufferPrep<bit_type>&>(tinfo[thread_number].processor->share_thread.DataF);
|
||||
for (int i = 0; i < DIV_CEIL(usage.files[DATA_GF2][DATA_TRIPLE],
|
||||
bit_type::default_length); i++)
|
||||
dest.push_triple(source.get_triple(bit_type::default_length));
|
||||
dest.push_triple(source.get_triple_no_count(bit_type::default_length));
|
||||
}
|
||||
catch (bad_cast& e)
|
||||
{
|
||||
|
||||
@@ -194,7 +194,9 @@ void OnlineMachine::start_networking()
|
||||
if (ipFileName.size() > 0) {
|
||||
if (my_port != Names::DEFAULT_PORT)
|
||||
throw runtime_error("cannot set port number when using IP file");
|
||||
playerNames.init(playerno, pnbase, ipFileName);
|
||||
if (nplayers == 0 and opt.isSet("-N"))
|
||||
opt.get("-N")->getInt(nplayers);
|
||||
playerNames.init(playerno, pnbase, ipFileName, nplayers);
|
||||
} else {
|
||||
if (not opt.get("-ext-server")->isSet)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,9 @@ public:
|
||||
|
||||
void start(int player, int target, int source);
|
||||
void stop(int player, int dest, int source);
|
||||
|
||||
T start(int player, const T& source);
|
||||
typename T::clear stop(int player, const typename T::clear& masked);
|
||||
};
|
||||
|
||||
#endif /* PROCESSOR_PRIVATEOUTPUT_H_ */
|
||||
|
||||
@@ -8,24 +8,42 @@
|
||||
|
||||
template<class T>
|
||||
void PrivateOutput<T>::start(int player, int target, int source)
|
||||
{
|
||||
proc.get_S_ref(target) = start(player, proc.get_S_ref(source));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T PrivateOutput<T>::start(int player, const T& source)
|
||||
{
|
||||
assert (player < proc.P.num_players());
|
||||
open_type mask;
|
||||
proc.DataF.get_input(proc.get_S_ref(target), mask, player);
|
||||
proc.get_S_ref(target) += proc.get_S_ref(source);
|
||||
T res;
|
||||
proc.DataF.get_input(res, mask, player);
|
||||
res += source;
|
||||
|
||||
if (player == proc.P.my_num())
|
||||
masks.push_back(mask);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PrivateOutput<T>::stop(int player, int dest, int source)
|
||||
{
|
||||
if (player == proc.P.my_num() and proc.Proc)
|
||||
{
|
||||
auto& value = proc.get_C_ref(dest);
|
||||
value = (proc.get_C_ref(source) - masks.front());
|
||||
auto& value = proc.get_C_ref(dest);
|
||||
value = stop(player, proc.get_C_ref(source));
|
||||
if (proc.Proc)
|
||||
value.output(proc.Proc->private_output, false);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename T::clear PrivateOutput<T>::stop(int player, const typename T::clear& source)
|
||||
{
|
||||
typename T::clear value;
|
||||
if (player == proc.P.my_num())
|
||||
{
|
||||
value = source - masks.front();
|
||||
masks.pop_front();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ SubProcessor<T>::SubProcessor(typename T::MAC_Check& MC,
|
||||
template<class T>
|
||||
SubProcessor<T>::~SubProcessor()
|
||||
{
|
||||
protocol.check();
|
||||
|
||||
for (size_t i = 0; i < personal_bit_preps.size(); i++)
|
||||
{
|
||||
auto& x = personal_bit_preps[i];
|
||||
@@ -225,8 +227,9 @@ void Processor<sint, sgf2n>::split(const Instruction& instruction)
|
||||
assert(unit == 64);
|
||||
int n_inputs = instruction.get_size();
|
||||
int n_bits = instruction.get_start().size() / n;
|
||||
assert(share_thread.protocol != 0);
|
||||
sint::split(Procb.S, instruction.get_start(), n_bits,
|
||||
&read_Sp(instruction.get_r(0)), n_inputs, P);
|
||||
&read_Sp(instruction.get_r(0)), n_inputs, *share_thread.protocol);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -85,13 +85,14 @@ if '2dense' in program.args:
|
||||
|
||||
program.disable_memory_warnings()
|
||||
|
||||
layers[-1].Y.input_from(0)
|
||||
layers[0].X.input_from(0)
|
||||
|
||||
Y = sint.Matrix(n_test, 10)
|
||||
X = sfix.Matrix(n_test, n_features)
|
||||
Y.input_from(0)
|
||||
X.input_from(0)
|
||||
|
||||
if not ('no_acc' in program.args and 'no_loss' in program.args):
|
||||
layers[-1].Y.input_from(0)
|
||||
layers[0].X.input_from(0)
|
||||
Y.input_from(0)
|
||||
X.input_from(0)
|
||||
|
||||
if 'always_acc' in program.args:
|
||||
n_part_epochs = 1
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
|
||||
Beaver(Player& P) : prep(0), MC(0), P(P) {}
|
||||
|
||||
Player& branch();
|
||||
|
||||
void init_mul(SubProcessor<T>* proc);
|
||||
void init_mul(Preprocessing<T>& prep, typename T::MAC_Check& MC);
|
||||
typename T::clear prepare_mul(const T& x, const T& y, int n = -1);
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
template<class T>
|
||||
Player& Beaver<T>::branch()
|
||||
{
|
||||
return P;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Beaver<T>::init_mul(SubProcessor<T>* proc)
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
BrainPrep(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@ class ChaiGearPrep : public MaliciousRingPrep<T>
|
||||
|
||||
Generator& get_generator();
|
||||
|
||||
template<int>
|
||||
void buffer_bits(true_type);
|
||||
template<int>
|
||||
void buffer_bits(false_type);
|
||||
|
||||
public:
|
||||
static void basic_setup(Player& P);
|
||||
static void key_setup(Player& P, mac_key_type alphai);
|
||||
@@ -32,6 +37,7 @@ public:
|
||||
ChaiGearPrep(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage), generator(0), square_producer(0),
|
||||
input_producer(0)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "FHEOffline/SimpleMachine.h"
|
||||
#include "FHEOffline/Producer.h"
|
||||
|
||||
#include "FHEOffline/DataSetup.hpp"
|
||||
|
||||
template<class T>
|
||||
MultiplicativeMachine* ChaiGearPrep<T>::machine = 0;
|
||||
template<class T>
|
||||
@@ -65,7 +67,8 @@ void ChaiGearPrep<T>::key_setup(Player& P, mac_key_type alphai)
|
||||
assert(machine);
|
||||
auto& setup = machine->setup.part<FD>();
|
||||
auto& options = CowGearOptions::singleton;
|
||||
setup.covert_secrets_generation(P, *machine, options.covert_security);
|
||||
read_or_generate_secrets(setup, P, *machine, options.covert_security,
|
||||
T::covert);
|
||||
|
||||
// adjust mac key
|
||||
mac_key_type diff = alphai - setup.alphai;
|
||||
@@ -169,14 +172,22 @@ void ChaiGearPrep<T>::buffer_inputs(int player)
|
||||
|
||||
template<class T>
|
||||
inline void ChaiGearPrep<T>::buffer_bits()
|
||||
{
|
||||
buffer_bits<0>(T::clear::characteristic_two);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<int>
|
||||
void ChaiGearPrep<T>::buffer_bits(false_type)
|
||||
{
|
||||
buffer_bits_from_squares(*this);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void ChaiGearPrep<ChaiGearShare<gf2n_short>>::buffer_bits()
|
||||
template<class T>
|
||||
template<int>
|
||||
void ChaiGearPrep<T>::buffer_bits(true_type)
|
||||
{
|
||||
buffer_bits_without_check();
|
||||
this->buffer_bits_without_check();
|
||||
assert(not this->bits.empty());
|
||||
for (auto& bit : this->bits)
|
||||
bit.force_to_bit();
|
||||
|
||||
@@ -26,6 +26,8 @@ public:
|
||||
|
||||
const static bool needs_ot = false;
|
||||
|
||||
const static true_type covert;
|
||||
|
||||
ChaiGearShare()
|
||||
{
|
||||
}
|
||||
@@ -37,5 +39,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
const true_type ChaiGearShare<T>::covert;
|
||||
|
||||
#endif /* PROTOCOLS_CHAIGEARSHARE_H_ */
|
||||
|
||||
@@ -12,38 +12,44 @@ using namespace std;
|
||||
|
||||
CowGearOptions CowGearOptions::singleton;
|
||||
|
||||
CowGearOptions::CowGearOptions()
|
||||
CowGearOptions::CowGearOptions(bool covert)
|
||||
{
|
||||
covert_security = 20;
|
||||
lowgear_from_covert();
|
||||
if (covert)
|
||||
{
|
||||
covert_security = 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
covert_security = -1;
|
||||
}
|
||||
|
||||
lowgear_security = 40;
|
||||
use_top_gear = false;
|
||||
}
|
||||
|
||||
void CowGearOptions::lowgear_from_covert()
|
||||
{
|
||||
lowgear_security = ceil(log2(covert_security));
|
||||
}
|
||||
|
||||
CowGearOptions::CowGearOptions(ez::ezOptionParser& opt, int argc,
|
||||
const char** argv) : CowGearOptions()
|
||||
const char** argv, bool covert) : CowGearOptions(covert)
|
||||
{
|
||||
if (covert)
|
||||
{
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
("Covert security parameter c. "
|
||||
"Cheating will be detected with probability 1/c (default: "
|
||||
+ to_string(covert_security) + ")").c_str(), // Help description.
|
||||
"-c", // Flag token.
|
||||
"--covert-security" // Flag token.
|
||||
);
|
||||
}
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
("Covert security parameter c. "
|
||||
"Cheating will be detected with probability 1/c (default: "
|
||||
+ to_string(covert_security) + ")").c_str(), // Help description.
|
||||
"-c", // Flag token.
|
||||
"--covert-security" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"LowGear security parameter (default: ceil(log2(c))", // Help description.
|
||||
"LowGear security parameter (default: 40)", // Help description.
|
||||
"-l", // Flag token.
|
||||
"--lowgear-security" // Flag token.
|
||||
);
|
||||
@@ -71,8 +77,6 @@ CowGearOptions::CowGearOptions(ez::ezOptionParser& opt, int argc,
|
||||
if (covert_security > (1LL << lowgear_security))
|
||||
insecure(", LowGear security less than key generation security");
|
||||
}
|
||||
else
|
||||
lowgear_from_covert();
|
||||
use_top_gear = opt.isSet("-T");
|
||||
opt.resetArgs();
|
||||
}
|
||||
|
||||
@@ -12,21 +12,25 @@ class CowGearOptions
|
||||
{
|
||||
bool use_top_gear;
|
||||
|
||||
void lowgear_from_covert();
|
||||
|
||||
public:
|
||||
static CowGearOptions singleton;
|
||||
|
||||
int covert_security;
|
||||
int lowgear_security;
|
||||
|
||||
CowGearOptions();
|
||||
CowGearOptions(ez::ezOptionParser& opt, int argc, const char** argv);
|
||||
CowGearOptions(bool covert = true);
|
||||
CowGearOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
bool covert = true);
|
||||
|
||||
bool top_gear()
|
||||
{
|
||||
return use_top_gear;
|
||||
}
|
||||
|
||||
void set_top_gear(bool use)
|
||||
{
|
||||
use_top_gear = use;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* PROTOCOLS_COWGEAROPTIONS_H_ */
|
||||
|
||||
@@ -24,6 +24,11 @@ class CowGearPrep : public MaliciousRingPrep<T>
|
||||
|
||||
PairwiseGenerator<FD>& get_generator();
|
||||
|
||||
template<int>
|
||||
void buffer_bits(true_type);
|
||||
template<int>
|
||||
void buffer_bits(false_type);
|
||||
|
||||
public:
|
||||
static void basic_setup(Player& P);
|
||||
static void key_setup(Player& P, mac_key_type alphai);
|
||||
@@ -33,6 +38,7 @@ public:
|
||||
CowGearPrep(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage),
|
||||
BitPrep<T>(proc, usage), RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage),
|
||||
pairwise_generator(0)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Tools/Bundle.h"
|
||||
|
||||
#include "Protocols/ReplicatedPrep.hpp"
|
||||
#include "FHEOffline/DataSetup.hpp"
|
||||
|
||||
template<class T>
|
||||
PairwiseMachine* CowGearPrep<T>::pairwise_machine = 0;
|
||||
@@ -39,8 +40,9 @@ void CowGearPrep<T>::basic_setup(Player& P)
|
||||
auto& setup = machine.setup<FD>();
|
||||
auto& options = CowGearOptions::singleton;
|
||||
#ifdef VERBOSE
|
||||
cerr << "Covert security parameter for key and MAC generation: "
|
||||
<< options.covert_security << endl;
|
||||
if (T::covert)
|
||||
cerr << "Covert security parameter for key and MAC generation: "
|
||||
<< options.covert_security << endl;
|
||||
cerr << "LowGear security parameter: " << options.lowgear_security << endl;
|
||||
#endif
|
||||
setup.secure_init(P, machine, T::clear::length(), options.lowgear_security);
|
||||
@@ -66,8 +68,8 @@ void CowGearPrep<T>::key_setup(Player& P, mac_key_type alphai)
|
||||
auto& machine = *pairwise_machine;
|
||||
auto& setup = machine.setup<FD>();
|
||||
auto& options = CowGearOptions::singleton;
|
||||
read_or_generate_covert_secrets(setup, P, machine,
|
||||
options.covert_security);
|
||||
read_or_generate_secrets(setup, P, machine,
|
||||
options.covert_security, T::covert);
|
||||
|
||||
// adjust mac key
|
||||
mac_key_type diff = alphai - setup.alphai;
|
||||
@@ -149,14 +151,22 @@ void CowGearPrep<T>::buffer_inputs(int player)
|
||||
|
||||
template<class T>
|
||||
inline void CowGearPrep<T>::buffer_bits()
|
||||
{
|
||||
buffer_bits<0>(T::clear::characteristic_two);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<int>
|
||||
void CowGearPrep<T>::buffer_bits(false_type)
|
||||
{
|
||||
buffer_bits_from_squares(*this);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void CowGearPrep<CowGearShare<gf2n_short>>::buffer_bits()
|
||||
template<class T>
|
||||
template<int>
|
||||
void CowGearPrep<T>::buffer_bits(true_type)
|
||||
{
|
||||
buffer_bits_without_check();
|
||||
this->buffer_bits_without_check();
|
||||
assert(not this->bits.empty());
|
||||
for (auto& bit : this->bits)
|
||||
bit.force_to_bit();
|
||||
|
||||
@@ -26,6 +26,8 @@ public:
|
||||
|
||||
const static bool needs_ot = false;
|
||||
|
||||
const static true_type covert;
|
||||
|
||||
CowGearShare()
|
||||
{
|
||||
}
|
||||
@@ -37,4 +39,7 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
const true_type CowGearShare<T>::covert;
|
||||
|
||||
#endif /* PROTOCOLS_COWGEARSHARE_H_ */
|
||||
|
||||
@@ -47,6 +47,11 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
FakeProtocol branch()
|
||||
{
|
||||
return P;
|
||||
}
|
||||
|
||||
void init_mul(SubProcessor<T>*)
|
||||
{
|
||||
results.clear();
|
||||
|
||||
@@ -68,8 +68,9 @@ public:
|
||||
*this = a - b;
|
||||
}
|
||||
|
||||
static void split(vector<bit_type>& dest, const vector<int>& regs, int n_bits,
|
||||
const This* source, int n_inputs, Player& P);
|
||||
static void split(vector<bit_type>& dest, const vector<int>& regs,
|
||||
int n_bits, const This* source, int n_inputs,
|
||||
GC::FakeSecret::Protocol& protocol);
|
||||
};
|
||||
|
||||
#endif /* PROTOCOLS_FAKESHARE_H_ */
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
template<class T>
|
||||
void FakeShare<T>::split(vector<bit_type>& dest,
|
||||
const vector<int>& regs, int n_bits, const This* source, int n_inputs,
|
||||
Player&)
|
||||
GC::FakeSecret::Protocol&)
|
||||
{
|
||||
assert(n_bits <= 64);
|
||||
int unit = GC::Clear::N_BITS;
|
||||
|
||||
39
Protocols/HighGearKeyGen.cpp
Normal file
39
Protocols/HighGearKeyGen.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* KeyGen.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FHEOffline/DataSetup.h"
|
||||
#include "Processor/OnlineOptions.h"
|
||||
|
||||
#include "Protocols/HighGearKeyGen.hpp"
|
||||
|
||||
template<>
|
||||
void PartSetup<FFT_Data>::key_and_mac_generation(Player& P,
|
||||
MachineBase& machine, int, false_type)
|
||||
{
|
||||
auto& batch_size = OnlineOptions::singleton.batch_size;
|
||||
auto backup = batch_size;
|
||||
batch_size = 100;
|
||||
bool done = false;
|
||||
int n_limbs[2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
n_limbs[i] = params.FFTD()[i].get_prD().get_t();
|
||||
#define X(L, M) \
|
||||
if (n_limbs[0] == L and n_limbs[1] == M) \
|
||||
{ \
|
||||
HighGearKeyGen<L, M>(P, params).run(*this, machine); \
|
||||
done = true; \
|
||||
}
|
||||
X(5, 3) X(4, 3) X(3, 2)
|
||||
if (not done)
|
||||
throw runtime_error("not compiled for choice of parameters");
|
||||
batch_size = backup;
|
||||
}
|
||||
|
||||
template<>
|
||||
void PartSetup<P2Data>::key_and_mac_generation(Player& P, MachineBase& machine,
|
||||
int, false_type)
|
||||
{
|
||||
HighGearKeyGen<2, 2>(P, params).run(*this, machine);
|
||||
}
|
||||
71
Protocols/HighGearKeyGen.h
Normal file
71
Protocols/HighGearKeyGen.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* HighGearKeyGen.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLS_HIGHGEARKEYGEN_H_
|
||||
#define PROTOCOLS_HIGHGEARKEYGEN_H_
|
||||
|
||||
#include "LowGearKeyGen.h"
|
||||
|
||||
#include <deque>
|
||||
using namespace std;
|
||||
|
||||
template<class T, class U>
|
||||
class KeyGenBitFactory
|
||||
{
|
||||
U& keygen;
|
||||
deque<T>& buffer;
|
||||
|
||||
public:
|
||||
KeyGenBitFactory(U& keygen, deque<T>& buffer) :
|
||||
keygen(keygen), buffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
T get_bit()
|
||||
{
|
||||
if (buffer.empty())
|
||||
keygen.buffer_mabits();
|
||||
auto res = buffer.front();
|
||||
buffer.pop_front();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<int L, int M>
|
||||
class HighGearKeyGen
|
||||
{
|
||||
public:
|
||||
typedef KeyGenProtocol<5, L> Proto0;
|
||||
typedef KeyGenProtocol<7, M> Proto1;
|
||||
|
||||
typedef typename Proto0::share_type share_type0;
|
||||
typedef typename Proto1::share_type share_type1;
|
||||
|
||||
typedef typename share_type0::open_type open_type0;
|
||||
typedef typename share_type1::open_type open_type1;
|
||||
|
||||
typedef ShareVector<share_type0> vector_type0;
|
||||
typedef ShareVector<share_type1> vector_type1;
|
||||
|
||||
typedef typename share_type0::bit_type BT;
|
||||
|
||||
Player& P;
|
||||
const FHE_Params& params;
|
||||
|
||||
Proto0 proto0;
|
||||
Proto1 proto1;
|
||||
|
||||
deque<share_type0> bits0;
|
||||
deque<share_type1> bits1;
|
||||
|
||||
HighGearKeyGen(Player& P, const FHE_Params& params);
|
||||
|
||||
void buffer_mabits();
|
||||
|
||||
template<class FD>
|
||||
void run(PartSetup<FD>& setup, MachineBase& machine);
|
||||
};
|
||||
|
||||
#endif /* PROTOCOLS_HIGHGEARKEYGEN_H_ */
|
||||
159
Protocols/HighGearKeyGen.hpp
Normal file
159
Protocols/HighGearKeyGen.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* HighGearKeyGen.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "HighGearKeyGen.h"
|
||||
#include "FHE/Rq_Element.h"
|
||||
|
||||
#include "LowGearKeyGen.hpp"
|
||||
|
||||
template<int L, int M>
|
||||
HighGearKeyGen<L, M>::HighGearKeyGen(Player& P, const FHE_Params& params) :
|
||||
P(P), params(params), proto0(P, params, 0), proto1(P, params, 1)
|
||||
{
|
||||
}
|
||||
|
||||
template<int L, int M>
|
||||
void HighGearKeyGen<L, M>::buffer_mabits()
|
||||
{
|
||||
vector<BT> diffs;
|
||||
vector<typename BT::open_type> open_diffs;
|
||||
vector<share_type0> my_bits0;
|
||||
vector<share_type1> my_bits1;
|
||||
int batch_size = 1000;
|
||||
auto& bmc = *GC::ShareThread<BT>::s().MC;
|
||||
for (int i = 0; i < batch_size; i++)
|
||||
{
|
||||
share_type0 a0;
|
||||
share_type1 a1;
|
||||
BT b0, b1;
|
||||
proto0.prep->get_dabit(a0, b0);
|
||||
proto1.prep->get_dabit(a1, b1);
|
||||
my_bits0.push_back(a0);
|
||||
my_bits1.push_back(a1);
|
||||
diffs.push_back(b0 + b1);
|
||||
}
|
||||
bmc.POpen(open_diffs, diffs, P);
|
||||
bmc.Check(P);
|
||||
for (int i = 0; i < batch_size; i++)
|
||||
{
|
||||
bits0.push_back(my_bits0[i]);
|
||||
bits1.push_back(
|
||||
my_bits1[i]
|
||||
+ share_type1::constant(open_diffs.at(i), P.my_num(),
|
||||
proto1.MC->get_alphai())
|
||||
- my_bits1[i] * open_diffs.at(i) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
template<int L, int M>
|
||||
template<class FD>
|
||||
void HighGearKeyGen<L, M>::run(PartSetup<FD>& setup, MachineBase& machine)
|
||||
{
|
||||
RunningTimer timer;
|
||||
|
||||
GlobalPRNG global_prng(P);
|
||||
auto& fftd = params.FFTD();
|
||||
|
||||
AddableVector<open_type0> a0(params.phi_m()), a0_prime(params.phi_m());
|
||||
AddableVector<open_type1> a1(params.phi_m()), a1_prime(params.phi_m());
|
||||
a0.randomize(global_prng);
|
||||
a1.randomize(global_prng);
|
||||
a0_prime.randomize(global_prng);
|
||||
a1_prime.randomize(global_prng);
|
||||
|
||||
KeyGenBitFactory<share_type0, HighGearKeyGen<L, M>> factory0(*this, bits0);
|
||||
KeyGenBitFactory<share_type1, HighGearKeyGen<L, M>> factory1(*this, bits1);
|
||||
|
||||
vector_type0 sk0;
|
||||
vector_type1 sk1;
|
||||
proto0.secret_key(sk0, factory0);
|
||||
proto1.secret_key(sk1, factory1);
|
||||
|
||||
vector_type0 e0, e0_prime;
|
||||
vector_type1 e1, e1_prime;
|
||||
proto0.binomial(e0, factory0);
|
||||
proto0.binomial(e0_prime, factory0);
|
||||
proto1.binomial(e1, factory1);
|
||||
proto1.binomial(e1_prime, factory1);
|
||||
|
||||
auto f0 = sk0;
|
||||
auto f0_prime = proto0.schur_product(f0, f0);
|
||||
|
||||
Rq_Element a(Ring_Element(fftd[0], evaluation, a0),
|
||||
Ring_Element(fftd[1], evaluation, a1));
|
||||
Rq_Element Sw_a(Ring_Element(fftd[0], evaluation, a0_prime),
|
||||
Ring_Element(fftd[1], evaluation, a1_prime));
|
||||
|
||||
bigint p = setup.FieldD.get_prime();
|
||||
bigint p1 = fftd[1].get_prime();
|
||||
vector<open_type0> b0, b0_prime;
|
||||
vector<open_type1> b1, b1_prime;
|
||||
proto0.MC->POpen(b0, sk0 * a0 + e0 * p, P);
|
||||
proto1.MC->POpen(b1, sk1 * a1 + e1 * p, P);
|
||||
proto0.MC->POpen(b0_prime, sk0 * a0_prime + e0_prime * p - f0_prime * p1, P);
|
||||
proto1.MC->POpen(b1_prime, sk1 * a1_prime + e1_prime * p, P);
|
||||
|
||||
Rq_Element b(Ring_Element(fftd[0], evaluation, b0),
|
||||
Ring_Element(fftd[1], evaluation, b1));
|
||||
Rq_Element Sw_b(Ring_Element(fftd[0], evaluation, b0_prime),
|
||||
Ring_Element(fftd[1], evaluation, b1_prime));
|
||||
|
||||
setup.pk.assign(a, b, Sw_a, Sw_b);
|
||||
|
||||
vector<open_type0> s0_shares;
|
||||
vector<open_type1> s1_shares;
|
||||
for (int i = 0; i < params.phi_m(); i++)
|
||||
{
|
||||
s0_shares.push_back(sk0.at(i).get_share());
|
||||
s1_shares.push_back(sk1.at(i).get_share());
|
||||
}
|
||||
setup.sk.assign({Ring_Element(fftd[0], evaluation, s0_shares),
|
||||
Ring_Element(fftd[1], evaluation, s1_shares)});
|
||||
|
||||
GC::ShareThread<BT>::s().MC->Check(P);
|
||||
|
||||
#ifdef DEBUG_HIGHGEAR_KEYGEN
|
||||
proto0.MC->POpen(s0_shares, sk0, P);
|
||||
proto1.MC->POpen(s1_shares, sk1, P);
|
||||
|
||||
vector<open_type0> e0_open, e0_prime_open;
|
||||
vector<open_type1> e1_open, e1_prime_open;
|
||||
proto0.MC->POpen(e0_open, e0, P);
|
||||
proto0.MC->POpen(e0_prime_open, e0_prime, P);
|
||||
proto1.MC->POpen(e1_open, e1, P);
|
||||
proto1.MC->POpen(e1_prime_open, e1_prime, P);
|
||||
|
||||
Rq_Element s(fftd, s0_shares, s1_shares);
|
||||
Rq_Element e(fftd, e0_open, e1_open);
|
||||
assert(b == s * a + e * p);
|
||||
|
||||
Rq_Element e_prime(fftd, e0_prime_open, e1_prime_open);
|
||||
assert(Sw_b == s * Sw_a + e_prime * p - s * s * p1);
|
||||
|
||||
cerr << "Revealed secret key for check" << endl;
|
||||
#endif
|
||||
|
||||
cerr << "Key generation took " << timer.elapsed() << " seconds" << endl;
|
||||
timer.reset();
|
||||
|
||||
map<string, Timer> timers;
|
||||
SimpleEncCommit_<FD> EC(P, setup.pk, setup.FieldD, timers, machine, 0, true);
|
||||
Plaintext_<FD> alpha(setup.FieldD);
|
||||
EC.next(alpha, setup.calpha);
|
||||
assert(alpha.is_diagonal());
|
||||
|
||||
setup.alphai = alpha.element(0);
|
||||
|
||||
cerr << "MAC key generation took " << timer.elapsed() << " seconds" << endl;
|
||||
|
||||
#ifdef DEBUG_HIGHGEAR_KEYGEN
|
||||
auto d = SemiMC<BasicSemiShare<FHE_SK>>().open(setup.sk, P).decrypt(
|
||||
setup.calpha, setup.FieldD);
|
||||
auto dd = SemiMC<SemiShare<typename FD::T>>().open(setup.alphai, P);
|
||||
for (unsigned i = 0; i < d.num_slots(); i++)
|
||||
assert(d.element(i) == dd);
|
||||
cerr << "Revealed MAC key for check" << endl;
|
||||
#endif
|
||||
}
|
||||
41
Protocols/HighGearShare.h
Normal file
41
Protocols/HighGearShare.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* HighGearShare.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLS_HIGHGEARSHARE_H_
|
||||
#define PROTOCOLS_HIGHGEARSHARE_H_
|
||||
|
||||
#include "ChaiGearShare.h"
|
||||
|
||||
template<class T>
|
||||
class HighGearShare : public ChaiGearShare<T>
|
||||
{
|
||||
typedef HighGearShare This;
|
||||
typedef ChaiGearShare<T> super;
|
||||
|
||||
public:
|
||||
typedef MAC_Check_<This> MAC_Check;
|
||||
typedef Direct_MAC_Check<This> Direct_MC;
|
||||
typedef ::Input<This> Input;
|
||||
typedef ::PrivateOutput<This> PrivateOutput;
|
||||
typedef SPDZ<This> Protocol;
|
||||
typedef ChaiGearPrep<This> LivePrep;
|
||||
|
||||
const static false_type covert;
|
||||
|
||||
HighGearShare()
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
HighGearShare(const U& other) :
|
||||
super(other)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
const false_type HighGearShare<T>::covert;
|
||||
|
||||
#endif /* PROTOCOLS_HIGHGEARSHARE_H_ */
|
||||
34
Protocols/LowGearKeyGen.cpp
Normal file
34
Protocols/LowGearKeyGen.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* LowGearKeyGen.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FHEOffline/DataSetup.h"
|
||||
#include "Processor/OnlineOptions.h"
|
||||
|
||||
#include "Protocols/LowGearKeyGen.hpp"
|
||||
|
||||
template<>
|
||||
void PairwiseSetup<FFT_Data>::key_and_mac_generation(Player& P,
|
||||
PairwiseMachine& machine, int, false_type)
|
||||
{
|
||||
int n_limbs = params.FFTD()[0].get_prD().get_t();
|
||||
switch (n_limbs)
|
||||
{
|
||||
#define X(L) case L: LowGearKeyGen<L>(P, machine, params).run(*this); break;
|
||||
X(3) X(4) X(5) X(6)
|
||||
#undef X
|
||||
default:
|
||||
throw runtime_error(
|
||||
"not compiled for choice of parameters, add X("
|
||||
+ to_string(n_limbs) + ") at " + __FILE__ + ":"
|
||||
+ to_string(__LINE__ - 5));
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void PairwiseSetup<P2Data>::key_and_mac_generation(Player& P,
|
||||
PairwiseMachine& machine, int, false_type)
|
||||
{
|
||||
LowGearKeyGen<2>(P, machine, params).run(*this);
|
||||
}
|
||||
78
Protocols/LowGearKeyGen.h
Normal file
78
Protocols/LowGearKeyGen.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* LowGearKeyGen.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLS_LOWGEARKEYGEN_H_
|
||||
#define PROTOCOLS_LOWGEARKEYGEN_H_
|
||||
|
||||
#include "ShareVector.h"
|
||||
#include "FHEOffline/PairwiseMachine.h"
|
||||
#include "Protocols/MascotPrep.h"
|
||||
#include "Processor/Processor.h"
|
||||
#include "GC/TinierSecret.h"
|
||||
#include "Math/gfp.h"
|
||||
|
||||
template<int X, int L>
|
||||
class KeyGenProtocol
|
||||
{
|
||||
public:
|
||||
typedef Share<gfp_<X, L>> share_type;
|
||||
typedef typename share_type::open_type open_type;
|
||||
typedef ShareVector<share_type> vector_type;
|
||||
|
||||
protected:
|
||||
Player& P;
|
||||
const FHE_Params& params;
|
||||
const FFT_Data& fftd;
|
||||
|
||||
SeededPRNG G;
|
||||
DataPositions usage;
|
||||
|
||||
share_type get_bit()
|
||||
{
|
||||
return prep->get_bit();
|
||||
}
|
||||
|
||||
public:
|
||||
Preprocessing<share_type>* prep;
|
||||
MAC_Check_<share_type>* MC;
|
||||
SubProcessor<share_type>* proc;
|
||||
|
||||
KeyGenProtocol(Player& P, const FHE_Params& params, int level = 0);
|
||||
~KeyGenProtocol();
|
||||
|
||||
void input(vector<vector_type>& shares, const Rq_Element& secret);
|
||||
template<class T>
|
||||
void binomial(vector_type& shares, T& prep);
|
||||
template<class T>
|
||||
void hamming(vector_type& shares, T& prep);
|
||||
template<class T>
|
||||
void secret_key(vector_type& shares, T& prep);
|
||||
vector_type schur_product(const vector_type& x, const vector_type& y);
|
||||
void output_to(int player, vector<open_type>& opened,
|
||||
vector<share_type>& shares);
|
||||
};
|
||||
|
||||
template<int L>
|
||||
class LowGearKeyGen : public KeyGenProtocol<5, L>
|
||||
{
|
||||
typedef KeyGenProtocol<5, L> super;
|
||||
|
||||
typedef typename super::share_type share_type;
|
||||
typedef typename super::open_type open_type;
|
||||
typedef typename super::vector_type vector_type;
|
||||
|
||||
Player& P;
|
||||
PairwiseMachine& machine;
|
||||
|
||||
void generate_keys(FHE_Params& params);
|
||||
|
||||
public:
|
||||
LowGearKeyGen(Player& P, PairwiseMachine& machine, FHE_Params& params);
|
||||
|
||||
template<class FD>
|
||||
void run(PairwiseSetup<FD>& setup);
|
||||
};
|
||||
|
||||
#endif /* PROTOCOLS_LOWGEARKEYGEN_H_ */
|
||||
284
Protocols/LowGearKeyGen.hpp
Normal file
284
Protocols/LowGearKeyGen.hpp
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* LowGearKeyGen.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LowGearKeyGen.h"
|
||||
#include "FHE/Rq_Element.h"
|
||||
|
||||
#include "Tools/benchmarking.h"
|
||||
|
||||
#include "Machines/SPDZ.hpp"
|
||||
#include "ShareVector.hpp"
|
||||
|
||||
template<int L>
|
||||
LowGearKeyGen<L>::LowGearKeyGen(Player& P, PairwiseMachine& machine,
|
||||
FHE_Params& params) :
|
||||
KeyGenProtocol<5, L>(P, params), P(P), machine(machine)
|
||||
{
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
KeyGenProtocol<X, L>::KeyGenProtocol(Player& P, const FHE_Params& params,
|
||||
int level) :
|
||||
P(P), params(params), fftd(params.FFTD().at(level)), usage(P)
|
||||
{
|
||||
open_type::init_field(params.FFTD().at(level).get_prD().pr);
|
||||
typename share_type::mac_key_type alphai;
|
||||
|
||||
if (OnlineOptions::singleton.live_prep)
|
||||
{
|
||||
prep = new MascotDabitOnlyPrep<share_type>(0, usage);
|
||||
alphai.randomize(G);
|
||||
}
|
||||
else
|
||||
{
|
||||
prep = new Sub_Data_Files<share_type>(P.N,
|
||||
get_prep_sub_dir<share_type>(P.num_players()), usage);
|
||||
read_mac_key(get_prep_sub_dir<share_type>(P.num_players()), P.N, alphai);
|
||||
}
|
||||
|
||||
MC = new MAC_Check_<share_type>(alphai);
|
||||
proc = new SubProcessor<share_type>(*MC, *prep, P);
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
KeyGenProtocol<X, L>::~KeyGenProtocol()
|
||||
{
|
||||
MC->Check(P);
|
||||
|
||||
usage.print_cost();
|
||||
|
||||
delete proc;
|
||||
delete prep;
|
||||
delete MC;
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
void KeyGenProtocol<X, L>::input(vector<vector_type>& shares, const Rq_Element& secret)
|
||||
{
|
||||
assert(secret.level() == 0);
|
||||
auto s = secret.get(0);
|
||||
s.change_rep(evaluation);
|
||||
auto& FFTD = s.get_FFTD();
|
||||
auto& inputter = this->proc->input;
|
||||
inputter.reset_all(P);
|
||||
for (int i = 0; i < FFTD.num_slots(); i++)
|
||||
inputter.add_from_all(s.get_element(i));
|
||||
inputter.exchange();
|
||||
shares.clear();
|
||||
shares.resize(P.num_players());
|
||||
for (int i = 0; i < FFTD.num_slots(); i++)
|
||||
for (int j = 0; j < P.num_players(); j++)
|
||||
shares[j].push_back(inputter.finalize(j));
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
template<class T>
|
||||
void KeyGenProtocol<X, L>::binomial(vector_type& shares, T& prep)
|
||||
{
|
||||
shares.resize(params.phi_m());
|
||||
RunningTimer timer, total;
|
||||
for (int i = 0; i < params.phi_m(); i++)
|
||||
{
|
||||
#ifdef VERBOSE
|
||||
if (timer.elapsed() > 10)
|
||||
{
|
||||
cerr << i << "/" << params.phi_m() << ", throughput " <<
|
||||
i / total.elapsed() << endl;
|
||||
timer.reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& share = shares[i];
|
||||
share = {};
|
||||
for (int i = 0; i < params.get_DG().get_NewHopeB(); i++)
|
||||
{
|
||||
share += prep.get_bit();
|
||||
share -= prep.get_bit();
|
||||
}
|
||||
}
|
||||
shares.fft(fftd);
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
template<class T>
|
||||
void KeyGenProtocol<X, L>::hamming(vector_type& shares, T& prep)
|
||||
{
|
||||
shares.resize(params.phi_m());
|
||||
int h = params.get_h();
|
||||
assert(h > 0);
|
||||
assert(shares.size() / h * h == shares.size());
|
||||
int n_bits = log(shares.size() / h) / log(2);
|
||||
// assert(size_t(h << n_bits) == shares.size());
|
||||
|
||||
for (auto& share : shares)
|
||||
share = prep.get_bit();
|
||||
|
||||
auto& protocol = proc->protocol;
|
||||
for (int i = 0; i < n_bits - 1; i++)
|
||||
{
|
||||
protocol.init_mul(proc);
|
||||
for (auto& share : shares)
|
||||
protocol.prepare_mul(share, prep.get_bit());
|
||||
protocol.exchange();
|
||||
for (auto& share : shares)
|
||||
share = protocol.finalize_mul();
|
||||
}
|
||||
|
||||
protocol.init_mul(proc);
|
||||
auto one = share_type::constant(1, P.my_num(), MC->get_alphai());
|
||||
for (auto& share : shares)
|
||||
protocol.prepare_mul(share, prep.get_bit() * 2 - one);
|
||||
protocol.exchange();
|
||||
for (auto& share : shares)
|
||||
share = protocol.finalize_mul();
|
||||
|
||||
shares.fft(fftd);
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
template<class T>
|
||||
void KeyGenProtocol<X, L>::secret_key(vector_type& shares, T& prep)
|
||||
{
|
||||
assert(params.get_h() != 0);
|
||||
cerr << "Generate secret key by ";
|
||||
if (params.get_h() > 0)
|
||||
{
|
||||
cerr << "Hamming weight" << endl;
|
||||
hamming(shares, prep);
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "binomial" << endl;
|
||||
binomial(shares, prep);
|
||||
}
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
typename KeyGenProtocol<X, L>::vector_type KeyGenProtocol<X, L>::schur_product(
|
||||
const vector_type& x, const vector_type& y)
|
||||
{
|
||||
vector_type res;
|
||||
assert(x.size() == y.size());
|
||||
auto& protocol = proc->protocol;
|
||||
protocol.init_mul(proc);
|
||||
for (size_t i = 0; i < x.size(); i++)
|
||||
protocol.prepare_mul(x[i], y[i]);
|
||||
protocol.exchange();
|
||||
for (size_t i = 0; i < x.size(); i++)
|
||||
res.push_back(protocol.finalize_mul());
|
||||
return res;
|
||||
}
|
||||
|
||||
template<int X, int L>
|
||||
void KeyGenProtocol<X, L>::output_to(int player, vector<open_type>& opened,
|
||||
vector<share_type>& shares)
|
||||
{
|
||||
PrivateOutput<share_type> po(*proc);
|
||||
vector<share_type> masked;
|
||||
for (auto& share : shares)
|
||||
masked.push_back(po.start(player, share));
|
||||
MC->POpen(opened, masked, P);
|
||||
for (auto& x : opened)
|
||||
x = po.stop(player, x);
|
||||
}
|
||||
|
||||
template<int L>
|
||||
void LowGearKeyGen<L>::generate_keys(FHE_Params& params)
|
||||
{
|
||||
RunningTimer timer;
|
||||
auto& pk = machine.pk;
|
||||
|
||||
GlobalPRNG global_prng(P);
|
||||
auto& FFTD = pk.get_params().FFTD()[0];
|
||||
|
||||
for (int i = 0; i < P.num_players(); i++)
|
||||
{
|
||||
vector_type sk;
|
||||
this->secret_key(sk, *this);
|
||||
vector<open_type> open_sk;
|
||||
this->output_to(i, open_sk, sk);
|
||||
if (P.my_num() == i)
|
||||
machine.sk.assign(Ring_Element(FFTD, evaluation, open_sk));
|
||||
vector_type e0;
|
||||
this->binomial(e0, *this);
|
||||
AddableVector<open_type> a0(pk.get_params().phi_m());
|
||||
a0.randomize(global_prng);
|
||||
vector<open_type> b0;
|
||||
assert(machine.sk.p() != 0);
|
||||
this->MC->POpen(b0, sk * a0 + e0 * machine.sk.p(), P);
|
||||
machine.other_pks[i] = FHE_PK(params, machine.sk.p());
|
||||
machine.other_pks[i].assign(Ring_Element(FFTD, evaluation, a0),
|
||||
Ring_Element(FFTD, evaluation, b0));
|
||||
}
|
||||
|
||||
this->MC->Check(P);
|
||||
|
||||
cerr << "Key generation took " << timer.elapsed() << " seconds" << endl;
|
||||
}
|
||||
|
||||
template<int L>
|
||||
template<class FD>
|
||||
void LowGearKeyGen<L>::run(PairwiseSetup<FD>& setup)
|
||||
{
|
||||
generate_keys(setup.params);
|
||||
machine.sk.check(machine.pk, setup.FieldD);
|
||||
|
||||
RunningTimer timer;
|
||||
|
||||
auto mac_key = SeededPRNG().get<typename FD::T>();
|
||||
|
||||
PairwiseGenerator<FD> generator(0, machine, &P);
|
||||
map<string, Timer> timers;
|
||||
MultiEncCommit<FD> EC(P, machine.other_pks, setup.FieldD,
|
||||
timers, machine, generator, true);
|
||||
assert(EC.proof.get_diagonal());
|
||||
vector<Plaintext_<FD>> m(EC.proof.U, setup.FieldD);
|
||||
for (auto& mm : m)
|
||||
mm.assign_constant(mac_key);
|
||||
|
||||
AddableVector<Ciphertext> C;
|
||||
octetStream ciphertexts, cleartexts;
|
||||
EC.generate_proof(C, m, ciphertexts, cleartexts);
|
||||
|
||||
AddableVector<Ciphertext> others_ciphertexts;
|
||||
others_ciphertexts.resize(EC.proof.U, machine.pk.get_params());
|
||||
Verifier<FD> verifier(EC.proof, setup.FieldD);
|
||||
verifier.NIZKPoK(others_ciphertexts, ciphertexts,
|
||||
cleartexts, machine.pk, false);
|
||||
|
||||
machine.enc_alphas.clear();
|
||||
for (int i = 0; i < P.num_players(); i++)
|
||||
machine.enc_alphas.push_back(machine.other_pks[i]);
|
||||
|
||||
for (int i = 1; i < P.num_players(); i++)
|
||||
{
|
||||
int player = P.get_player(-i);
|
||||
#ifdef VERBOSE_HE
|
||||
cerr << "Sending proof with " << 1e-9 * ciphertexts.get_length() << "+"
|
||||
<< 1e-9 * cleartexts.get_length() << " GB" << endl;
|
||||
#endif
|
||||
timers["Sending"].start();
|
||||
P.pass_around(ciphertexts);
|
||||
P.pass_around(cleartexts);
|
||||
timers["Sending"].stop();
|
||||
#ifdef VERBOSE_HE
|
||||
cerr << "Checking proof of player " << i << endl;
|
||||
#endif
|
||||
timers["Verifying"].start();
|
||||
verifier.NIZKPoK(others_ciphertexts, ciphertexts,
|
||||
cleartexts, machine.other_pks[player], false);
|
||||
timers["Verifying"].stop();
|
||||
machine.enc_alphas.at(player) = others_ciphertexts.at(0);
|
||||
}
|
||||
|
||||
setup.set_alphai(mac_key);
|
||||
machine.enc_alphas.at(P.my_num()) = C.at(0);
|
||||
|
||||
auto test = machine.sk.decrypt(C[0], setup.FieldD);
|
||||
for (int i = 0; i < setup.FieldD.num_slots(); i++)
|
||||
assert(test.element(i) == mac_key);
|
||||
|
||||
cerr << "MAC key generation took " << timer.elapsed() << " seconds" << endl;
|
||||
}
|
||||
41
Protocols/LowGearShare.h
Normal file
41
Protocols/LowGearShare.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* LowGearShare.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLS_LOWGEARSHARE_H_
|
||||
#define PROTOCOLS_LOWGEARSHARE_H_
|
||||
|
||||
#include "CowGearShare.h"
|
||||
|
||||
template<class T>
|
||||
class LowGearShare : public CowGearShare<T>
|
||||
{
|
||||
typedef LowGearShare This;
|
||||
typedef CowGearShare<T> super;
|
||||
|
||||
public:
|
||||
typedef MAC_Check_<This> MAC_Check;
|
||||
typedef Direct_MAC_Check<This> Direct_MC;
|
||||
typedef ::Input<This> Input;
|
||||
typedef ::PrivateOutput<This> PrivateOutput;
|
||||
typedef SPDZ<This> Protocol;
|
||||
typedef CowGearPrep<This> LivePrep;
|
||||
|
||||
const static false_type covert;
|
||||
|
||||
LowGearShare()
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
LowGearShare(const U& other) :
|
||||
super(other)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
const false_type LowGearShare<T>::covert;
|
||||
|
||||
#endif /* PROTOCOLS_LOWGEARSHARE_H_ */
|
||||
@@ -40,6 +40,7 @@ MalRepRingPrepWithBits<T>::MalRepRingPrepWithBits(SubProcessor<T>* proc,
|
||||
DataPositions& usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage), MalRepRingPrep<T>(proc, usage),
|
||||
RingOnlyBitsFromSquaresPrep<T>(proc, usage),
|
||||
SimplerMalRepRingPrep<T>(proc, usage)
|
||||
|
||||
@@ -32,6 +32,7 @@ MaliciousRepPrepWithBits<T>::MaliciousRepPrepWithBits(SubProcessor<T>* proc,
|
||||
DataPositions& usage) :
|
||||
BufferPrep<T>(usage), MaliciousRepPrep<T>(proc, usage),
|
||||
BitPrep<T>(proc, usage), RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
@@ -173,6 +174,7 @@ void MaliciousBitOnlyRepPrep<T>::buffer_bits()
|
||||
auto buffer_size = this->buffer_size;
|
||||
assert(honest_proc);
|
||||
Player& P = honest_proc->P;
|
||||
honest_prep.buffer_size = buffer_size;
|
||||
bits.clear();
|
||||
for (int i = 0; i < buffer_size; i++)
|
||||
{
|
||||
|
||||
@@ -12,21 +12,21 @@
|
||||
#include "Spdz2kPrep.hpp"
|
||||
|
||||
template<class T>
|
||||
void MaliciousRingPrep<T>::buffer_dabits(ThreadQueues* queues)
|
||||
void MaliciousDabitOnlyPrep<T>::buffer_dabits(ThreadQueues* queues)
|
||||
{
|
||||
buffer_dabits<0>(queues, T::clear::characteristic_two);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<int>
|
||||
void MaliciousRingPrep<T>::buffer_dabits(ThreadQueues*, true_type)
|
||||
void MaliciousDabitOnlyPrep<T>::buffer_dabits(ThreadQueues*, true_type)
|
||||
{
|
||||
throw runtime_error("only implemented for integer-like domains");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<int>
|
||||
void MaliciousRingPrep<T>::buffer_dabits(ThreadQueues* queues, false_type)
|
||||
void MaliciousDabitOnlyPrep<T>::buffer_dabits(ThreadQueues* queues, false_type)
|
||||
{
|
||||
assert(this->proc != 0);
|
||||
vector<dabit<T>> check_dabits;
|
||||
|
||||
@@ -24,7 +24,8 @@ void MaliciousShamirMC<T>::init_open(const Player& P, int n)
|
||||
reconstructions[i].resize(i);
|
||||
for (int j = 0; j < i; j++)
|
||||
reconstructions[i][j] =
|
||||
Shamir<T>::get_rec_factor(j, i);
|
||||
Shamir<T>::get_rec_factor(P.get_player(j),
|
||||
P.num_players(), P.my_num(), i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ typename T::open_type MaliciousShamirMC<T>::finalize_open()
|
||||
int threshold = ShamirMachine::s().threshold;
|
||||
shares.resize(2 * threshold + 1);
|
||||
for (size_t j = 0; j < shares.size(); j++)
|
||||
shares[j].unpack((*this->os)[j]);
|
||||
shares[j].unpack((*this->os)[this->player->get_player(j)]);
|
||||
return reconstruct(shares);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ template<class T>
|
||||
MaliciousShamirPO<T>::MaliciousShamirPO(Player& P) :
|
||||
P(P), shares(P.num_players())
|
||||
{
|
||||
MC.init_open(P);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
template<class T>
|
||||
MamaPrep<T>::MamaPrep(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage), OTPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
OTPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage)
|
||||
{
|
||||
this->params.amplify = true;
|
||||
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
typedef MascotMultiplier<This> Multiplier;
|
||||
typedef FixedVec<T, N> sacri_type;
|
||||
typedef This input_type;
|
||||
typedef This input_check_type;
|
||||
typedef MamaRectangle<T, N> Square;
|
||||
typedef typename T::Square Rectangle;
|
||||
|
||||
@@ -95,6 +96,12 @@ public:
|
||||
super(other.get_share(), other.get_mac())
|
||||
{
|
||||
}
|
||||
|
||||
template<class U, class V>
|
||||
MamaShare(const U& share, const V& mac) :
|
||||
super(share, mac)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* PROTOCOLS_MAMASHARE_H_ */
|
||||
|
||||
@@ -27,50 +27,88 @@ public:
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class MascotTriplePrep : public OTPrep<T>
|
||||
class MascotInputPrep : public OTPrep<T>
|
||||
{
|
||||
void buffer_inputs(int player);
|
||||
|
||||
public:
|
||||
MascotTriplePrep(SubProcessor<T> *proc, DataPositions &usage) :
|
||||
MascotInputPrep(SubProcessor<T> *proc, DataPositions &usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
OTPrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
|
||||
void buffer_triples();
|
||||
void buffer_inputs(int player);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class MascotPrep: public virtual MaliciousRingPrep<T>,
|
||||
class MascotTriplePrep : public MascotInputPrep<T>
|
||||
{
|
||||
public:
|
||||
MascotTriplePrep(SubProcessor<T> *proc, DataPositions &usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
MascotInputPrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
|
||||
void buffer_triples();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class MascotDabitOnlyPrep : public virtual MaliciousDabitOnlyPrep<T>,
|
||||
public virtual MascotTriplePrep<T>
|
||||
{
|
||||
public:
|
||||
MascotDabitOnlyPrep(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MascotTriplePrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
virtual ~MascotDabitOnlyPrep()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void buffer_bits();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class MascotPrep : public virtual MaliciousRingPrep<T>,
|
||||
public virtual MascotDabitOnlyPrep<T>
|
||||
{
|
||||
public:
|
||||
MascotPrep(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage), BitPrep<T>(proc, usage),
|
||||
RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage),
|
||||
MascotTriplePrep<T>(proc, usage)
|
||||
MascotTriplePrep<T>(proc, usage),
|
||||
MascotDabitOnlyPrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
virtual ~MascotPrep()
|
||||
{
|
||||
}
|
||||
|
||||
void buffer_bits() { throw runtime_error("use subclass"); }
|
||||
virtual void buffer_bits()
|
||||
{
|
||||
MascotDabitOnlyPrep<T>::buffer_bits();
|
||||
}
|
||||
|
||||
void buffer_edabits(bool strict, int n_bits, ThreadQueues* queues);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class MascotFieldPrep : public MascotPrep<T>
|
||||
class MascotFieldPrep : public virtual MascotPrep<T>
|
||||
{
|
||||
void buffer_bits();
|
||||
|
||||
public:
|
||||
MascotFieldPrep<T>(SubProcessor<T>* proc, DataPositions& usage) :
|
||||
BufferPrep<T>(usage),
|
||||
BitPrep<T>(proc, usage), RingPrep<T>(proc, usage),
|
||||
MaliciousDabitOnlyPrep<T>(proc, usage),
|
||||
MaliciousRingPrep<T>(proc, usage),
|
||||
MascotTriplePrep<T>(proc, usage), MascotPrep<T>(proc, usage)
|
||||
MascotTriplePrep<T>(proc, usage),
|
||||
MascotDabitOnlyPrep<T>(proc, usage),
|
||||
MascotPrep<T>(proc, usage)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,6 +36,10 @@ void OTPrep<T>::set_protocol(typename T::Protocol& protocol)
|
||||
BitPrep<T>::set_protocol(protocol);
|
||||
SubProcessor<T>* proc = this->proc;
|
||||
assert(proc != 0);
|
||||
|
||||
// make sure not to use Montgomery multiplication
|
||||
T::open_type::next::template init<typename T::open_type>(false);
|
||||
|
||||
triple_generator = new typename T::TripleGenerator(
|
||||
BaseMachine::s().fresh_ot_setup(),
|
||||
proc->P.N, -1,
|
||||
@@ -66,7 +70,7 @@ void MascotTriplePrep<T>::buffer_triples()
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void MascotFieldPrep<T>::buffer_bits()
|
||||
void MascotDabitOnlyPrep<T>::buffer_bits()
|
||||
{
|
||||
this->params.generateBits = true;
|
||||
auto& triple_generator = this->triple_generator;
|
||||
@@ -78,7 +82,7 @@ void MascotFieldPrep<T>::buffer_bits()
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void MascotTriplePrep<T>::buffer_inputs(int player)
|
||||
void MascotInputPrep<T>::buffer_inputs(int player)
|
||||
{
|
||||
auto& triple_generator = this->triple_generator;
|
||||
assert(triple_generator);
|
||||
|
||||
@@ -56,13 +56,14 @@ public:
|
||||
}
|
||||
|
||||
template<class U>
|
||||
static void split(vector<U>& dest, const vector<int>& regs,
|
||||
int n_bits, const super* source, int n_inputs, Player& P)
|
||||
static void split(vector<U>& dest, const vector<int>& regs, int n_bits,
|
||||
const super* source, int n_inputs,
|
||||
typename bit_type::Protocol& protocol)
|
||||
{
|
||||
if (regs.size() / n_bits != 3)
|
||||
throw runtime_error("only secure with three-way split");
|
||||
|
||||
super::split(dest, regs, n_bits, source, n_inputs, P);
|
||||
super::split(dest, regs, n_bits, source, n_inputs, protocol);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
PostSacrifice(Player& P);
|
||||
~PostSacrifice();
|
||||
|
||||
Player& branch();
|
||||
|
||||
void init_mul(SubProcessor<T>* proc);
|
||||
typename T::clear prepare_mul(const T& x, const T& y, int n = -1);
|
||||
void exchange() { internal.exchange(); }
|
||||
|
||||
@@ -18,6 +18,12 @@ PostSacrifice<T>::~PostSacrifice()
|
||||
check();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Player& PostSacrifice<T>::branch()
|
||||
{
|
||||
return P;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PostSacrifice<T>::init_mul(SubProcessor<T>* proc)
|
||||
{
|
||||
|
||||
@@ -41,9 +41,11 @@ public:
|
||||
}
|
||||
|
||||
template<class U>
|
||||
static void split(vector<U>& dest, const vector<int>& regs,
|
||||
int n_bits, const Rep3Share2* source, int n_inputs, Player& P)
|
||||
static void split(vector<U>& dest, const vector<int>& regs, int n_bits,
|
||||
const Rep3Share2* source, int n_inputs,
|
||||
typename U::Protocol& protocol)
|
||||
{
|
||||
auto& P = protocol.P;
|
||||
int my_num = P.my_num();
|
||||
assert(n_bits <= 64);
|
||||
int unit = GC::Clear::N_BITS;
|
||||
|
||||
@@ -14,6 +14,7 @@ class Rep4 : public ProtocolBase<T>
|
||||
friend class Rep4RingPrep<T>;
|
||||
|
||||
typedef typename T::open_type open_type;
|
||||
typedef array<ElementPRNG<typename T::open_type>, 3> prngs_type;
|
||||
|
||||
octetStreams send_os;
|
||||
octetStreams receive_os;
|
||||
@@ -21,6 +22,7 @@ class Rep4 : public ProtocolBase<T>
|
||||
array<array<Hash, 4>, 4> send_hashes, receive_hashes;
|
||||
|
||||
array<vector<open_type>, 5> add_shares;
|
||||
array<open_type, 5> dotprod_shares;
|
||||
vector<int> bit_lengths;
|
||||
|
||||
class ResTuple
|
||||
@@ -56,10 +58,14 @@ class Rep4 : public ProtocolBase<T>
|
||||
false_type);
|
||||
|
||||
public:
|
||||
array<ElementPRNG<typename T::open_type>, 3> rep_prngs;
|
||||
prngs_type rep_prngs;
|
||||
Player& P;
|
||||
|
||||
Rep4(Player& P);
|
||||
Rep4(Player& P, prngs_type& prngs);
|
||||
~Rep4();
|
||||
|
||||
Rep4 branch();
|
||||
|
||||
void init_mul(SubProcessor<T>* proc = 0);
|
||||
void init_mul(Preprocessing<T>& prep, typename T::MAC_Check& MC);
|
||||
@@ -78,6 +84,10 @@ public:
|
||||
|
||||
void trunc_pr(const vector<int>& regs, int size, SubProcessor<T>& proc);
|
||||
|
||||
template<class U>
|
||||
void split(vector<T>& dest, const vector<int>& regs, int n_bits,
|
||||
const U* source, int n_inputs);
|
||||
|
||||
int get_n_relevant_players() { return 2; }
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,40 @@ Rep4<T>::Rep4(Player& P) :
|
||||
rep_prngs[i].SetSeed(to_receive[P.get_player(i)].get_data());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Rep4<T>::Rep4(Player& P, prngs_type& prngs) :
|
||||
my_num(P.my_num()), P(P)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
rep_prngs[i].SetSeed(prngs[i]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Rep4<T>::~Rep4()
|
||||
{
|
||||
for (auto& x : receive_hashes)
|
||||
for (auto& y : x)
|
||||
if (y.size > 0)
|
||||
{
|
||||
check();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& x : send_hashes)
|
||||
for (auto& y : x)
|
||||
if (y.size > 0)
|
||||
{
|
||||
check();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Rep4<T> Rep4<T>::branch()
|
||||
{
|
||||
return {P, rep_prngs};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Rep4<T>::init_mul(SubProcessor<T>*)
|
||||
{
|
||||
@@ -184,7 +218,7 @@ template<class T>
|
||||
void Rep4<T>::init_dotprod(SubProcessor<T>*)
|
||||
{
|
||||
init_mul();
|
||||
next_dotprod();
|
||||
dotprod_shares = {};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -192,15 +226,16 @@ void Rep4<T>::prepare_dotprod(const T& x, const T& y)
|
||||
{
|
||||
auto a = get_addshares(x, y);
|
||||
for (int i = 0; i < 5; i++)
|
||||
add_shares[i].back() += a[i];
|
||||
dotprod_shares[i] += a[i];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Rep4<T>::next_dotprod()
|
||||
{
|
||||
for (auto& a : add_shares)
|
||||
a.push_back({});
|
||||
for (int i = 0; i < 5; i++)
|
||||
add_shares[i].push_back(dotprod_shares[i]);
|
||||
bit_lengths.push_back(-1);
|
||||
dotprod_shares = {};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -234,7 +269,6 @@ T Rep4<T>::finalize_mul(int)
|
||||
template<class T>
|
||||
T Rep4<T>::finalize_dotprod(int)
|
||||
{
|
||||
this->counter++;
|
||||
return finalize_mul();
|
||||
}
|
||||
|
||||
@@ -297,6 +331,7 @@ void Rep4<T>::trunc_pr(const vector<int>& regs, int size,
|
||||
SubProcessor<T>& proc, false_type)
|
||||
{
|
||||
assert(regs.size() % 4 == 0);
|
||||
this->trunc_pr_counter += size * regs.size() / 4;
|
||||
typedef typename T::open_type open_type;
|
||||
|
||||
vector<TruncPrTupleWithGap<open_type>> infos;
|
||||
@@ -419,3 +454,76 @@ void Rep4<T>::trunc_pr(const vector<int>& regs, int size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class U>
|
||||
void Rep4<T>::split(vector<T>& dest, const vector<int>& regs, int n_bits,
|
||||
const U* source, int n_inputs)
|
||||
{
|
||||
assert(regs.size() / n_bits == 2);
|
||||
assert(n_bits <= 64);
|
||||
int unit = GC::Clear::N_BITS;
|
||||
int my_num = P.my_num();
|
||||
int i0 = -1;
|
||||
|
||||
switch (my_num)
|
||||
{
|
||||
case 0:
|
||||
i0 = 1;
|
||||
break;
|
||||
case 1:
|
||||
i0 = 0;
|
||||
break;
|
||||
case 2:
|
||||
i0 = 1;
|
||||
break;
|
||||
case 3:
|
||||
i0 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
vector<BitVec> to_share;
|
||||
init_mul();
|
||||
|
||||
for (int k = 0; k < DIV_CEIL(n_inputs, unit); k++)
|
||||
{
|
||||
int start = k * unit;
|
||||
int m = min(unit, n_inputs - start);
|
||||
|
||||
square64 square;
|
||||
|
||||
for (int j = 0; j < m; j++)
|
||||
{
|
||||
auto& input_share = source[j + start];
|
||||
auto input_value = input_share[i0] + input_share[i0 + 1];
|
||||
square.rows[j] = Integer(input_value).get();
|
||||
}
|
||||
|
||||
square.transpose(m, n_bits);
|
||||
|
||||
for (int j = 0; j < n_bits; j++)
|
||||
{
|
||||
to_share.push_back(square.rows[j]);
|
||||
bit_lengths.push_back(m);
|
||||
}
|
||||
}
|
||||
|
||||
array<PointerVector<ResTuple>, 2> results;
|
||||
for (auto& x : results)
|
||||
x.resize(to_share.size());
|
||||
prepare_joint_input(0, 1, 3, 2, to_share, results[0]);
|
||||
prepare_joint_input(2, 3, 1, 0, to_share, results[1]);
|
||||
P.send_receive_all(channels, send_os, receive_os);
|
||||
finalize_joint_input(0, 1, 3, 2, results[0]);
|
||||
finalize_joint_input(2, 3, 1, 0, results[1]);
|
||||
|
||||
for (int k = 0; k < DIV_CEIL(n_inputs, unit); k++)
|
||||
{
|
||||
for (int j = 0; j < n_bits; j++)
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
auto res = results[i].next().res;
|
||||
dest.at(regs.at(2 * j + i) + k) = res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user