def test_secfld(self): secfld = mpc.SecFld() self.assertEqual(secfld.field.modulus, 2) secfld = mpc.SecFld(l=16) a = secfld(1) b = secfld(0) self.assertEqual(mpc.run(mpc.output(a + b)), 1) self.assertEqual(mpc.run(mpc.output(a * b)), 0) secfld = mpc.SecFld(101) a = secfld(1) b = secfld(-1) self.assertEqual(mpc.run(mpc.output(a + b)), 0) self.assertEqual(mpc.run(mpc.output(a * b)), 100) self.assertEqual(mpc.run(mpc.output(a == b)), 0) self.assertEqual(mpc.run(mpc.output(a == -b)), 1) self.assertEqual(mpc.run(mpc.output(a**2 == b**2)), 1) self.assertEqual(mpc.run(mpc.output(a != b)), 1) with self.assertRaises(TypeError): a < b with self.assertRaises(TypeError): a <= b with self.assertRaises(TypeError): a > b with self.assertRaises(TypeError): a >= b
async def main(): if sys.argv[1:]: N = int(sys.argv[1]) else: N = 8 print('Setting input to default =', N) await mpc.start() secint = mpc.SecInt() print('Using secure integers:', secint) for n in range(2, N + 1): print(n, await mpc.output(random_derangement(n, secint))) secfxp = mpc.SecFxp() print('Using secure fixed-point numbers:', secfxp) for n in range(2, N + 1): print(n, await mpc.output(random_derangement(n, secfxp))) secpfld = mpc.SecFld(l=max(len(mpc.parties), (N - 1)).bit_length()) print('Using secure prime fields:', secpfld) for n in range(2, N + 1): print(n, await mpc.output(random_derangement(n, secpfld))) secbfld = mpc.SecFld(char2=True, l=max(len(mpc.parties), (N - 1)).bit_length()) print('Using secure binary fields:', secbfld) for n in range(2, N + 1): print(n, await mpc.output(random_derangement(n, secbfld))) await mpc.shutdown()
def test_psecfld(self): secfld = mpc.SecFld(min_order=2**16) a = secfld(1) b = secfld(0) self.assertEqual(mpc.run(mpc.output(a + b)), 1) self.assertEqual(mpc.run(mpc.output(a * b)), 0) self.assertEqual(mpc.run(mpc.output(mpc.to_bits(secfld(0), 8))), [0, 0, 0, 0, 0, 0, 0, 0]) self.assertEqual(mpc.run(mpc.output(mpc.to_bits(secfld(1), 8))), [1, 0, 0, 0, 0, 0, 0, 0]) self.assertEqual(mpc.run(mpc.output(mpc.to_bits(secfld(255), 8))), [1, 1, 1, 1, 1, 1, 1, 1]) secfld = mpc.SecFld(modulus=101) a = secfld(1) b = secfld(-1) self.assertEqual(mpc.run(mpc.output(a + b)), 0) self.assertEqual(mpc.run(mpc.output(a * b)), 100) self.assertEqual(mpc.run(mpc.output(a / b)), 100) self.assertEqual(mpc.run(mpc.output(a == b)), 0) self.assertEqual(mpc.run(mpc.output(a == -b)), 1) self.assertEqual(mpc.run(mpc.output(a**2 == b**2)), 1) self.assertEqual(mpc.run(mpc.output(a != b)), 1) a = secfld(0) b = secfld(1) self.assertEqual(mpc.run(mpc.output(a & b)), 0) self.assertEqual(mpc.run(mpc.output(a | b)), 1) self.assertEqual(mpc.run(mpc.output(a ^ b)), 1) self.assertEqual(mpc.run(mpc.output(~a)), 1) self.assertIn(mpc.run(mpc.output(mpc.random_bit(secfld))), [0, 1]) self.assertIn(mpc.run(mpc.output(mpc.random_bit(secfld, signed=True))), [-1, 1])
def test_convert(self): secint = mpc.SecInt() secint8 = mpc.SecInt(8) secint16 = mpc.SecInt(16) secfld257 = mpc.SecFld(257) secfld263 = mpc.SecFld(263) secfxp = mpc.SecFxp() secfxp16 = mpc.SecFxp(16) x = [secint8(-100), secint8(100)] y = mpc.convert(x, secint) self.assertEqual(mpc.run(mpc.output(y)), [-100, 100]) y = mpc.convert(y, secint8) self.assertEqual(mpc.run(mpc.output(y)), [-100, 100]) x = [secint16(i) for i in range(10)] y = mpc.convert(x, secfld257) self.assertEqual(mpc.run(mpc.output(y)), list(range(10))) x = [secfld257(i) for i in range(10)] y = mpc.convert(x, secfld263) self.assertEqual(mpc.run(mpc.output(y)), list(range(10))) x = [secint(-100), secint(100)] y = mpc.convert(x, secfxp) self.assertEqual(mpc.run(mpc.output(y)), [-100, 100]) y = mpc.convert(y, secint) self.assertEqual(mpc.run(mpc.output(y)), [-100, 100]) x = [secfxp16(-100.25), secfxp16(100.875)] y = mpc.convert(x, secfxp) self.assertEqual(mpc.run(mpc.output(y)), [-100.25, 100.875]) y = mpc.convert(y, secfxp16) self.assertEqual(mpc.run(mpc.output(y)), [-100.25, 100.875])
def test_secfld(self): secfld = mpc.SecFld(101) s = seclist([], secfld) self.assertEqual(s, []) s = seclist(sectype=secfld) self.assertEqual(s, []) s.append(False) s.append(secfld(100)) s[1:2] = (1, ) s += [2, 3] s.reverse() s = [5, 4] + s s.reverse() s = s + [6, 7] del s[0] s.remove(4) s[5] = 9 del s[2:4] self.assertEqual(mpc.run(mpc.output(list(s))), [1, 2, 6, 9]) secfld2 = mpc.SecFld() self.assertRaises(TypeError, seclist, [secfld(1)], secfld2) self.assertRaises(ValueError, seclist, []) self.assertRaises(TypeError, operator.add, seclist([secfld(1)]), seclist([secfld2(1)]))
def test_pickle(self): xsecfld = mpc.SecFld(256) psecfld = mpc.SecFld(257) secint = mpc.SecInt() secfxp = mpc.SecFxp() secflt = mpc.SecFlt() seccl = mpc.SecClassGroup(-23) a = seccl.group((2, 1)) # NB: mpc.transfer() calls pickle.dumps() and pickle.loads() self.assertEqual( mpc.run(mpc.output(mpc.run(mpc.transfer(xsecfld(12), senders=0)))), 12) self.assertEqual( mpc.run(mpc.output(mpc.run(mpc.transfer(psecfld(12), senders=0)))), 12) self.assertEqual( mpc.run(mpc.output(mpc.run(mpc.transfer(secint(12), senders=0)))), 12) self.assertEqual( mpc.run(mpc.output(mpc.run(mpc.transfer(secfxp(12.5), senders=0)))), 12.5) self.assertEqual( mpc.run(mpc.output(mpc.run(mpc.transfer(secflt(12.5), senders=0)))), 12.5) self.assertEqual( mpc.run( mpc.output(mpc.run(mpc.transfer(seccl((2, 1, 3)), senders=0)))), a) self.assertEqual(mpc.run(mpc.transfer(xsecfld.field(12), senders=0)), 12) self.assertEqual(mpc.run(mpc.transfer(psecfld.field(12), senders=0)), 12) self.assertEqual(mpc.run(mpc.transfer(secint.field(12), senders=0)), 12) self.assertEqual(mpc.run(mpc.transfer(secfxp.field(13), senders=0)), 13) self.assertEqual(mpc.run(mpc.transfer(xsecfld.field.modulus, 0)), xsecfld.field.modulus) x = [(xsecfld(12), psecfld(12), secint(12), secfxp(12.5), secflt(12.5), seccl((2, 1, 3))), [ xsecfld.field(12), psecfld.field(12), secint.field(12), secfxp.field(13), a ], xsecfld.field.modulus] y = mpc.run(mpc.transfer(x, senders=0)) self.assertTrue( all(mpc.run(mpc.output(a == b)) for a, b in zip(y[0], x[0]))) self.assertEqual(y[1], x[1]) self.assertEqual(y[2], x[2])
def test_psecfld(self): secfld = mpc.SecFld(min_order=2**16) a = secfld(1) b = secfld(0) self.assertEqual(mpc.run(mpc.output(a + b)), 1) self.assertEqual(mpc.run(mpc.output(a * b)), 0) c = mpc.run(mpc.output(mpc.to_bits(secfld(0), 8))) self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(1), 8))) self.assertEqual(c, [1, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 8))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1]) secfld = mpc.SecFld(modulus=101) a = secfld(1) b = secfld(-1) self.assertEqual(mpc.run(mpc.output(a + b)), 0) self.assertEqual(mpc.run(mpc.output(a * b)), 100) self.assertEqual(mpc.run(mpc.output(a / b)), 100) self.assertEqual(mpc.run(mpc.output(a == b)), 0) self.assertEqual(mpc.run(mpc.output(a == -b)), 1) self.assertEqual(mpc.run(mpc.output(a**2 == b**2)), 1) self.assertEqual(mpc.run(mpc.output(a != b)), 1) a = secfld(0) b = secfld(1) self.assertEqual(mpc.run(mpc.output(a & b)), 0) self.assertEqual(mpc.run(mpc.output(a | b)), 1) self.assertEqual(mpc.run(mpc.output(a ^ b)), 1) self.assertEqual(mpc.run(mpc.output(~a)), 1) for a, b in [(secfld(1), secfld(1)), (1, secfld(1)), (secfld(1), 1)]: with self.assertRaises(TypeError): a < b with self.assertRaises(TypeError): a <= b with self.assertRaises(TypeError): a > b with self.assertRaises(TypeError): a >= b with self.assertRaises(TypeError): a // b with self.assertRaises(TypeError): a % b with self.assertRaises(TypeError): divmod(a, b) b = mpc.random_bit(secfld) self.assertIn(mpc.run(mpc.output(b)), [0, 1]) b = mpc.random_bit(secfld, signed=True) self.assertIn(mpc.run(mpc.output(b)), [-1, 1])
def test_secfld(self): secfld = mpc.SecFld(2, char2=True) a = getrandbits(secfld, 1) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 1) secfld = mpc.SecFld(3) a = getrandbits(secfld, 1) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 1) a = mpc.run(mpc.output(randrange(secfld, 1, 3))) self.assertGreaterEqual(int(a), 1) self.assertLessEqual(int(a), 2) secfld = mpc.SecFld(256) a = getrandbits(secfld, 8) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8 - 1) a = mpc.run(mpc.output(randrange(secfld, 256))) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8 - 1) a = mpc.run(mpc.output(randint(secfld, 0, 2))) self.assertIn(a, [0, 1, 2]) x = mpc.run(mpc.output(random_unit_vector(secfld, 6))) self.assertEqual(int(sum(x)), 1) x = mpc.run(mpc.output(random_permutation(secfld, range(1, 9)))) self.assertSetEqual({a for a in range(1, 9)}, {int(a) for a in x}) x = mpc.run(mpc.output(random_derangement(secfld, range(2)))) self.assertListEqual([1, 0], [int(a) for a in x]) secfld = mpc.SecFld(257) a = getrandbits(secfld, 8) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8 - 1) a = mpc.run(mpc.output(randrange(secfld, 257))) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8) a = mpc.run(mpc.output(randint(secfld, -1, 1))) self.assertIn(a, [-1, 0, 1]) x = mpc.run(mpc.output(random_unit_vector(secfld, 6))) self.assertEqual(int(sum(x)), 1) x = mpc.run(mpc.output(random_permutation(secfld, range(1, 9)))) self.assertSetEqual({a for a in range(1, 9)}, {int(a) for a in x}) x = mpc.run(mpc.output(random_derangement(secfld, range(2)))) self.assertListEqual([1, 0], [int(a) for a in x])
def test_secfld(self): secfld = mpc.SecFld(2, char=2) a = getrandbits(secfld, 1, True) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a[0]), 0) self.assertLessEqual(int(a[0]), 1) secfld = mpc.SecFld(3) a = getrandbits(secfld, 1) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 1) a = mpc.run(mpc.output(randrange(secfld, 1, 3))) self.assertGreaterEqual(int(a), 1) self.assertLessEqual(int(a), 2) secfld = mpc.SecFld(256) a = getrandbits(secfld, 8) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8 - 1) a = mpc.run(mpc.output(randrange(secfld, 256))) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8 - 1) a = mpc.run(mpc.output(randint(secfld, 0, 2))) self.assertIn(a, [0, 1, 2]) x = mpc.run(mpc.output(random_unit_vector(secfld, 2))) self.assertEqual(int(sum(x)), 1) x = mpc.run(mpc.output(random_permutation(secfld, range(1, 9)))) self.assertSetEqual(set(map(int, x)), set(range(1, 9))) x = mpc.run(mpc.output(random_derangement(secfld, range(2)))) self.assertListEqual(list(map(int, x)), [1, 0]) secfld = mpc.SecFld(257) a = getrandbits(secfld, 8) a = mpc.run(mpc.output(a)) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8 - 1) a = mpc.run(mpc.output(randrange(secfld, 257))) self.assertGreaterEqual(int(a), 0) self.assertLessEqual(int(a), 2**8) a = mpc.run(mpc.output(randint(secfld, -1, 1))) self.assertIn(a, [-1, 0, 1]) x = mpc.run(mpc.output(random_unit_vector(secfld, 1))) self.assertEqual(int(sum(x)), 1) x = mpc.run(mpc.output(random_permutation(secfld, range(1, 9)))) self.assertSetEqual(set(map(int, x)), set(range(1, 9))) x = mpc.run(mpc.output(random_derangement(secfld, range(2)))) self.assertListEqual(list(map(int, x)), [1, 0])
def test_bsecfld(self): secfld = mpc.SecFld(char=2, min_order=2**8) a = secfld(57) b = secfld(67) c = mpc.run(mpc.output(mpc.input(a, 0))) self.assertEqual(int(c), 57) c = mpc.run(mpc.output(a - (-a))) self.assertEqual(int(c), 0) c = mpc.run(mpc.output(a * b)) self.assertEqual(int(c), 137) c = mpc.run(mpc.output(c / a)) self.assertEqual(int(c), 67) c = mpc.run(mpc.output(a**254 * a)) self.assertEqual(int(c), 1) c = mpc.run(mpc.output(a & b)) self.assertEqual(int(c), 1) c = mpc.run(mpc.output(a | b)) self.assertEqual(int(c), 123) c = mpc.run(mpc.output(a ^ b)) self.assertEqual(int(c), 122) c = mpc.run(mpc.output(~a)) self.assertEqual(int(c), 198) c = mpc.run(mpc.output(mpc.to_bits(secfld(0)))) self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(1)))) self.assertEqual(c, [1, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255)))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 1))) self.assertEqual(c, [1]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 4))) self.assertEqual(c, [1, 1, 1, 1])
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 test_QR_SG(self): for group in fg.QuadraticResidues(l=768), fg.SchnorrGroup(l=768): secgrp = mpc.SecGrp(group) g = group.generator g2 = mpc.run(mpc.output(secgrp(g) * g)) self.assertEqual(int(g), int(group.identity * g)) self.assertFalse( mpc.run(mpc.output(secgrp(g) / g != group.identity))) self.assertTrue(mpc.run(mpc.output(g * secgrp(g) == g2))) secfld = mpc.SecFld(modulus=secgrp.group.order) self.assertEqual(mpc.run(mpc.output(secgrp.repeat(g, -secfld(2)))), 1 / g2) self.assertEqual(mpc.run(mpc.output(secgrp.repeat(secgrp(g), 2))), g2) m, z = group.encode(15) self.assertEqual( mpc.run(mpc.output(secgrp.decode(secgrp(m), secgrp(z)))), 15) h = secgrp.if_else(secgrp.sectype(0), g, secgrp(g2)) self.assertEqual(mpc.run(mpc.output(h)), g2) a = secgrp(g) self.assertRaises(TypeError, operator.truediv, 2, a) self.assertRaises(TypeError, operator.add, a, a) self.assertRaises(TypeError, operator.add, g, a) self.assertRaises(TypeError, operator.neg, a) self.assertRaises(TypeError, operator.sub, a, a) self.assertRaises(TypeError, operator.sub, g, a)
def test_bsecfld(self): secfld = mpc.SecFld(char=2, min_order=2**8) a = secfld(57) b = secfld(67) self.assertEqual(int(mpc.run(mpc.output(mpc.input(a, 0)))), 57) self.assertEqual(int(mpc.run(mpc.output(+a - -a))), 0) self.assertEqual(int(mpc.run(mpc.output(a * b))), 137) self.assertEqual(int(mpc.run(mpc.output(a * b / a))), 67) self.assertEqual(int(mpc.run(mpc.output(a**254 * a))), 1) self.assertEqual(int(mpc.run(mpc.output(a & b))), 1) self.assertEqual(int(mpc.run(mpc.output(a | b))), 123) self.assertEqual(int(mpc.run(mpc.output(a ^ b))), 122) self.assertEqual(int(mpc.run(mpc.output(~a))), 198) c = mpc.run(mpc.output(mpc.to_bits(secfld(0)))) self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(1)))) self.assertEqual(c, [1, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255)))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 1))) self.assertEqual(c, [1]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 4))) self.assertEqual(c, [1, 1, 1, 1]) self.assertEqual(mpc.run(mpc.output(mpc.matrix_sub([[a]], [[a]])[0])), [0]) self.assertEqual( mpc.run(mpc.output(mpc.matrix_prod([c], [[a] * 4], True)[0])), [0]) self.assertEqual( mpc.run(mpc.output(mpc.matrix_prod([[a] * 4], [c], True)[0])), [0])
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 main(): if not mpc.args: m = 8 print('Setting input to default =', m) else: m = int(mpc.args[0]) mpc.start() secfld = mpc.SecFld(l=max(len(mpc.parties), (m - 1)).bit_length() + 1) print('Using secure fields:', secfld) for n in range(2, m + 1): print(n, mpc.run(mpc.output(random_derangement(n, secfld)))) secint = mpc.SecInt() print('Using secure integers:', secint) for n in range(2, m + 1): print(n, mpc.run(mpc.output(random_derangement(n, secint)))) secfxp = mpc.SecFxp() print('Using secure fixed-point numbers:', secfxp) for n in range(2, m + 1): print(n, mpc.run(mpc.output(random_derangement(n, secfxp)))) mpc.shutdown()
def test_bsecfld(self): secfld = mpc.SecFld(char2=True, l=8) a = secfld(57) b = secfld(67) c = mpc.run(mpc.output(mpc.input(a, 0))) self.assertEqual(c.value.value, 57) c = mpc.run(mpc.output(a - (-a))) self.assertEqual(c.value.value, 0) c = mpc.run(mpc.output(a * b)) self.assertEqual(c.value.value, 137) c = mpc.run(mpc.output(c / a)) self.assertEqual(c.value.value, 67) c = mpc.run(mpc.output(a**254 * a)) self.assertEqual(c.value.value, 1) c = mpc.run(mpc.output(a & b)) self.assertEqual(c.value.value, 1) c = mpc.run(mpc.output(a | b)) self.assertEqual(c.value.value, 123) c = mpc.run(mpc.output(a ^ b)) self.assertEqual(c.value.value, 122) c = mpc.run(mpc.output(~a)) self.assertEqual(c.value.value, 198) c = mpc.run(mpc.output(mpc.to_bits(secfld(0)))) self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(1)))) self.assertEqual(c, [1, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255)))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 1))) self.assertEqual(c, [1]) c = mpc.run(mpc.output(mpc.to_bits(secfld(255), 4))) self.assertEqual(c, [1, 1, 1, 1])
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)
def test_qsecfld(self): secfld = mpc.SecFld(7**3) a = secfld(1) b = secfld(0) self.assertEqual(mpc.run(mpc.output(+a)), 1) self.assertNotEqual(id(a), id(+a)) # NB: +a creates a copy self.assertEqual(mpc.run(mpc.output(a + b)), 1) self.assertEqual(mpc.run(mpc.output(a * b)), 0)
def test_secfld(self): secfld = mpc.SecFld() x = [secfld(0), secfld(0)] self.assertRaises(TypeError, mean, x) self.assertRaises(TypeError, variance, x) self.assertRaises(TypeError, stdev, x) self.assertRaises(TypeError, mode, x) self.assertRaises(TypeError, median, x)
async def main(): if sys.argv[1:]: N = int(sys.argv[1]) else: N = 8 print('Setting input to default =', N) await mpc.start() await xprint(N, 'integers', mpc.SecInt()) await xprint(N, 'fixed-point numbers:', mpc.SecFxp()) bound = max(len(mpc.parties) + 1, N) await xprint(N, 'prime fields', mpc.SecFld(min_order=bound)) await xprint(N, 'binary fields', mpc.SecFld(char=2, min_order=bound)) await xprint(N, 'quinary fields', mpc.SecFld(char=5, min_order=bound)) await xprint(N, 'extension fields (medium prime)', mpc.SecFld(order=11**7)) await xprint(N, 'extension fields (larger prime)', mpc.SecFld(order=1031**3)) await mpc.shutdown()
def test_secfld(self): secfld = mpc.SecFld() x = [secfld(0), secfld(0)] self.assertRaises(TypeError, mean, x) self.assertRaises(TypeError, variance, x) self.assertRaises(TypeError, stdev, x) self.assertRaises(TypeError, mode, x) self.assertRaises(TypeError, median, x) self.assertRaises(TypeError, quantiles, x) self.assertRaises(TypeError, covariance, x, x) self.assertRaises(TypeError, correlation, x, x) self.assertRaises(TypeError, linear_regression, x, x)
async def sign(self, M): """Threshold Schnorr signature generation.""" g = self.group.generator H = self.H x = self.x secgrp = mpc.SecGrp(self.group) secfld = mpc.SecFld(self.group.order) u = mpc._random(secfld) a = await secgrp.repeat_public(g, u) # a = g^u c = H(a, M) r = u + c * x r = int(await mpc.output(r)) S = c, r return S
def test_secfld(self): secfld = mpc.SecFld(101) s = seclist([], secfld) self.assertEqual(s, []) s = seclist(sectype=secfld) self.assertEqual(s, []) s.append(False) s.append(secfld(100)) s[1:2] = (1, ) s += [2, 3] s.reverse() s = [5, 4] + s s.reverse() s = s + [6, 7] del s[0] self.assertEqual(mpc.run(mpc.output(list(s))), [1, 2, 3, 4, 5, 6, 7])
async def main(): if sys.argv[1:]: n = int(sys.argv[1]) else: n = 10 print('Setting input to default =', n) secfld = mpc.SecFld(min_order=max(len(mpc.parties) + 1, n)) secint = mpc.SecInt() secfxp = mpc.SecFxp() await xprint(n, mpc.unit_vector, secfld) # NB: secret_index does not work with secfld await xprint(n, mpc.unit_vector, secint) await xprint(n, secret_index, secint) await xprint(n, mpc.unit_vector, secfxp) await xprint(n, secret_index, secfxp)
async def keygen(g): """Threshold ElGamal key generation.""" group = type(g) secgrp = mpc.SecGrp(group) n = group.order if n is not None and is_prime(n): secnum = mpc.SecFld(n) else: l = isqrt(-group.discriminant).bit_length() secnum = mpc.SecInt(l) while True: x = mpc._random(secnum) h = await secgrp.repeat_public(g, x) # g^x if h != group.identity: # NB: this branch will always be followed unless n is artificially small return x, h
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)
def test_EC(self): curves = ( fg.EllipticCurve('Ed25519'), # affine coordinates fg.EllipticCurve('Ed25519', coordinates='projective'), fg.EllipticCurve('Ed25519', coordinates='extended'), fg.EllipticCurve('Ed448', coordinates='projective'), fg.EllipticCurve('secp256k1', coordinates='projective'), fg.EllipticCurve('BN256', coordinates='projective'), fg.EllipticCurve('BN256_twist', coordinates='projective')) for group in curves: secgrp = mpc.SecGrp(group) secfld = mpc.SecFld(modulus=secgrp.group.order) g = group.generator self.assertFalse(mpc.run(mpc.output(secgrp(g) != g))) b = secgrp(g.value) self.assertEqual(mpc.run(mpc.output(b - b)), group.identity) c = secgrp(g) self.assertEqual(mpc.run(mpc.output(b)), mpc.run(mpc.output(c))) self.assertEqual(mpc.run(secgrp.repeat_public(g, -secfld(2))), g ^ -2) self.assertEqual(mpc.run(mpc.output(secfld(2) * g)), g ^ 2) self.assertEqual(mpc.run(mpc.output(2 * secgrp(g))), g ^ 2) bp4 = 4 * g sec_bp4 = 4 * secgrp(g) + secgrp.identity self.assertEqual(mpc.run(mpc.output(-sec_bp4)), -bp4) sec_bp8 = secgrp.repeat(bp4, secfld(2)) self.assertEqual(mpc.run(mpc.output(sec_bp8)), bp4 + bp4) self.assertEqual( mpc.run(mpc.output(secgrp.repeat(bp4, secfld(3)))), 3 * bp4) self.assertEqual(mpc.run(mpc.output(group.identity + b)), g) self.assertEqual(mpc.run(mpc.output(g - b)), group.identity) if group.curvename != 'BN256_twist': m, z = group.encode(42) self.assertEqual( mpc.run(mpc.output(secgrp.decode(secgrp(m), secgrp(z)))), 42) self.assertRaises(TypeError, operator.mul, sec_bp4, 13) self.assertRaises(TypeError, operator.truediv, sec_bp4, sec_bp4) self.assertRaises(TypeError, operator.truediv, 1, sec_bp4) self.assertRaises(TypeError, operator.pow, sec_bp4, 1) self.assertRaises(ValueError, secgrp, [0])
async def sign(self, M): """Threshold DSA signature generation.""" g = self.group.generator q = self.group.order H = self.H x = self.x secgrp = mpc.SecGrp(self.group) secfld = mpc.SecFld(q) while True: k = mpc._random(secfld) a = await secgrp.repeat_public(g, k) # a = g^k if a == self.group.identity: continue r = self.to_int(a) % q if r == 0: continue s = (H(M) + x * r) / k s = int(await mpc.output(s)) if s != 0: break S = r, s return S
def test_Sn(self): group = fg.SymmetricGroup(5) a = group([3, 4, 2, 1, 0]) b = a @ a secgrp = mpc.SecGrp(group) c = secgrp(a) d = a @ c self.assertEqual(mpc.run(mpc.output(d)), b) e = ~c f = e @ b self.assertEqual(mpc.run(mpc.output(f)), a) self.assertTrue(mpc.run(mpc.output(f == c))) group = fg.SymmetricGroup(11) secgrp = mpc.SecGrp(group) a = group([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]) secfld = mpc.SecFld(11) # ord(a) = 11 a7 = secgrp.repeat(a, secfld(7)) self.assertEqual(mpc.run(mpc.output(a7)), a ^ 7) a7 = secgrp.repeat_public(a, secfld(7)) self.assertEqual(mpc.run(a7), a ^ 7) a6 = a ^ 6 a12 = a6 @ a6 self.assertEqual(mpc.run(mpc.output(secgrp(a6).inverse())), a ^ 5) self.assertEqual( mpc.run(mpc.output((secgrp(a) ^ 6) @ secgrp.identity)), a6) self.assertEqual(mpc.run(mpc.output(secgrp.repeat(a6, secfld(2)))), a12) self.assertEqual( mpc.run(mpc.output(secgrp.repeat(secgrp(a), secfld(6)))), a6) p = secgrp(a) self.assertRaises(TypeError, operator.add, p, p) self.assertRaises(TypeError, operator.mul, p, p) self.assertRaises(TypeError, operator.mul, 1, p) group.is_multiplicative = True self.assertTrue(mpc.run(mpc.output(a * p == a ^ 2))) group.is_multiplicative = False self.assertRaises(ValueError, secgrp, [0, 1, 2, 3])
async def main(): parser = argparse.ArgumentParser() parser.add_argument( '-i', '--dataset', type=int, metavar='I', help=('dataset 0=synthetic (default), 1=student, 2=wine-red, ' '3=wine-white, 4=year, 5=gas-methane, 6=gas-CO, 7=higgs')) parser.add_argument('-u', '--data-url', action='store_true', default=False, help='show URL for downloading dataset I') parser.add_argument('-l', '--lambda_', type=float, metavar='L', help='regularization L>=0.0 (default=1.0)') parser.add_argument('-a', '--accuracy', type=int, metavar='A', help='accuracy A (number of fractional bits)') parser.add_argument( '-n', '--samples', type=int, metavar='N', help='number of samples in synthetic data (default=1000)') parser.add_argument( '-d', '--features', type=int, metavar='D', help='number of features in synthetic data (default=10)') parser.add_argument('-e', '--targets', type=int, metavar='E', help='number of targets in synthetic data (default=1)') parser.set_defaults(dataset=0, lambda_=1.0, accuracy=-1, samples=1000, features=10, targets=1) args = parser.parse_args() await mpc.start() if not args.dataset: range_alpha = range(4, 8) n, d, e, split = args.samples, args.features, args.targets, 0 name = 'SYNTHETIC' logging.info('Generating synthetic data') X = await synthesize_data(n, d, e) else: settings = [('student+performance', 'student-mat', 6), ('Wine+Quality', 'winequality-red', 7), ('Wine+Quality', 'winequality-white', 8), ('Yearpredictionmsd', 'YearPredictionMSD', 6), ('Gas+sensor+array+under+dynamic+gas+mixtures', 'ethylene_methane', 8), ('Gas+sensor+array+under+dynamic+gas+mixtures', 'ethylene_CO', 9), ('HIGGS', 'HIGGS', 5)] url, name, alpha = settings[args.dataset - 1] url = 'https://archive.ics.uci.edu/ml/datasets/' + url if args.data_url: print(f'URL: {url}') range_alpha = range(alpha, alpha + 1) infofile = os.path.join('data', 'regr', 'info-' + name + '.csv') logging.info(f'Loading dataset {name}') X, d, e, split = read_data(infofile) n = len(X) logging.info(f'Loaded {n} samples') print(f'dataset: {name} with {n} samples, {d} features, and {e} target(s)') print(f'regularization lambda: {args.lambda_}') # split in train set and test set if split: # fixed split X1, X2 = X[:split], X[split:] else: # random split (all parties use same rnd) rnd = await mpc.transfer(random.randrange(2**31), senders=0) X1, X2 = sklearn.model_selection.train_test_split(X, train_size=0.7, random_state=rnd) del X X1, Y1 = X1[:, :d], X1[:, d:] X2, Y2 = X2[:, :d], X2[:, d:] n1 = len(X1) d = d + 1 # add (virtual) feature column X_d = [1, ..., 1] for vertical intercept # ridge regression "in the clear" ridge = sklearn.linear_model.Ridge(alpha=args.lambda_, fit_intercept=True, copy_X=True, solver='cholesky') ridge.fit(X1, Y1) error_train_skit = rmse(Y1, ridge.predict(X1)) error_test_skit = rmse(Y2, ridge.predict(X2)) print(f'scikit train error: {error_train_skit}') print(f'scikit test error: {error_test_skit}') if args.accuracy >= 0: alpha = args.accuracy range_alpha = range(alpha, alpha + 1) for alpha in range_alpha: # accuracy parameter print('accuracy alpha:', alpha) # set parameters accordingly beta = 2**alpha lambda_ = round(args.lambda_ * beta**2) gamma = n1 * beta**2 + lambda_ secint = mpc.SecInt(gamma.bit_length() + 1) print( f'secint prime size: |q| = {secint.field.modulus.bit_length()} bits' f' (secint bit length: {secint.bit_length})') bound = round(d**(d / 2)) * gamma**d secfld = mpc.SecFld(min_order=2 * bound + 1, signed=True) print( f'secfld prime size: |p| = {secfld.field.modulus.bit_length()} bits' ) f2 = float(beta) q = secint.field.modulus logging.info( 'Transpose, scale, and create (degree 0) shares for X and Y') # enforce full size shares (mod q numbers) by adding q to each element Xt = [[int(a * f2) + q for a in col] for col in X1.transpose()] Yt = [[int(a * f2) + q for a in col] for col in Y1.transpose()] timeStart = time.process_time() logging.info('Compute A = X^T X + lambda I and B = X^T Y') AB = [] for i in range(d - 1): xi = Xt[i] for j in range(i, d - 1): xj = Xt[j] s = 0 for k in range(n1): s += xi[k] * xj[k] AB.append(s) # X_i dot X_j AB.append(sum(xi) * beta) # X_i dot X_d for j in range(e): yj = Yt[j] s = 0 for k in range(n1): s += xi[k] * yj[k] AB.append(s) # X_i dot Y_j AB.append(n1 * beta**2) # X_d dot X_d for j in range(e): AB.append(beta * sum(Yt[j])) # X_d dot Y_j del Xt, Yt AB = [secint.field(a) for a in AB] AB = await mpc._reshare(AB) timeMiddle = time.process_time() logging.info('Compute w = A^-1 B') # convert secint to secfld AB = [secint(a) for a in AB] AB = mpc.convert(AB, secfld) # extract A and B from the AB array A = [[None] * d for _ in range(d)] B = [[None] * e for _ in range(d)] index = 0 for i in range(d): A[i][i] = AB[index] + lambda_ index += 1 for j in range(i + 1, d): A[i][j] = A[j][i] = AB[index] index += 1 for j in range(e): B[i][j] = AB[index] index += 1 # solve A w = B w_det = linear_solve(A, B) w_det = await mpc.output(w_det) w_det = list(map(int, w_det)) w = np.reshape(w_det[:-1], (d, e)) w /= w_det[-1] timeEnd = time.process_time() logging.info(f'Total time {timeEnd - timeStart} = ' f'A and B in {timeMiddle - timeStart} + ' f'A^-1 B in {timeEnd - timeMiddle} seconds') error_train_mpyc = rmse(Y1, np.dot(X1, w[:-1]) + w[-1]) error_test_mpyc = rmse(Y2, np.dot(X2, w[:-1]) + w[-1]) print(f'MPyC train error: {error_train_mpyc}') print(f'MPyC test error: {error_test_mpyc}') print( f'relative train error: {(error_train_mpyc - error_train_skit) / error_train_skit}' ) print( f'relative test error: {(error_test_mpyc - error_test_skit) / error_test_skit}' ) await mpc.shutdown()