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_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])
async def random_unit_vector(n): # returns list of n secint elements await mpc.returnType(secint, n) # set return type of this MPyC coroutine if n == 1: return [secint(1)] b = mpc.random_bit(secint) # pick one random bit if n>=2 x = random_unit_vector((n + 1) // 2) # recursive call with m=(n+1)//2 if n % 2 == 0: y = mpc.scalar_mul(b, x) # y = [0]*m or y = x return y + mpc.vector_sub(x, y) # [0]*m + x or x + [0]*m elif await mpc.eq_public(b * x[0], 1): # reject if b=1 and x[0]=1 return random_unit_vector(n) # start over else: y = mpc.scalar_mul(b, x[1:]) # y = [0]*m or y = x[1:] return x[:1] + y + mpc.vector_sub( x[1:], y) # [x[0]] + ([0]*m + x[1:] or [0]*m + x[1:])
async def random_unit_vector(n, sectype): """Random permutation of [sectype(1)] + [sectype(0) for i in range(n-1)].""" await mpc.returnType((sectype, True), n) if n == 1: return [sectype(1)] b = mpc.random_bit(sectype) x = random_unit_vector((n + 1) // 2, sectype) if n % 2 == 0: y = mpc.scalar_mul(b, x) return y + mpc.vector_sub(x, y) elif await mpc.eq_public(b * x[0], 1): return random_unit_vector(n, sectype) else: y = mpc.scalar_mul(b, x[1:]) return x[:1] + y + mpc.vector_sub(x[1:], y)
def test_secint(self): secint = mpc.SecInt() a = secint(12) b = secint(13) self.assertEqual(mpc.run(mpc.output(mpc.input(a, 0))), 12) self.assertEqual(mpc.run(mpc.output(mpc.input([a, b], 0))), [12, 13]) self.assertEqual(mpc.run(mpc.output(-a)), -12) self.assertEqual(mpc.run(mpc.output(+a)), 12) self.assertNotEqual(id(a), id(+a)) # NB: +a creates a copy self.assertEqual(mpc.run(mpc.output(a * b + b)), 12 * 13 + 13) self.assertEqual(mpc.run(mpc.output((a * b) / b)), 12) self.assertEqual(mpc.run(mpc.output((a * b) / 12)), 13) self.assertEqual(mpc.run(mpc.output(a**11 * a**-6 * a**-5)), 1) self.assertEqual(mpc.run(mpc.output(a**(secint.field.modulus - 1))), 1) c = mpc.to_bits( mpc.SecInt(0)(0)) # mpc.output() only works for nonempty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(mpc.SecInt(1)(0)))) self.assertEqual(c, [0]) c = mpc.run(mpc.output(mpc.to_bits(mpc.SecInt(1)(1)))) self.assertEqual(c, [1]) c = mpc.to_bits(secint(0), 0) # mpc.output() only works for nonempty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(secint(0)))) self.assertEqual(c, [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(1)))) self.assertEqual(c, [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(8113)))) self.assertEqual(c, [ 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(2**31 - 1)))) self.assertEqual(c, [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(2**31 - 1), 16))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secint(-1), 8))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secint(-2**31)))) self.assertEqual(c, [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(-2**31), 16))) self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.from_bits(mpc.to_bits(secint(8113))))) self.assertEqual(c, 8113) c = mpc.run(mpc.output(mpc.from_bits(mpc.to_bits(secint(2**31 - 1))))) self.assertEqual(c, 2**31 - 1) # TODO: from_bits for negative numbers # c = mpc.run(mpc.output(mpc.from_bits(mpc.to_bits(secint(-2**31))))) # self.assertEqual(c, -2**31) self.assertFalse(mpc.run(mpc.eq_public(secint(4), secint(2)))) self.assertTrue(mpc.run(mpc.eq_public(secint(42), secint(42)))) self.assertEqual(mpc.run(mpc.output(abs(secint(1)))), 1) self.assertEqual(mpc.run(mpc.output(secint(-2**31) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(-2**31 + 1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(-1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(0) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(2**31 - 1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(5) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(-5) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(50) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(50) % 4)), 2) self.assertEqual(mpc.run(mpc.output(secint(50) % 32)), 18) self.assertEqual(mpc.run(mpc.output(secint(-50) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(-50) % 32)), 14) self.assertEqual(mpc.run(mpc.output(secint(5) // 2)), 2) self.assertEqual(mpc.run(mpc.output(secint(50) // 2)), 25) self.assertEqual(mpc.run(mpc.output(secint(50) // 4)), 12) self.assertEqual(mpc.run(mpc.output(secint(11) << 3)), 88) self.assertEqual(mpc.run(mpc.output(secint(-11) << 3)), -88) self.assertEqual(mpc.run(mpc.output(secint(70) >> 2)), 17) self.assertEqual(mpc.run(mpc.output(secint(-70) >> 2)), -18) self.assertEqual(mpc.run(mpc.output(secint(50) % 17)), 16) self.assertEqual(mpc.run(mpc.output(secint(177) % 17)), 7) self.assertEqual(mpc.run(mpc.output(secint(-50) % 17)), 1) self.assertEqual(mpc.run(mpc.output(secint(-177) % 17)), 10) self.assertEqual(mpc.run(mpc.output(secint(3)**0)), 1) self.assertEqual(mpc.run(mpc.output(secint(3)**18)), 3**18) self.assertIn(mpc.run(mpc.output(mpc.random_bit(secint))), [0, 1]) self.assertIn(mpc.run(mpc.output(mpc.random_bit(secint, signed=True))), [-1, 1])
def test_secint(self): secint = mpc.SecInt() a = secint(12) b = secint(13) c = mpc.run(mpc.output(mpc.input(a, 0))) self.assertEqual(c, 12) c = mpc.run(mpc.output(mpc.input([a, b], 0))) self.assertEqual(c, [12, 13]) c = mpc.run(mpc.output(a * b + b)) self.assertEqual(c, 12 * 13 + 13) c = mpc.run(mpc.output((a * b) / b)) self.assertEqual(c, 12) c = mpc.run(mpc.output((a * b) / 12)) self.assertEqual(c, 13) c = mpc.run(mpc.output(a**11 * a**(-6) * a**(-5))) self.assertEqual(c, 1) c = mpc.run(mpc.output(a**(secint.field.modulus - 1))) self.assertEqual(c, 1) self.assertEqual(mpc.run(mpc.output(secint(12)**73)), 12**73) c = mpc.to_bits( mpc.SecInt(0)(0)) # mpc.output() only works for non-empty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(mpc.SecInt(1)(0)))) self.assertEqual(c, [0]) c = mpc.run(mpc.output(mpc.to_bits(mpc.SecInt(1)(1)))) self.assertEqual(c, [1]) c = mpc.to_bits(secint(0), 0) # mpc.output() only works for non-empty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(secint(0)))) self.assertEqual(c, [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(1)))) self.assertEqual(c, [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(8113)))) self.assertEqual(c, [ 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(2**31 - 1)))) self.assertEqual(c, [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(2**31 - 1), 16))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secint(-1), 8))) self.assertEqual(c, [1, 1, 1, 1, 1, 1, 1, 1]) c = mpc.run(mpc.output(mpc.to_bits(secint(-2**31)))) self.assertEqual(c, [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ]) c = mpc.run(mpc.output(mpc.to_bits(secint(-2**31), 16))) self.assertEqual(c, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) c = mpc.run(mpc.output(mpc.from_bits(mpc.to_bits(secint(8113))))) self.assertEqual(c, 8113) c = mpc.run(mpc.output(mpc.from_bits(mpc.to_bits(secint(2**31 - 1))))) self.assertEqual(c, 2**31 - 1) # TODO: from_bits for negative numbers # c = mpc.run(mpc.output(mpc.from_bits(mpc.to_bits(secint(-2**31))))) # self.assertEqual(c, -2**31) self.assertEqual(mpc.run(mpc.output(secint(-2**31) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(-2**31 + 1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(-1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(0) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(2**31 - 1) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(5) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(-5) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secint(50) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(50) % 4)), 2) self.assertEqual(mpc.run(mpc.output(secint(50) % 32)), 18) self.assertEqual(mpc.run(mpc.output(secint(-50) % 2)), 0) self.assertEqual(mpc.run(mpc.output(secint(-50) % 32)), 14) self.assertEqual(mpc.run(mpc.output(secint(5) // 2)), 2) self.assertEqual(mpc.run(mpc.output(secint(50) // 2)), 25) self.assertEqual(mpc.run(mpc.output(secint(50) // 4)), 12) self.assertEqual(mpc.run(mpc.output(secint(11) << 3)), 88) self.assertEqual(mpc.run(mpc.output(secint(-11) << 3)), -88) self.assertEqual(mpc.run(mpc.output(secint(70) >> 2)), 17) self.assertEqual(mpc.run(mpc.output(secint(-70) >> 2)), -18) self.assertEqual(mpc.run(mpc.output(secint(50) % 17)), 16) self.assertEqual(mpc.run(mpc.output(secint(177) % 17)), 7) self.assertEqual(mpc.run(mpc.output(secint(-50) % 17)), 1) self.assertEqual(mpc.run(mpc.output(secint(-177) % 17)), 10) self.assertEqual(mpc.run(mpc.output(secint(3)**73)), 3**73) b = mpc.random_bit(secint) self.assertIn(mpc.run(mpc.output(b)), [0, 1]) b = mpc.random_bit(secint, signed=True) self.assertIn(mpc.run(mpc.output(b)), [-1, 1])
# Generate two different noise values (from the same distribution) # Each party will end up using one of the two in an oblivious manner # TODO: Server explanation blabla?? noise0 = float(np.random.normal(0, SIGMA1)) noise1 = float(np.random.normal(0, SIGMA1)) # 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