Skip to content

Commit

Permalink
Semi-honest computation based on threshold semi-homomorphic encryption.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkskeller committed Feb 17, 2022
1 parent 61d40b7 commit 0f7020d
Show file tree
Hide file tree
Showing 129 changed files with 1,973 additions and 539 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
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.9 (Jan 11, 2021)
## 0.3.0 (Feb 17, 2022)

- Semi-honest computation based on threshold semi-homomorphic encryption
- Batch normalization backward propagation
- AlexNet for CIFAR-10
- Specific private output protocols
- Semi-honest additive secret sharing without communication
- Sending of personal values
- Allow overwriting of persistence files
- Protocol signature in persistence files

## 0.2.9 (Jan 11, 2022)

- Disassembler
- Run-time parameter for probabilistic truncation error
Expand Down
1 change: 1 addition & 0 deletions CONFIG
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ else
AVX_OT = 1
endif
else
ARCH =
AVX_OT = 0
endif

Expand Down
37 changes: 26 additions & 11 deletions Compiler/GC/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ class movsb(NonVectorInstruction):
code = opcodes['MOVSB']
arg_format = ['sbw','sb']

class trans(base.VarArgsInstruction):
class trans(base.VarArgsInstruction, base.DynFormatInstruction):
""" Secret bit register vector transpose. The first destination vector
will contain the least significant bits of all source vectors etc.
Expand All @@ -511,10 +511,22 @@ class trans(base.VarArgsInstruction):
code = opcodes['TRANS']
is_vec = lambda self: True
def __init__(self, *args):
self.arg_format = ['int'] + ['sbw'] * args[0] + \
['sb'] * (len(args) - 1 - args[0])
super(trans, self).__init__(*args)

@classmethod
def dynamic_arg_format(cls, args):
yield 'int'
n = next(args)
for i in range(n):
yield 'sbw'
next(args)
while True:
try:
yield 'sb'
next(args)
except StopIteration:
break

class bitb(NonVectorInstruction):
""" Copy fresh secret random bit to secret bit register.
Expand Down Expand Up @@ -560,7 +572,7 @@ def add_usage(self, req_node):
req_node.increment(('bit', 'input', self.args[i]), self.args[i + 1])

class inputbvec(base.DoNotEliminateInstruction, base.VarArgsInstruction,
base.Mergeable):
base.Mergeable, base.DynFormatInstruction):
""" Copy private input to secret bit registers bit by bit. The input is
read as floating-point number, multiplied by a power of two, rounded to an
integer, and then decomposed into bits.
Expand All @@ -577,11 +589,18 @@ class inputbvec(base.DoNotEliminateInstruction, base.VarArgsInstruction,
code = opcodes['INPUTBVEC']

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)

@classmethod
def dynamic_arg_format(cls, args):
yield 'int'
for i, n in cls.bases(args):
yield 'int'
yield 'p'
for j in range(n - 3):
yield 'sbw'
yield 'int'

@staticmethod
def get_arg_tuples(args):
i = 0
Expand All @@ -590,10 +609,6 @@ def get_arg_tuples(args):
i += args[i]
assert i == len(args)

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)
Expand Down
28 changes: 17 additions & 11 deletions Compiler/GC/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class bitsn(cls):
return cls.types[length]
@classmethod
def conv(cls, other):
if isinstance(other, cls):
if isinstance(other, cls) and cls.n == other.n:
return other
elif isinstance(other, MemValue):
return cls.conv(other.read())
Expand Down Expand Up @@ -246,14 +246,20 @@ def conv_regint_by_bit(cls, n, res, other):
assert n == res.n
assert n == other.size
cls.conv_cint_vec(cint(other, size=other.size), res)
@classmethod
def conv(cls, other):
if isinstance(other, cbits) and cls.n != None and \
cls.n // cls.unit == other.n // cls.unit:
return other
else:
return super(cbits, cls).conv(other)
types = {}
def load_int(self, value):
if self.n <= 64:
tmp = regint(value)
elif value == self.long_one():
tmp = cint(1, size=self.n)
else:
raise CompilerError('loading long integers to cbits not supported')
n_limbs = math.ceil(self.n / self.unit)
tmp = regint(size=n_limbs)
for i in range(n_limbs):
tmp[i].load_int(value % 2 ** self.unit)
value >>= self.unit
self.load_other(tmp)
def store_in_dynamic_mem(self, address):
inst.stmsdci(self, cbits.conv(address))
Expand Down Expand Up @@ -1163,14 +1169,14 @@ class cbitfix(object):
@classmethod
def _new(cls, value):
res = cls()
if cls.k < value.unit:
bits = value.bit_decompose(cls.k)
sign = bits[-1]
value += (sign << (cls.k)) * -1
res.v = value
return res
def output(self):
v = self.v
if self.k < v.unit:
bits = self.v.bit_decompose(self.k)
sign = bits[-1]
v += (sign << (self.k)) * -1
inst.print_float_plainb(v, cbits.get_type(32)(-self.f), cbits(0),
cbits(0), cbits(0))

Expand Down
20 changes: 15 additions & 5 deletions Compiler/allocator.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,20 @@ def keep_merged_order(instr, n, t):
add_edge(last_input[t][1], n)
last_input[t][0] = n

def keep_text_order(inst, n):
if inst.get_players() is None:
# switch
for x in list(last_input.keys()):
if isinstance(x, int):
add_edge(last_input[x][0], n)
del last_input[x]
keep_merged_order(instr, n, None)
elif last_input[None][0] is not None:
keep_merged_order(instr, n, None)
else:
for player in inst.get_players():
keep_merged_order(instr, n, player)

for n,instr in enumerate(block.instructions):
outputs,inputs = instr.get_def(), instr.get_used()

Expand All @@ -427,7 +441,7 @@ def keep_merged_order(instr, n, t):

# will be merged
if isinstance(instr, TextInputInstruction):
keep_merged_order(instr, n, TextInputInstruction)
keep_text_order(instr, n)
elif isinstance(instr, RawInputInstruction):
keep_merged_order(instr, n, RawInputInstruction)

Expand Down Expand Up @@ -479,10 +493,6 @@ def keep_merged_order(instr, n, t):
last_print_str = n
elif isinstance(instr, PublicFileIOInstruction):
keep_order(instr, n, instr.__class__)
elif isinstance(instr, startprivateoutput_class):
keep_order(instr, n, startprivateoutput_class, 2)
elif isinstance(instr, stopprivateoutput_class):
keep_order(instr, n, stopprivateoutput_class, 2)
elif isinstance(instr, prep_class):
keep_order(instr, n, instr.args[0])
elif isinstance(instr, StackInstruction):
Expand Down
Loading

0 comments on commit 0f7020d

Please sign in to comment.