def agg_logrank_test(secfxp, d1, d2, n1, n2, agg_d1, agg_d2, stride): candidates = [] maxT = len(d1) for start in range(0, maxT, stride): group = start // stride n_observed_events = agg_d1[group] + agg_d2[group] msn = min(stride, n_observed_events) # upper bound stop = min(start + stride, maxT) logging.info(f'Interval {group + 1} (time {start + 1} to {stop})' f' # observed events = {n_observed_events}') if msn == 0: continue oblivious_table = [[secfxp(0), secfxp(0), secfxp(1), secfxp(1)]] * msn ix = [secfxp(0)] * msn for j in range(start, stop): is_active = d1[j] + d2[j] != 0 ix = mpc.if_else(is_active, [1 - mpc.sum(ix)] + ix[:-1], ix) select = mpc.scalar_mul(is_active, ix) new = [d1[j], d2[j], n1[j], n2[j]] for i in range(msn): oblivious_table[i] = mpc.if_else(select[i], new, oblivious_table[i]) candidates.extend(oblivious_table) return logrank_test(secfxp, *zip(*candidates))
def __lt__( self, other ): # NB: __lt__() is basic comparison as in Python's list.sort() c = mpc.in_prod([self.n, -self.d], [other.d, other.n]) < 0 c = mpc.if_else(self.pos, c, 0) c = mpc.if_else(other.pos, c, 1) return c
def test_if_else_if_swap(self): secfld = mpc.SecFld() a = secfld(0) b = secfld(1) c = secfld(1) self.assertEqual(mpc.run(mpc.output(c.if_else(a, b))), 0) self.assertEqual(mpc.run(mpc.output(mpc.if_swap(1 - c, a, b))), [0, 1]) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, [a, b], [b, a]))), [0, 1]) self.assertEqual(mpc.run(mpc.output((1 - c).if_swap(a, b))), [0, 1]) secint = mpc.SecInt() a = secint(-1) b = secint(1) c = secint(1) self.assertEqual(mpc.run(mpc.output(c.if_swap([a, b], [b, a])[0])), [1, -1]) self.assertEqual(mpc.run(mpc.output(mpc.if_else(1 - c, b, b))), 1) self.assertEqual(mpc.run(mpc.output(mpc.if_swap(c, a, b))), [1, -1]) self.assertEqual(mpc.run(mpc.output((1 - c).if_else([a, b], [b, a]))), [1, -1]) secfxp = mpc.SecFxp() a = secfxp(-1.0) b = secfxp(1.0) c = secfxp(1) self.assertEqual(mpc.run(mpc.output(c.if_else([a, a], [b, b]))), [-1.0, -1.0]) self.assertEqual(mpc.run(mpc.output(mpc.if_swap(1 - c, a, b))), [-1.0, 1.0]) self.assertEqual(mpc.run(mpc.output(mpc.if_swap(c, 0.0, 1.0))), [1.0, 0.0]) self.assertEqual(mpc.run(mpc.output((1 - c).if_else(0.0, 1.0))), 1.0)
def argmax(x): argmax = type(x[0])(0) m = x[0] for i in range(1, len(x)): b = (m >= x[i]) argmax = mpc.if_else(b, argmax, i) m = mpc.if_else(b, m, x[i]) return argmax
def argmax(xs, arg_ge): n = len(xs) if n == 1: return secint(0), xs[0] i0, max0 = argmax(xs[:n // 2], arg_ge) i1, max1 = argmax(xs[n // 2:], arg_ge) a, m = arg_ge(max0, max1) return mpc.if_else(a, n // 2 + i1, i0), m
def calculate_gains_for_thresholds(column, outcomes): gains = column.map(lambda _: None) is_right = column.map(lambda _: s(0)) selection = [None for _ in range(len(column.values))] last_considered_value = s(-1) for index in reversed(range(len(column.values))): gains.values[index] = calculate_gain(is_right, outcomes) is_right.values[index] = s(1) is_duplicate = column.values[index] == last_considered_value selection[index] = ~is_duplicate last_considered_value = mpc.if_else(column.is_included(index), column.values[index], last_considered_value) return gains.select(selection)
# computes a database join function (sums by category) # this code is written as a script, so we call mpc.run() on each individual mpc operation instead of # calling it once on the whole operation as in mult3, innerprod # # this code was contributed by Berry Schoenmakers via private correspondence # from mpyc.runtime import mpc from mpyc.seclists import seclist secint = mpc.SecInt() N = 25 # number of samples C = 4 # number of categories # deterministic input data # (no mpc.input to assign different inputs to different parties) categories = [(secint(i), secint(i % C)) for i in range(N)] values = [(secint(i), secint(i)) for i in range(N)] mpc.run(mpc.start()) s = seclist([0] * C, secint) for i, c in categories: for j, v in values: s[c] += mpc.if_else(i == j, v, 0) print(mpc.run(mpc.output(list(s)))) mpc.run(mpc.shutdown())
async def main(): parser = argparse.ArgumentParser() parser.add_argument( '-i', '--dataset', type=int, metavar='I', help=('dataset 0=uvlp (default), 1=wiki, 2=tb2x2, 3=woody, ' '4=LPExample_R20, 5=sc50b, 6=kb2, 7=LPExample')) parser.add_argument('-l', '--bit-length', type=int, metavar='L', help='override preset bit length for dataset') parser.set_defaults(dataset=0, bit_length=0) args = parser.parse_args() settings = [('uvlp', 24, 37 / 3), ('wiki', 24, 20), ('tb2x2', 18, 10.5), ('woody', 36, 540), ('LPExample_R20', 52, 3.441176), ('sc50b', 52, 70), ('kb2', 96, 1749.9204734889486), ('LPExample', 96, 1188806595)] name, bit_length, exact_max = settings[args.dataset] if args.bit_length: bit_length = args.bit_length with open(os.path.join('data', 'lp', name + '.csv')) as file: T = list(csv.reader(file)) m = len(T) - 1 n = len(T[0]) - 1 secfxp = mpc.SecFxp(bit_length) print( f'Using secure {bit_length}-bit fixed-point numbers: {secfxp.__name__}' ) print(f'dataset: {name} with {m} constraints and {n} variables') T[0][-1] = '0' # initialize optimal value for i in range(m + 1): for j in range(n + 1): T[i][j] = secfxp(float(T[i][j]), integral=False) c = T[0][:-1] # maximize c.x subject to A.x <= b, x >= 0 A = [T[i + 1][:-1] for i in range(m)] b = [T[i + 1][-1] for i in range(m)] await mpc.start() cobasis = [secfxp(j) for j in range(n)] basis = [secfxp(n + i) for i in range(m)] iteration = 0 while True: # find index of pivot column p_col_index, minimum = argmin_int(T[0][:-1]) if await mpc.output(minimum >= 0): break # maximum reached # find index of pivot row p_col = mpc.matrix_prod([p_col_index], T, True)[0] constraints = [[T[i][-1], p_col[i], p_col[i] > 0.0001] for i in range(1, m + 1)] p_row_index, (_, pivot, _) = argmin_rat(constraints) # reveal progress a bit iteration += 1 mx = await mpc.output(T[0][-1]) p = await mpc.output(pivot) logging.info(f'Iteration {iteration}: {mx} pivot={p}') # swap basis entries delta = mpc.in_prod(basis, p_row_index) - mpc.in_prod( cobasis, p_col_index) cobasis = mpc.vector_add(cobasis, mpc.scalar_mul(delta, p_col_index)) basis = mpc.vector_sub(basis, mpc.scalar_mul(delta, p_row_index)) # update tableau Tij = Tij - (Til - bool(i==k))/Tkl * (Tkj + bool(j==l)) p_col_index.append(secfxp(0)) p_row_index.insert(0, secfxp(0)) p_col = mpc.vector_sub(p_col, p_row_index) p_col = mpc.scalar_mul(1 / pivot, p_col) p_row = mpc.matrix_prod([p_row_index], T)[0] p_row = mpc.vector_add(p_row, p_col_index) T = mpc.gauss(T, secfxp(1), p_col, p_row) mx = await mpc.output(T[0][-1]) rel_error = (mx - exact_max) / exact_max print(f'max = {mx} (error {rel_error:.3%}) in {iteration} iterations') logging.info('Solution x') x = [secfxp(0) for _ in range(n)] for i in range(m): u = mpc.unit_vector(basis[i], m + n)[:n] v = mpc.scalar_mul(T[i + 1][-1], u) x = mpc.vector_add(x, v) cx = mpc.in_prod(c, x) Ax = mpc.matrix_prod([x], A, True)[0] approx = lambda a: 1.01 * a + 0.0001 Ax_bounded_by_b = mpc.all(Ax[i] <= approx(b[i]) for i in range(m)) x_nonnegative = mpc.all(x[j] >= 0 for j in range(n)) logging.info('Dual solution y') y = [secfxp(0) for _ in range(m)] for j in range(n): u = mpc.unit_vector(cobasis[j], m + n)[n:] v = mpc.scalar_mul(T[0][j], u) y = mpc.vector_sub(y, v) yb = mpc.in_prod(y, b) yA = mpc.matrix_prod([y], A)[0] approx = lambda a: mpc.if_else(a < 0, 1 / 1.01, 1.01) * a + 0.0001 yA_bounded_by_c = mpc.all(yA[j] <= approx(c[j]) for j in range(n)) y_nonpositive = mpc.all(y[i] <= 0 for i in range(m)) cx_eq_yb = abs(cx - yb) <= 0.01 * abs(cx) check = mpc.all([ cx_eq_yb, Ax_bounded_by_b, x_nonnegative, yA_bounded_by_c, y_nonpositive ]) check = bool(await mpc.output(check)) print( f'verification c.x == y.b, A.x <= b, x >= 0, y.A <= c, y <= 0: {check}' ) x = await mpc.output(x) print(f'solution = {x}') await mpc.shutdown()
def test_if_else(self): secfld = mpc.SecFld() a = secfld(0) b = secfld(1) c = secfld(1) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, a, b))), 0) self.assertEqual(mpc.run(mpc.output(mpc.if_else(1 - c, a, b))), 1) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, [a, b], [b, a]))), [0, 1]) self.assertEqual( mpc.run(mpc.output(mpc.if_else(1 - c, [a, b], [b, a]))), [1, 0]) secint = mpc.SecInt() a = secint(-1) b = secint(1) c = secint(1) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, a, b))), -1) self.assertEqual(mpc.run(mpc.output(mpc.if_else(1 - c, a, b))), 1) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, [a, b], [b, a]))), [-1, 1]) self.assertEqual( mpc.run(mpc.output(mpc.if_else(1 - c, [a, b], [b, a]))), [1, -1]) secfxp = mpc.SecFxp() a = secfxp(-1.0) b = secfxp(1.0) c = secfxp(1) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, a, b))), -1.0) self.assertEqual(mpc.run(mpc.output(mpc.if_else(1 - c, a, b))), 1.0) self.assertEqual(mpc.run(mpc.output(mpc.if_else(c, 0.0, 1.0))), 0.0) self.assertEqual(mpc.run(mpc.output(mpc.if_else(1 - c, 0.0, 1.0))), 1.0)
m = len(mpc.parties) if m%2 == 0: print('OT runs with odd number of parties only.') sys.exit() t = m//2 message = [(None, None)] * t choice = [None] * t if mpc.pid == 0: print('You are the trusted third party.') elif 1 <= mpc.pid <= t: message[mpc.pid - 1] = (random.randint(0, 99), random.randint(0, 99)) print(f'You are sender {mpc.pid} holding messages ' f'{message[mpc.pid - 1][0]} and {message[mpc.pid - 1][1]}.') else: choice[mpc.pid - t - 1] = random.randint(0, 1) print(f'You are receiver {mpc.pid - t} with random choice bit {choice[mpc.pid - t - 1]}.') mpc.run(mpc.start()) secnum = mpc.SecInt() for i in range(1, t+1): x = mpc.input([secnum(message[i-1][0]), secnum(message[i-1][1])], i) b = mpc.input(secnum(choice[i-1]), t + i) a = mpc.run(mpc.output(mpc.if_else(b, x[1], x[0]), t + i)) if a is not None: print(f'You have received message {a}.') mpc.run(mpc.shutdown())
def arg_le_rat(x0, x1): n0, d0 = x0 n1, d1 = x1 a = mpc.in_prod([n0, d0], [d1, -n1]) >= 0 m = mpc.if_else(a, [n1, d1], [n0, d0]) return a, m
def arg_le_int(x0, x1): a = x0 >= x1 m = mpc.if_else(a, x1, x0) return a, m
sec_noise0, sec_noise1 = secfxp(None), secfxp(None) # Secret-share both noise values with every other party all_sec_noises0 = mpc.input(sec_noise0, senders=list(range(1, M))) all_sec_noises1 = mpc.input(sec_noise1, senders=list(range(1, M))) # Collectively (and securely) draw M-1 random bits (one for each client) # These will be use to select which noise to use (0 or 1), for all clients sec_selection_bits = mpc.random_bits(secfxp, M - 1) sec_chosen_noises = [] for client_id, selection_bit_for_client in enumerate(sec_selection_bits): # If b is 0, we select noise0 from this client # If b is 1, we select noise1 from this client sec_chosen_noise = mpc.if_else(selection_bit_for_client, all_sec_noises1[client_id], all_sec_noises0[client_id]) sec_chosen_noises.append(sec_chosen_noise) # Aggregate the secure noise values from all parties total_sec_noise = scalar_add_all(sec_chosen_noises) # Find the secure maximum in the aggregated array of votes sec_max = mpc.max(total_sec_votes) # Add the aggregated noise to this max value noisy_sec_max = sec_max + total_sec_noise # Reveal (=recombine the shares) of this noisy maximum noisy_max = float(mpc.run(mpc.output(noisy_sec_max)))
# Convert them to secure type sec_noise0, sec_noise1 = secfxp(noise0), secfxp(noise1) # Secret-share both noise values with every other party all_sec_noises0 = mpc.input(sec_noise0) all_sec_noises1 = mpc.input(sec_noise1) # Generate a random selection bit b = mpc.random_bit( secfxp ) # FIXME: Will be the SAME random bit for every party (want a DIFFERENT one) # This will choose to keep noise0 or noise1 depending on the value of b # b is not known by the party, this is an hence an oblivious choice chosen_sec_noises = mpc.if_else(b, all_sec_noises1, all_sec_noises0) ################################################################################### # Aggregate the secure noise values from all parties total_sec_noise = scalar_add_all(chosen_sec_noises) # Find the secure maximum in the aggregated array of votes sec_max = mpc.max(total_sec_votes) # Add the aggregated noise to this max value noisy_sec_max = sec_max + total_sec_noise # Reveal (=recombine the shares) of this noisy maximum noisy_max = float(mpc.run(mpc.output(noisy_sec_max, receivers=range(0, M))))
def if_else(condition, if_true, if_false): if isinstance(if_true, tuple) and isinstance(if_false, tuple): return tuple(if_else(condition, list(if_true), list(if_false))) else: return mpc.if_else(condition, if_true, if_false)