def protocol(rt): print "Starting protocol" Zp = GF(11) a, b, c = rt.prss_share([1, 2, 3], Zp, 0) x, y, z = rt.prss_share([1, 2, 3], Zp, 1) a_b = rt.open(rt.convert_bit_share(a, GF256)) b_b = rt.open(rt.convert_bit_share(b, GF256)) c_b = rt.open(rt.convert_bit_share(c, GF256)) x_b = rt.open(rt.convert_bit_share(x, GF256)) y_b = rt.open(rt.convert_bit_share(y, GF256)) z_b = rt.open(rt.convert_bit_share(z, GF256)) def check(result, variable, expected): if result == expected: print "%s: %s (correct)" % (variable, result) else: print "%s: %s (incorrect, expected %d)" \ % (variable, result, expected) a_b.addCallback(check, "a_b", GF256(0)) b_b.addCallback(check, "b_b", GF256(0)) c_b.addCallback(check, "c_b", GF256(0)) x_b.addCallback(check, "x_b", GF256(1)) y_b.addCallback(check, "y_b", GF256(1)) z_b.addCallback(check, "z_b", GF256(1)) rt.wait_for(a_b, b_b, c_b, x_b, y_b, z_b)
def test_add_macs_produces_correct_sharing(self, runtime): # TODO: Here we use the open method of the BeDOZa runtime in # order to verify the macs of the generated full share. In # order to be more unit testish, this test should use its own # way of verifying these. p = 17 Zp = GF(p) secret = 6 random = Random(283883) paillier_random = Random(random.getrandbits(128)) paillier = ModifiedPaillier(runtime, random) add_macs_random = Random(random.getrandbits(128)) shares_random = Random(random.getrandbits(128)) shares = [] shares.append( partial_share(shares_random, runtime, Zp, secret, paillier=paillier)) shares.append( partial_share(shares_random, runtime, Zp, secret + 1, paillier=paillier)) shares.append( partial_share(shares_random, runtime, Zp, secret + 2, paillier=paillier)) shares.append( partial_share(shares_random, runtime, Zp, secret + 3, paillier=paillier)) bits_in_p = 5 u_bound = 2**(4 * bits_in_p) alpha = 15 zs = add_macs(runtime, Zp, u_bound, alpha, add_macs_random, paillier, shares) def verify(open_shares): inx = secret for open_share in open_shares: self.assertEquals(inx, open_share.value) inx += 1 opened_shares = [] for s in zs: opened_shares.append(runtime.open(s)) d = gather_shares(opened_shares) d.addCallback(verify) return d
def __init__(self, runtime, security_parameter, p, random): assert p > 1 self.random = random # TODO: Generate Paillier cipher with N_i sufficiently larger than p self.runtime = runtime self.p = p self.Zp = GF(p) self.k = self._bit_length_of(p) self.security_parameter = security_parameter self.u_bound = 2**(self.security_parameter + 4 * self.k) self.zk_random = Random(self.random.getrandbits(128)) paillier_random = Random(self.random.getrandbits(128)) alpha_random = Random(self.random.getrandbits(128)) self.paillier = ModifiedPaillier(runtime, paillier_random) # Debug output. #print "n_%d**2:%d" % (runtime.id, self.paillier.pubkey['n_square']) #print "n_%d:%d" % (runtime.id, self.paillier.pubkey['n']) #print "n_%d bitlength: %d" % \ # (runtime.id, self._bit_length_of(self.paillier.pubkey['n'])) #self.Zp = GF(p) #self.Zn2 = GF(self.paillier.pubkey['n_square']) #self.alpha = self.Zp(self.random.randint(0, p - 1)) self.alpha = alpha_random.randint(0, p - 1) self.n2 = runtime.players[runtime.id].pubkey['n_square']
def test_generate_triples_generates_correct_triples(self, runtime): p = 17 Zp = GF(p) random = Random(574566 + runtime.id) triple_generator = TripleGenerator(runtime, self.security_parameter, p, random) triples = triple_generator._generate_triples(10) def check((a, b, c)): self.assertEquals(c, a * b) def open(triple): d1 = runtime.open(triple.a) d2 = runtime.open(triple.b) d3 = runtime.open(triple.c) d = gatherResults([d1, d2, d3]) runtime.schedule_callback(d, check) return d for triple in triples: runtime.schedule_callback(triple, open) return gatherResults(triples)
def test_mul_same_player_inputs_and_receives(self, runtime): p = 17 random = Random(283883) triple_generator = TripleGenerator(runtime, self.security_parameter, p, random) Zp = GF(p) ais = [Zp(6), Zp(6), Zp(6), Zp(6)] b2 = Zp(7) cs = [] for ai in ais: cs.append(triple_generator.paillier.encrypt(b2.value, 2)) n = len(ais) r1 = triple_generator._mul(2, 2, n, ais, cs) def check(shares): for share in shares: if runtime.id == 2: self.assertEquals(share.value, 8) return True r1.addCallback(check) return r1
def eval_poly(runtime): print "Starting protocol" start_time = time() modulus = find_prime(2**65, blum=True) Zp = GF(modulus) # In this example we just let Player 1 share the input values. if runtime.id == 1: x = runtime.shamir_share([1], Zp, 17) a = runtime.shamir_share([1], Zp, 42) b = runtime.shamir_share([1], Zp, -5) c = runtime.shamir_share([1], Zp, 87) else: x = runtime.shamir_share([1], Zp) a = runtime.shamir_share([1], Zp) b = runtime.shamir_share([1], Zp) c = runtime.shamir_share([1], Zp) # Evaluate the polynomial. p = a * (x * x) + b * x + c sign = (p < 0) * -1 + (p > 0) * 1 output = runtime.open(sign) output.addCallback(done, start_time, runtime)
def setUp(self): RuntimeTestCase.setUp(self) self.Zp = GF(17) bits_in_p = 5 self.security_parameter = 32 self.u_bound = 2**(self.security_parameter + 4 * bits_in_p) self.alpha = 15
def test_share_protocol_multi(self, runtime): p, k = 17, 5 Zp = GF(p) random = Random(345453 + runtime.id) elms = [Zp(runtime.id), Zp(runtime.id * 3)] paillier_random = Random(random.getrandbits(128)) zk_random = Random(random.getrandbits(128)) paillier = ModifiedPaillier(runtime, paillier_random) partial_shares = generate_partial_share_contents( elms, runtime, paillier, k, zk_random) def decrypt(share_contents): self.assertEquals(2, len(share_contents)) decrypted_shares = [ paillier.decrypt(share_contents[i].enc_shares[runtime.id - 1]) for i in range(2) ] decrypted_shares = [ _convolute(runtime, decrypted_shares[i]) for i in range(2) ] def test_sum(vals, should_be): self.assertEquals([Zp(e) for e in should_be], vals) runtime.schedule_callback(decrypted_shares[0], test_sum, [1, 2, 3]) runtime.schedule_callback(decrypted_shares[1], test_sum, [3, 6, 9]) runtime.schedule_callback(partial_shares, decrypt) return partial_shares
def test_encrypted_random_real_shares_open_correctly(self, runtime): random = Random(3423993) modulus = 17 Zp = GF(modulus) bits_in_p = 5 u_bound = 2**(4 * bits_in_p) alpha = 15 paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128))) share_random = Random(random.getrandbits(128)) gen = TestShareGenerator(Zp, runtime, share_random, paillier, u_bound, alpha) shares = gen.generate_random_shares(7) expected_result = [9, 16, 7, 12, 3, 5, 6] results = [] for inx, share in enumerate(shares): def check(v, expected_result): self.assertEquals(expected_result, v) r = runtime.open(share) results.append(r) runtime.schedule_callback(r, check, expected_result[inx]) return gather_shares(results)
def test_send_two_senders_in_parallel(self, runtime): """Test of send a value.""" self.Zp = GF(6277101735386680763835789423176059013767194773182842284081) def check(ls): for s, x in ls: self.assertEquals(int(x), 42) return ls value = 42 receivers = [2, 3] if 1 == runtime.id: d1 = runtime.broadcast([1], receivers, str(value)) else: d1 = runtime.broadcast([1], receivers) if 2 == runtime.id: d2 = runtime.broadcast([2], [3], str(value)) else: d2 = runtime.broadcast([2], [3]) ds = [d1] if [] != d2: ds.append(d2) dls = DeferredList(ds) dls.addCallback(check) return dls
def test_encrypted_random_shares_decrypt_correctly(self, runtime): random = Random(3423993) modulus = 17 Zp = GF(modulus) paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128))) shares = self._partial_random_shares(random, runtime, Zp, 7, paillier=paillier) expected_result = [9, 16, 7, 12, 3, 5, 6] for inx, share in enumerate(shares): def decrypt(share, expected_result): decrypted_share = paillier.decrypt( share.enc_shares[runtime.id - 1]) decrypted_shares = _convolute(runtime, decrypted_share) def test_sum(vals, expected_result): v = Zp(sum(vals)) self.assertEquals(expected_result, v) runtime.schedule_callback(decrypted_shares, test_sum, expected_result) runtime.schedule_callback(share, decrypt, expected_result[inx]) return shares
def test_shares_have_correct_type(self, runtime): Zp = GF(23) share = partial_share(Random(23499), runtime, Zp, 7) def test(share): self.assertEquals(Zp, share.value.field) runtime.schedule_callback(share, test) return share
def test_convolute_field_element(self, runtime): Zp = GF(17) res = _convolute_gf_elm(runtime, Zp(runtime.id)) def verify(result): self.assertEquals(runtime.players.keys(), result) runtime.schedule_callback(res, verify) return res
def test_vec_mul_E_is_correct(self): s, prover_id, k, Zn = 5, 1, 0, GF(17) c = [None] * s y = [Zn(i) for i in range(1, 6)] zk = ZKProof(s, prover_id, k, RuntimeStub(), c) zk.e = [1, 0, 1, 1, 0] x = [1, 2, 0, 1, 0] x_mul_E = zk._vec_mul_E(x) self.assertEquals([v for v in [1, 2, 1, 4, 2, 1, 1, 0, 0]], x_mul_E)
def __init__(self, runtime): # Save the Runtime for later use self.runtime = runtime # This is the value we will use in the protocol. self.millions = rand.randint(1, 200) print "I am Millionaire %d and I am worth %d millions." \ % (runtime.id, self.millions) # For the comparison protocol to work, we need a field modulus # bigger than 2**(l+1) + 2**(l+k+1), where the bit length of # the input numbers is l and k is the security parameter. # Further more, the prime must be a Blum prime (a prime p such # that p % 4 == 3 holds). The find_prime function lets us find # a suitable prime. l = runtime.options.bit_length k = runtime.options.security_parameter Zp = GF(find_prime(2**(l + 1) + 2**(l + k + 1), blum=True)) # We must secret share our input with the other parties. They # will do the same and we end up with three variables m1, m2, m3 = runtime.shamir_share([1, 2, 3], Zp, self.millions) # Now that everybody has secret shared their inputs we can # compare them. We compare the worth of the first millionaire # with the two others, and compare those two millionaires with # each other. m1_ge_m2 = m1 >= m2 m1_ge_m3 = m1 >= m3 m2_ge_m3 = m2 >= m3 # The results are secret shared, so we must open them before # we can do anything usefull with them. open_m1_ge_m2 = runtime.open(m1_ge_m2) open_m1_ge_m3 = runtime.open(m1_ge_m3) open_m2_ge_m3 = runtime.open(m2_ge_m3) # We will now gather the results and call the # self.results_ready method when they have all been received. results = gather_shares([open_m1_ge_m2, open_m1_ge_m3, open_m2_ge_m3]) results.addCallback(self.results_ready) # We can add more callbacks to the callback chain in results. # These are called in sequence when self.results_ready is # finished. The first callback acts like a barrier and makes # all players wait on each other. # # The callbacks are always called with an argument equal to # the return value of the preceeding callback. We do not need # the argument (which is None since self.results_ready does # not return anything), so we throw it away using a lambda # expressions which ignores its first argument. runtime.schedule_callback(results, lambda _: runtime.synchronize()) # The next callback shuts the runtime down, killing the # connections between the players. runtime.schedule_callback(results, lambda _: runtime.shutdown())
def test_not_hyper(self): """Check a non-hyper-invertible matrix.""" Zp = GF(11) # This is an invertible matrix, but it is not hyper-invertible # since none of the three the upper 2x2 matrices are # invertible. m = Matrix([[Zp(2), Zp(3), Zp(4)], [Zp(4), Zp(6), Zp(9)], [Zp(3), Zp(5), Zp(8)]]) self.assertFalse(self.is_hyper(m))
def eval_poly(runtime): print "Starting protocol" start_time = time() Zp = GF( 57896044618658097711785492504343953926634992332820282019728792003956564819949 ) # Gx = 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad245a # Gy = 0x20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9 # In this example we just let Player 1 share the input values. if runtime.id == 1: x = runtime.shamir_share( [1], Zp, 0x656773b68b20e9d9b4332081b21898bae504c1088a8b28595c4704a301b8f722 ) # x1 a = runtime.shamir_share( [1], Zp, 0x13b5d4c07675266c9d07f91b07d48ef0fdbe9b4e24e2992304901ac2a97b59f1 ) # y1 b = runtime.shamir_share( [1], Zp, 0x5a1e4aff484be0404f28de08a82f7b32271260b5c803963991c3fa7376c2de77 ) # x2 c = runtime.shamir_share( [1], Zp, 0x41f6d23c8f62c91f9ec4f6d64dd0994c9c2441c1ed65cc4e1c97e9d68a9de169 ) # y2 else: x = runtime.shamir_share([1], Zp) a = runtime.shamir_share([1], Zp) b = runtime.shamir_share([1], Zp) c = runtime.shamir_share([1], Zp) # x: 7ff0a38a625bbb21d7da773abf0f2af4bcebc4846898943bde295589d0c29e09 # y: 5b7ac2e700968c81b0af36b611061653b4d916082cac0012295ddcf9c1954641 # Evaluate the polynomial. # p = a * (x * x) + b * x + c lam = divide(c - a, b - x, 64) # x3 = (lam * lam) - x - b # y3 = lam * (x - x3) - a output1 = runtime.open(lam) # output2 = runtime.open(y3) output1.addCallback(done, start_time, runtime) # output2.addCallback(done, start_time, runtime) runtime.wait_for(output1)
def main(): # Parse command line arguments. parser = OptionParser(usage=__doc__) parser.add_option("--modulus", help="lower limit for modulus (can be an expression)") parser.set_defaults(modulus=2**65) Runtime.add_options(parser) options, args = parser.parse_args() if len(args) == 2: number = int(args[1]) else: number = None if len(args) == 0: parser.error("you must specify a config file") Zp = GF(find_prime(options.modulus, blum=True)) # Load configuration file. id, players = load_config(args[0]) runtime_class = make_runtime_class(mixins=[ComparisonToft07Mixin]) pre_runtime = create_runtime(id, players, 1, options, runtime_class) def run(runtime): print "Connected." # Players 1 and 2 are doing a sharing over the field Zp. # Our input is number (None for other players). if runtime.id == 3: print "I have no number" else: print "My number: %d." % number (x, y) = runtime.shamir_share([1, 2], Zp, number) # Do the secret computation. result = divide(x, y, 10) # 10 bits for the result. # Now open the result so we can see it. dprint("The two numbers divided are: %s", runtime.open(result)) result.addCallback(lambda _: runtime.shutdown()) pre_runtime.addCallback(run) # Start the Twisted event loop. reactor.run()
def test_shares_are_additive(self, runtime): secret = 7 share = partial_share(Random(34993), runtime, GF(23), secret) def convolute(share): values = _convolute_gf_elm(runtime, share.value) def test_sum(vals): self.assertEquals(secret, sum(vals)) runtime.schedule_callback(values, test_sum) runtime.schedule_callback(share, convolute) return share
def test_mul_computes_correct_result(self, runtime): p = 17 random = Random(283883) triple_generator = TripleGenerator(runtime, 32, p, random) Zp = GF(p) ais = [Zp(6), Zp(6), Zp(6), Zp(6)] b2 = Zp(7) cs = [] for ai in ais: cs.append(triple_generator.paillier.encrypt(b2.value, 2)) n = len(ais) if runtime.id == 1: r1 = triple_generator._mul(1, 2, n, ais, cs) def check1(shares): for share in shares: pc = tuple(runtime.program_counter) runtime.protocols[2].sendData(pc, TEXT, str(share.value)) return True r1.addCallback(check1) return r1 else: r1 = triple_generator._mul(1, 2, n) def check(shares): deferreds = [] for share in shares: if runtime.id == 2: def check_additivity(zi, zj): self.assertEquals((Zp(long(zi)) + zj).value, 8) return None d = Deferred() d.addCallback(check_additivity, share.value) runtime._expect_data(1, TEXT, d) deferreds.append(d) else: self.assertEquals(share.value, 0) return gatherResults(deferreds) r1.addCallback(check) return r1
def test_send(self, runtime): """Test of send a value.""" self.Zp = GF(6277101735386680763835789423176059013767194773182842284081) value = 42 receivers = [2, 3] if 1 == runtime.id: d = runtime.broadcast([1], receivers, str(value)) else: d = runtime.broadcast([1], receivers) def check(x): self.assertEquals(int(x), 42) d.addCallback(check) return d
def test_fullmul_encrypted_values_are_the_same_as_the_share(self, runtime): p = 17 Zp = GF(p) random = Random(283883) triple_generator = TripleGenerator(runtime, self.security_parameter, p, random) paillier = triple_generator.paillier share_as = [] share_bs = [] share_as.append( partial_share(random, runtime, GF(p), 6, paillier=paillier)) share_bs.append( partial_share(random, runtime, GF(p), 7, paillier=paillier)) share_as.append( partial_share(random, runtime, GF(p), 5, paillier=paillier)) share_bs.append( partial_share(random, runtime, GF(p), 4, paillier=paillier)) share_as.append( partial_share(random, runtime, GF(p), 2, paillier=paillier)) share_bs.append( partial_share(random, runtime, GF(p), 3, paillier=paillier)) share_zs = triple_generator._full_mul(share_as, share_bs) def check(shares): all_enc_shares = [] for share in shares: def test_enc(enc_shares, value): all_the_same, zi_enc = reduce( lambda x, y: (x[0] and x[1] == y, y), enc_shares, (True, enc_shares[0])) zi_enc = triple_generator.paillier.decrypt(zi_enc) self.assertEquals(value, Zp(zi_enc)) return True for inx, enc_share in enumerate(share.enc_shares): d = _convolute(runtime, enc_share) if runtime.id == inx + 1: d.addCallback(test_enc, share.value) all_enc_shares.append(d) return gatherResults(all_enc_shares) d = gatherResults(share_zs) d.addCallback(check) return d
def test_fullmul_computes_the_correct_result(self, runtime): p = 17 Zp = GF(p) random = Random(283883) triple_generator = TripleGenerator(runtime, self.security_parameter, p, random) paillier = triple_generator.paillier share_as = [] share_bs = [] share_as.append( partial_share(random, runtime, GF(p), 6, paillier=paillier)) share_bs.append( partial_share(random, runtime, GF(p), 7, paillier=paillier)) share_as.append( partial_share(random, runtime, GF(p), 5, paillier=paillier)) share_bs.append( partial_share(random, runtime, GF(p), 4, paillier=paillier)) share_as.append( partial_share(random, runtime, GF(p), 2, paillier=paillier)) share_bs.append( partial_share(random, runtime, GF(p), 3, paillier=paillier)) share_zs = triple_generator._full_mul(share_as, share_bs) def check(shares): def test_sum(ls): self.assertEquals(8, Zp(sum(ls[0]))) self.assertEquals(3, Zp(sum(ls[1]))) self.assertEquals(6, Zp(sum(ls[2]))) values = [] for share in shares: value = _convolute(runtime, share.value.value) values.append(value) d = gatherResults(values) runtime.schedule_callback(d, test_sum) return d d = gatherResults(share_zs) d.addCallback(check) return d
def test_send_multiple_senders_in_one_burst(self, runtime): """Test of send a value.""" self.Zp = GF(6277101735386680763835789423176059013767194773182842284081) value = 42 if 1 == runtime.id: value = 7 if 1 == runtime.id or 3 == runtime.id: ds = runtime.broadcast([1, 3], [2], str(value)) if 2 == runtime.id: ds = runtime.broadcast([1, 3], [2]) dls = DeferredList(ds) def check(ls): self.assertEquals(int(ls[0][1]), 7) self.assertEquals(int(ls[1][1]), 42) return ls dls.addCallback(check) return dls return None
def test_encrypted_real_share_open_correctly(self, runtime): random = Random(3423993) modulus = 17 Zp = GF(modulus) bits_in_p = 5 u_bound = 2**(4 * bits_in_p) alpha = 15 paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128))) share_random = Random(random.getrandbits(128)) gen = ShareGenerator(Zp, runtime, share_random, paillier, u_bound, alpha) share = gen.generate_share(7) def check(v): self.assertEquals(7, v) r = runtime.open(share) runtime.schedule_callback(r, check) return r
def test_encrypted_shares_decrypt_correctly(self, runtime): random = Random(3423993) modulus = 17 secret = 7 paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128))) share = partial_share(Random(random.getrandbits(128)), runtime, GF(modulus), secret, paillier=paillier) def decrypt(share): decrypted_share = paillier.decrypt(share.enc_shares[runtime.id - 1]) decrypted_shares = _convolute(runtime, decrypted_share) def test_sum(vals): self.assertEquals(secret, sum(vals) % modulus) runtime.schedule_callback(decrypted_shares, test_sum) runtime.schedule_callback(share, decrypt) return share
def test_generate_triple_candidates_generates_correct_triples( self, runtime): p = 17 Zp = GF(p) random = Random(283883) triple_generator = TripleGenerator(runtime, self.security_parameter, p, random) triples = triple_generator._generate_triple_candidates(5) def verify(triples): for inx in xrange(len(triples) // 3): self.assertEquals(triples[10 + inx], triples[inx] * triples[5 + inx]) opened_shares = [] for s in triples: opened_shares.append(runtime.open(s)) d = gather_shares(opened_shares) d.addCallback(verify) return d
def test_share_protocol_single(self, runtime): p, k = 17, 5 Zp = GF(p) random = Random(3455433 + runtime.id) elms = [Zp(runtime.id)] paillier_random = Random(random.getrandbits(128)) zk_random = Random(random.getrandbits(128)) paillier = ModifiedPaillier(runtime, paillier_random) partial_shares = generate_partial_share_contents( elms, runtime, paillier, k, zk_random) def decrypt(share_contents): self.assertEquals(1, len(share_contents)) decrypted_share = paillier.decrypt( share_contents[0].enc_shares[runtime.id - 1]) decrypted_shares = _convolute(runtime, decrypted_share) def test_sum(vals): self.assertEquals([Zp(e) for e in [1, 2, 3]], vals) runtime.schedule_callback(decrypted_shares, test_sum) runtime.schedule_callback(partial_shares, decrypt) return partial_shares
import viff.reactor viff.reactor.install() from twisted.internet import reactor from twisted.internet.defer import gatherResults from viff.math.field import GF from viff.runtime import create_runtime from viff.config import load_config from viff.utils.util import dprint id, players = load_config(sys.argv[1]) print "I am player %d" % id Z31 = GF(31) def protocol(rt): elements = [rt.open(rt.prss_share_random(Z31)) for _ in range(10)] result = gatherResults(elements) dprint("bits: %s", result) rt.wait_for(result) pre_runtime = create_runtime(id, players, (len(players) - 1) // 2) pre_runtime.addCallback(protocol) reactor.run()
import sys import viff.reactor viff.reactor.install() from twisted.internet import reactor from viff.math.field import GF from viff.runtime import create_runtime from viff.runtimes.paillier import PaillierRuntime from viff.config import load_config from viff.utils.util import dprint, find_prime id, players = load_config(sys.argv[1]) Zp = GF(find_prime(2**64)) input = int(sys.argv[2]) print "I am player %d and will input %s" % (id, input) def protocol(runtime): print "-" * 64 print "Program started" print a, b = runtime.share([1, 2], Zp, input) c = a * b dprint("a%d: %s", runtime.id, a) dprint("b%d: %s", runtime.id, b)