def test_misc(self): secint = mpc.SecInt() secfxp = mpc.SecFxp() secfld = mpc.SecFld() for secnum in (secint, secfxp, secfld): self.assertEqual(type(mpc.run(mpc.output(secnum(0), raw=True))), secnum.field) self.assertEqual(mpc.run(mpc.output(mpc._reshare([secnum(0)]))), [0]) self.assertEqual(mpc.run(mpc.output(mpc.all(secnum(1) for _ in range(5)))), True) self.assertEqual(mpc.run(mpc.output(mpc.all([secnum(1), secnum(1), secnum(0)]))), False) self.assertEqual(mpc.run(mpc.output(mpc.any(secnum(0) for _ in range(5)))), False) self.assertEqual(mpc.run(mpc.output(mpc.any([secnum(0), secnum(1), secnum(1)]))), True) self.assertEqual(mpc.run(mpc.output(mpc.sum([secnum(1)], start=1))), 2) self.assertEqual(mpc.run(mpc.output(mpc.prod([secnum(1)], start=1))), 1) self.assertEqual(mpc.run(mpc.output(mpc.sum([secnum(1)], start=secnum(1)))), 2) self.assertEqual(mpc.run(mpc.output(mpc.min(secint(i) for i in range(-1, 2, 1)))), -1) self.assertEqual(mpc.run(mpc.output(mpc.argmin(secint(i) for i in range(-1, 2, 1))[0])), 0) self.assertEqual(mpc.run(mpc.output(mpc.max(secfxp(i) for i in range(-1, 2, 1)))), 1) self.assertEqual(mpc.run(mpc.output(mpc.argmax(secfxp(i) for i in range(-1, 2, 1))[0])), 2) self.assertEqual(mpc.run(mpc.output(list(mpc.min_max(map(secfxp, range(5)))))), [0, 4]) x = (secint(i) for i in range(-3, 3)) s = [0, -1, 1, -2, 2, -3] self.assertEqual(mpc.run(mpc.output(mpc.sorted(x, key=lambda a: a*(2*a+1)))), s) x = (secfxp(i) for i in range(5)) self.assertEqual(mpc.run(mpc.output(mpc.sorted(x, reverse=True))), [4, 3, 2, 1, 0]) self.assertEqual(mpc.run(mpc.output(mpc.sum(map(secint, range(5))))), 10) self.assertEqual(mpc.run(mpc.output(mpc.sum([secfxp(2.75)], start=3.125))), 5.875) self.assertEqual(int(mpc.run(mpc.output(mpc.prod(map(secfxp, range(1, 5)))))), 24) self.assertEqual(int(mpc.run(mpc.output(mpc.prod([secfxp(1.414214)]*4)))), 4)
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))
async def mpc_signumsum(input_bits): # compute sum and specify placeholder for result sec_sum = mpc.sum(input_bits) # compute maximum length of binary representation of sum (+1 as int() rounds down) bit_len = int(1 + math.log(len(input_bits), 2.0)) # compute signum -- maximum length of binary representation is provided for better efficiency result = mpc.sgn(sec_sum, l=bit_len) return result
def test_empty_input(self): secint = mpc.SecInt() self.assertEqual(mpc.run(mpc.gather([])), []) self.assertEqual(mpc.run(mpc.output([])), []) self.assertEqual(mpc._reshare([]), []) self.assertEqual(mpc.convert([], None), []) self.assertEqual(mpc.sum([]), 0) self.assertEqual(mpc.sum([], start=1), 1) self.assertEqual(mpc.run(mpc.output(mpc.sum([], start=secint(1)))), 1) self.assertEqual(mpc.prod([]), 1) self.assertEqual(mpc.all([]), 1) self.assertEqual(mpc.any([]), 0) self.assertEqual(mpc.in_prod([], []), 0) self.assertEqual(mpc.vector_add([], []), []) self.assertEqual(mpc.vector_sub([], []), []) self.assertEqual(mpc.scalar_mul(secint(0), []), []) self.assertEqual(mpc.schur_prod([], []), []) self.assertEqual(mpc.from_bits([]), 0)
def test_misc(self): secint = mpc.SecInt() secfxp = mpc.SecFxp() secfld = mpc.SecFld() for secnum in (secint, secfxp, secfld): self.assertEqual(mpc.run(mpc.output(mpc._reshare([secnum(0)]))), [0]) self.assertEqual( mpc.run(mpc.output(mpc.all(secnum(1) for _ in range(5)))), True) self.assertEqual( mpc.run(mpc.output(mpc.all([secnum(1), secnum(1), secnum(0)]))), False) self.assertEqual( mpc.run(mpc.output(mpc.any(secnum(0) for _ in range(5)))), False) self.assertEqual( mpc.run(mpc.output(mpc.any([secnum(0), secnum(1), secnum(1)]))), True) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=1))), 2) self.assertEqual( mpc.run(mpc.output(mpc.prod([secnum(1)], start=1))), 1) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=secnum(1)))), 2) self.assertEqual( mpc.run(mpc.output(mpc.min(secint(i) for i in range(-1, 2, 1)))), -1) self.assertEqual( mpc.run(mpc.output(mpc.max(secfxp(i) for i in range(-1, 2, 1)))), 1) self.assertEqual( mpc.run(mpc.output(list(mpc.min_max(map(secfxp, range(5)))))), [0, 4]) self.assertEqual(mpc.run(mpc.output(mpc.sum(map(secint, range(5))))), 10) self.assertEqual( mpc.run(mpc.output(mpc.sum([secfxp(2.72)], start=3.14))), 5.86) self.assertEqual( int(mpc.run(mpc.output(mpc.prod(map(secfxp, range(1, 5)))))), 24) self.assertEqual( int(mpc.run(mpc.output(mpc.prod([secfxp(1.414214)] * 4)))), 4)
async def main(): # initialize mpc, define secure int type LEN = 10 await mpc.start() secint = mpc.SecInt(64) # initialize inputs values = [np.random.randint(1,1000) for _ in range(LEN)] n = len(mpc.parties) inputs = mpc.input([secint(v)for v in values], senders=list(range(n))) # compute pairwise products prod = inputs[0] for inp in inputs[1:]: prod = mpc.schur_prod(prod, inp) ip = mpc.sum(prod) # output result result = await mpc.output(ip) print("result:", result) await mpc.shutdown()
async def id3(T, R) -> asyncio.Future: sizes = [mpc.in_prod(T, v) for v in S[C]] i, mx = mpc.argmax(sizes) sizeT = mpc.sum(sizes) stop = (sizeT <= int(args.epsilon * len(T))) + (mx == sizeT) if not (R and await mpc.is_zero_public(stop)): i = await mpc.output(i) logging.info(f'Leaf node label {i}') tree = i else: T_R = [[mpc.schur_prod(T, v) for v in S[A]] for A in R] gains = [GI(mpc.matrix_prod(T_A, S[C], True)) for T_A in T_R] k = await mpc.output(mpc.argmax(gains, key=SecureFraction)[0]) T_Rk = T_R[k] del T_R, gains # release memory A = list(R)[k] logging.info(f'Attribute node {A}') if args.parallel_subtrees: subtrees = await mpc.gather( [id3(Tj, R.difference([A])) for Tj in T_Rk]) else: subtrees = [await id3(Tj, R.difference([A])) for Tj in T_Rk] tree = A, subtrees return tree
def test_misc(self): secint = mpc.SecInt() secfxp = mpc.SecFxp() secfld = mpc.SecFld() for secnum in (secint, secfxp, secfld): self.assertEqual(type(mpc.run(mpc.output(secnum(0), raw=True))), secnum.field) self.assertEqual(mpc.run(mpc.output(mpc._reshare([secnum(0)]))), [0]) self.assertEqual( mpc.run(mpc.output(mpc.all(secnum(1) for _ in range(5)))), True) self.assertEqual( mpc.run(mpc.output(mpc.all([secnum(1), secnum(1), secnum(0)]))), False) self.assertEqual( mpc.run(mpc.output(mpc.any(secnum(0) for _ in range(5)))), False) self.assertEqual( mpc.run(mpc.output(mpc.any([secnum(0), secnum(1), secnum(1)]))), True) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=1))), 2) self.assertEqual( mpc.run(mpc.output(mpc.prod([secnum(1)], start=1))), 1) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=secnum(1)))), 2) self.assertEqual( mpc.run(mpc.output(mpc.find([secnum(1)], 0, e=-1))), -1) self.assertEqual(mpc.run(mpc.output(mpc.find([secnum(1)], 1))), 0) self.assertEqual( mpc.run(mpc.output(mpc.find([secnum(1)], 1, f=lambda i: i))), 0) self.assertEqual( mpc.run(mpc.output(mpc.min(secint(i) for i in range(-1, 2, 1)))), -1) self.assertEqual( mpc.run( mpc.output(mpc.argmin(secint(i) for i in range(-1, 2, 1))[0])), 0) self.assertEqual( mpc.run(mpc.output(mpc.max(secfxp(i) for i in range(-1, 2, 1)))), 1) self.assertEqual( mpc.run( mpc.output(mpc.argmax(secfxp(i) for i in range(-1, 2, 1))[0])), 2) self.assertEqual( mpc.run(mpc.output(list(mpc.min_max(map(secfxp, range(5)))))), [0, 4]) x = (secint(i) for i in range(-3, 3)) s = [0, -1, 1, -2, 2, -3] self.assertEqual( mpc.run(mpc.output(mpc.sorted(x, key=lambda a: a * (2 * a + 1)))), s) x = (secfxp(i) for i in range(5)) self.assertEqual(mpc.run(mpc.output(mpc.sorted(x, reverse=True))), [4, 3, 2, 1, 0]) self.assertEqual(mpc.run(mpc.output(mpc.sum(map(secint, range(5))))), 10) self.assertEqual( mpc.run(mpc.output(mpc.sum([secfxp(2.75)], start=3.125))), 5.875) self.assertEqual( int(mpc.run(mpc.output(mpc.prod(map(secfxp, range(1, 5)))))), 24) self.assertEqual( int(mpc.run(mpc.output(mpc.prod([secfxp(1.414214)] * 4)))), 4) self.assertEqual(mpc.find([], 0), 0) self.assertEqual(mpc.find([], 0, e=None), (1, 0)) self.assertEqual( mpc.run(mpc.output(list(mpc.find([secfld(1)], 1, e=None)))), [0, 0]) self.assertEqual( mpc.run(mpc.output(mpc.find([secfld(2)], 2, bits=False))), 0) x = [secint(i) for i in range(5)] f = lambda i: [i**2, 3**i] self.assertEqual(mpc.run(mpc.output(mpc.find(x, 2, bits=False, f=f))), [4, 9]) cs_f = lambda b, i: [b * (2 * i + 1) + i**2, (b * 2 + 1) * 3**i] self.assertEqual( mpc.run(mpc.output(mpc.find(x, 2, bits=False, cs_f=cs_f))), [4, 9])
def getitem(self, index): """get item with a secret index, returns 0 when item is not included""" length = len(self.values) unit = mpc.unit_vector(index, length) return mpc.sum(mpc.schur_prod(self.included_values_or_zero(), unit))
def len(self): return mpc.sum(self.included)
def sum(self): return mpc.sum(self.values)
def getitem(self, index): """get item with a secret index""" length = len(self.values) unit = mpc.unit_vector(index, length) return mpc.sum(mpc.schur_prod(self.values, unit))
def sum(self): return mpc.sum(self.included_values_or_zero())
async def signumsum(input_bits): # compute sum and specify placeholder for result sec_sum = mpc.sum(input_bits) result = mpc.sgn(sec_sum) return result
async def main(): await mpc.start() with open(f"icissp2020-{len(mpc.parties)}_parties-output.csv", 'w', newline='') as csvfile: print(f"running benchmarks; output will be in {csvfile.name}") print("clearing netem delay just in case ...") subprocess.run(["sudo", "tc", "qdisc","del","dev","lo","root","netem","delay", '0ms']) subprocess.run(["sudo", "tc", "qdisc","del","dev","lo","root","netem","loss", '0%']) fieldnames = ["length","delay","loss","addition","mpc.vector_add()","summation","mpc.sum()","multiplication","mpc.schur_prod()","product","mpc.prod()"] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for d in range(0,55,5): for p in range(0,11,1): for length in [1,10,100]: print("generating random inputs ...") a = [ [ mpc.input(sec(secrets.randbits(sec.bit_length)))[0] for _ in range(length) ] for _ in range(loop) ] b = [ [ mpc.input(sec(secrets.randbits(sec.bit_length)))[0] for _ in range(length) ] for _ in range(loop) ] r1 = [None] * loop r2 = [None] * loop res = [None] * 8 for i in range(loop): await mpc.output(a[i]) await mpc.output(b[i]) time.sleep(1) print(f"comparing {loop} runs on vectors of length {length} with latency {d*2}ms and {p}% loss\n") subprocess.run(["sudo", "tc", "qdisc","add","dev","lo","root","netem","delay", f"{d}ms"]) subprocess.run(["sudo", "tc", "qdisc","add","dev","lo","root","netem","loss", f"{p}%"]) print("elementwise addition".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = list(map(operator.add, a[i], b[i])) r1[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[0] = f"{(t2 - t1):f}" time.sleep(1) print("mpc.vector_add()".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = mpc.vector_add(a[i], b[i]) r2[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[1] = f"{(t2 - t1):f}" time.sleep(1) print("summation".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = functools.reduce(operator.add, a[i]) r1[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[2] = f"{(t2 - t1):f}" time.sleep(1) print("mpc.sum()".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = mpc.sum(a[i]) r2[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[3] = f"{(t2 - t1):f}" time.sleep(1) print("elementwise multiplication".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = list(map(operator.mul, a[i], b[i])) r1[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[4] = f"{(t2 - t1):f}" time.sleep(1) print("mpc.schur_prod()".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = mpc.schur_prod(a[i], b[i]) r2[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[5] = f"{(t2 - t1):f}" time.sleep(1) print("product".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = functools.reduce(operator.mul, a[i]) r1[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[6] = f"{(t2 - t1):f}" time.sleep(1) print("mpc.prod()".ljust(32), end='', flush=True) t1 = time.perf_counter() for i in range(loop): r = mpc.prod(a[i]) r2[i] = await mpc.gather(r) t2 = time.perf_counter() print(f"{(t2 - t1):.5} seconds") res[7] = f"{(t2 - t1):f}" time.sleep(1) subprocess.run(["sudo", "tc", "qdisc","del","dev","lo","root","netem","delay", "0ms"]) subprocess.run(["sudo", "tc", "qdisc","del","dev","lo","root","netem","loss", "0%"]) writer.writerow({ 'length': f"{length}", 'delay': f"{d*2}", 'loss': f"{p}", 'addition': res[0], 'mpc.vector_add()': res[1], 'summation': res[2], 'mpc.sum()': res[3], 'multiplication': res[4], 'mpc.schur_prod()': res[5], 'product': res[6], 'mpc.prod()': res[7] }) await mpc.shutdown()
def aggregate(d, n, stride): agg_d = [ mpc.sum(d[start:start + stride]) for start in range(0, len(d), stride) ] agg_n = n[::stride] return agg_d, agg_n
def test_secint(self): secint = mpc.SecInt() a = mpc.run(mpc.output(getrandbits(secint, 10))) self.assertGreaterEqual(a, 0) self.assertLessEqual(a, 2**10 - 1) x = mpc.run(mpc.output(random_unit_vector(secint, 4))) self.assertEqual(sum(x), 1) a = mpc.run(mpc.output(randrange(secint, 37))) # French roulette self.assertGreaterEqual(a, 0) self.assertLessEqual(a, 36) a = mpc.run(mpc.output(randrange(secint, 1, 7))) # one die self.assertGreaterEqual(a, 1) self.assertLessEqual(a, 6) a = mpc.run(mpc.output(randrange(secint, 1, 7) + randrange(secint, 1, 7))) # two dice self.assertGreaterEqual(a, 2) self.assertLessEqual(a, 12) a = mpc.run(mpc.output(randrange(secint, 1, 32, 2))) self.assertGreaterEqual(a, 1) self.assertLessEqual(a, 31) self.assertEqual(a % 2, 1) a = mpc.run(mpc.output(randint(secint, -1, 1))) self.assertIn(a, [-1, 0, 1]) x = list(range(8)) shuffle(secint, x) shuffle(secint, x) x = mpc.run(mpc.output(x)) self.assertSetEqual(set(x), set(range(8))) x = mpc.run(mpc.output(random_permutation(secint, 8))) self.assertSetEqual(set(x), set(range(8))) x = mpc.run(mpc.output(random_derangement(secint, 2))) self.assertListEqual(x, [1, 0]) x = mpc.run(mpc.output(random_derangement(secint, range(1, 9)))) self.assertSetEqual(set(x), set(range(1, 9))) x = mpc.run(mpc.output(choice(secint, [1, 2, 3, 4, 5]))) self.assertIn(x, [1, 2, 3, 4, 5]) x = mpc.run(mpc.output(choice(secint, [secint(-100), secint(200), secint(-300)]))) self.assertIn(x, [-100, 200, -300]) x = mpc.run(mpc.output(mpc.sum(choices(secint, [0, 1], k=5)))) # uniform self.assertGreaterEqual(x, 0) self.assertLessEqual(x, 5) x = mpc.run(mpc.output(mpc.sum(choices(secint, [0, 1], [25, 75])))) # Bernoulli self.assertGreaterEqual(x, 0) self.assertLessEqual(x, 1) x = mpc.run(mpc.output(mpc.sum(choices(secint, [0, 1], [25, 75], k=10)))) # binomial self.assertGreaterEqual(x, 0) self.assertLessEqual(x, 10) x = mpc.run(mpc.output(sample(secint, [2**i for i in range(16)], 8))) self.assertGreaterEqual(sum(x), 2**8 - 1) self.assertLessEqual(sum(x), 2**8 * (2**8 - 1)) x = mpc.run(mpc.output(sample(secint, range(10**8), 10))) self.assertGreaterEqual(min(x), 0) self.assertLessEqual(max(x), 10**8 - 1) x = mpc.run(mpc.output(sample(secint, range(1000000, 3000000, 1000), 10))) self.assertGreaterEqual(min(x) // 1000, 1000) self.assertLessEqual(max(x) // 1000, 3000) self.assertEqual(sum(x) % 1000, 0)
def get_attribute_value_for_sample(sample, index): unit_vector = mpc.unit_vector(index, len(sample)) return mpc.sum(mpc.schur_prod(sample, unit_vector))
async def sum(): secint = mpc.SecInt() x = [secint(1), secint(1), secint(0), secint(1), secint(1), secint(0)] t = mpc.sum(x) return t
Run with m parties to compute: - m = sum_{i=0}^{m-1} 1 = sum(1 for i in range(m)) - m**2 = sum_{i=0}^{m-1} 2i+1 = sum(2*i+1 for i in range(m)) - 2**m = prod_{i=0}^{m-1} 2 = prod(2 for i in range(m)) - m! = prod_{i=0}^{m-1} i+1 = prod(i+1 for i in range(m)) Bit lengths of secure integers ensure each result fits for any m >= 1. """ from mpyc.runtime import mpc m = len(mpc.parties) l = m.bit_length() mpc.run(mpc.start()) print('m =', mpc.run(mpc.output(mpc.sum(mpc.input(mpc.SecInt(l + 1)(1)))))) print( 'm**2 =', mpc.run( mpc.output(mpc.sum(mpc.input(mpc.SecInt(2 * l + 1)(2 * mpc.pid + 1)))))) print('2**m =', mpc.run(mpc.output(mpc.prod(mpc.input(mpc.SecInt(m + 2)(2)))))) print( 'm! =', mpc.run( mpc.output( mpc.prod(mpc.input( mpc.SecInt(int(m * (l - 1.4) + 3))(mpc.pid + 1)))))) mpc.run(mpc.shutdown())
all_sec_vi = mpc.input(sec_vi) cmd = 'std' if cmd == 'min': sec_minimum = mpc.min(all_sec_vi) minimum = mpc.run(mpc.output(sec_minimum)) print(minimum) elif cmd == 'max': sec_maximum = mpc.max(all_sec_vi) maximum = mpc.run(mpc.output(sec_maximum)) print(maximum) elif cmd == 'mean': sec_sum = mpc.sum(all_sec_vi) sec_mean = mpc.div(sec_sum, nb_parties) mean = mpc.run(mpc.output(sec_mean)) print(mean) elif cmd == 'std': sec_sum = mpc.sum(all_sec_vi) sec_mean = mpc.div(sec_sum, nb_parties) sec_stddev = mpc.pow(mpc.sub(all_sec_vi[0], sec_mean), 2) for v in all_sec_vi[1:]: sec_stddev = mpc.add(sec_stddev, mpc.pow(mpc.sub(v, sec_mean), 2)) stddev = np.sqrt( float(mpc.run(mpc.output(sec_stddev))) / float(nb_parties)) print(stddev) ###############################################################################