def assert_positive(self, bl): """ Assert that the present VcShare represents a positive value, that is, a value in [0,2^bl] with bl the given bit length. """ if qap != None: rt = self.sh.runtime bits = rt.bit_decompose(self.sh, bl) # small optimization: instead of making vc shares for everything, we do things explicitly via the secret shares rt.vc_counter[-1] += 1 sid = "/".join(map(str, rt.vc_counter[:])) def printwires(vals): for (ix, val) in enumerate(vals): print >> qapv, sid + "b" + str(ix) + ":", val.value qapv.flush() gather_shares(bits).addCallback(printwires) for i in range(bl): print >> qap, "1", sid + "b" + str(i), "* 1", self.constname( self.sh.runtime ), "-1", sid + "b" + str(i), "= ." # all values are bits print >> qap, self.strsig(), " ".join([ str(-(2**i)) + " " + sid + "b" + str(i) for i in xrange(len(bits)) ]), "* 1", self.constname( self.sh.runtime), "= ." # bit decompositon is correct qap.flush()
def callf(runtime): ret = f(runtime) retsh = [] for_each_in(Share, lambda x: retsh.append(x), ret) def printAndExit(runtime, vals): valsrev = list(reversed(vals)) retc = for_each_in(Share, lambda x: valsrev.pop(), ret) print "[ Verifiable computation result", retc, "]" if runtime.__class__.__name__ != "LocalRuntime": time.sleep(1) runtime.shutdown() return runtime if retsh != []: # print all returned values and then shut down gather_shares(retsh).addCallback( lambda x: printAndExit(runtime, x)) else: if runtime.__class__.__name__ != "LocalRuntime": time.sleep(1) runtime.shutdown() return runtime
def add(self, share_a, share_b): """Addition of shares. Communication cost: none. Each party ``P_i`` computes:: [z]_i = [x]_i + [y]_i = (x_i + y_i mod p, rho_xi + rho_yi mod p, C_x * C_y) """ def is_share(s, field): if not isinstance(s, Share): if not isinstance(s, FieldElement): s = field(s) (v, rhov, Cv) = self._additive_constant(field(0), s) return OrlandiShare(self, field, v, rhov, Cv) return s # Either share_a or share_b must have an attribute called "field". field = share_a.field share_b = is_share(share_b, field) # Add rho_xi and rho_yi and compute the commitment. def compute_sums((x, y)): (zi, (rhozi1, rhozi2), Cz) = self._plus(x, y) return OrlandiShare(self, field, zi, (rhozi1, rhozi2), Cz) result = gather_shares([share_a, share_b]) result.addCallbacks(compute_sums, self.error_handler) return result
def test_prss_share_asymmetric(self, runtime): """Test asymmetric pseudo-random secret sharing.""" # Share a single input -- the result should be a Share and not # a singleton list. if runtime.id == 2: b = runtime.prss_share([2], self.Zp, 42 + runtime.id) else: b = runtime.prss_share([2], self.Zp) # Share two inputs, but do it in "backwards" order. if runtime.id == 1 or runtime.id == 3: c, a = runtime.prss_share([3, 1], self.Zp, 42 + runtime.id) else: c, a = runtime.prss_share([3, 1], self.Zp) self.assert_type(a, Share) self.assert_type(b, Share) self.assert_type(c, Share) opened_a = runtime.open(a) opened_b = runtime.open(b) opened_c = runtime.open(c) opened_a.addCallback(self.assertEquals, 42 + 1) opened_b.addCallback(self.assertEquals, 42 + 2) opened_c.addCallback(self.assertEquals, 42 + 3) return gather_shares([opened_a, opened_b, opened_c])
def double_share_random(self, T, d1, d2, field): """Double-share a random secret using two polynomials. The guarantee is that a number of shares are made and out of those, the *T* that are returned by this method will be correct double-sharings of a random number using *d1* and *d2* as the polynomial degrees. """ si = rand.randint(0, field.modulus - 1) svec1, rvec1 = self._share_single(si, d1, field) svec2, rvec2 = self._share_single(si, d2, field) result = gather_shares([gather_shares(svec1[T:]), gather_shares(svec2[T:])]) self.schedule_callback(result, self._exchange_double, rvec1, rvec2, T, field, d1, d2) return result
def generate_triples(self, field, quantity=1, gather=True): """Generate *quantity* multiplication triples using PRSS. These are random numbers *a*, *b*, and *c* such that ``c = ab``. This function can be used in pre-processing. Returns a tuple with the number of triples generated and a Deferred which will yield a singleton-list with a 3-tuple. """ # This adjusted to the PRF based on SHA1 (160 bits). quantity = min(quantity, max(int(160 /numdigits(field.modulus - 1, 2)), 1)) a_t = self.prss_share_random_multi(field, quantity) b_t = self.prss_share_random_multi(field, quantity) r_t, r_2t = self.prss_double_share(field, quantity) c_t = [0] * quantity for i in range(quantity): # Multiply a and b without resharing. c_2t = gather_shares([a_t[i], b_t[i]]) c_2t.addCallback(lambda (a, b): a * b) d_2t = c_2t - r_2t[i] d = self.open(d_2t, threshold=2*self.threshold) c_t[i] = r_t[i] + d if gather: return [gatherResults(triple) for triple in zip(a_t, b_t, c_t)] else: return zip(a_t, b_t, c_t)
def greater_than_equal(self, share_a, share_b): """Compute ``share_a >= share_b``. Both arguments must be from the same field. The result is a :class:`~viff.field.GF256` share. :warning: The result type (:class:`~viff.field.GF256`) is different from the argument types (general field elements). """ field = getattr(share_a, "field", getattr(share_b, "field", None)) if not isinstance(share_a, Share): share_a = Share(self, field, share_a) if not isinstance(share_b, Share): share_b = Share(self, field, share_b) l = self.options.bit_length m = l + self.options.security_parameter t = m + 1 assert 2**(l+1) + 2**t < field.modulus, "2^(l+1) + 2^t < p must hold" assert self.num_players + 2 < 2**l a = share_a - share_b + 2**l b, bits = self.decomposed_random_sharing(field, m) T = self.open(2**t - b + a) result = gather_shares((T,) + bits) self.schedule_callback(result, self._finish_greater_than_equal, l) return result
def mul(self, share_x, share_y): """Multiplication of shares. Preprocessing: 1 multiplication triple. Communication: 2 openings. """ assert isinstance(share_x, Share), \ "share_x must be a Share." if not isinstance(share_y, Share): # Local multiplication. share_x always is a Share by # operator overloading in Share. We clone share_x first # to avoid changing it. result = share_x.clone() result.addCallback(lambda x: share_y * x) return result # At this point both share_x and share_y must be Share # objects. We multiply them via a multiplication triple. (a, b, c), _ = self.get_triple(share_x.field) d = self.open(share_x - a) e = self.open(share_y - b) # TODO: We ought to be able to simply do # # return d*e + d*y + e*x + c # # but that leads to infinite recursion since d and e are # Shares, not FieldElements. So we have to do a bit more # work... The following callback also leads to recursion, but # only one level since d and e are FieldElements now, which # means that we return in the above if statements. result = gather_shares([d, e]) result.addCallback(lambda (d,e): d*e + d*b + e*a + c) return result
def sub(self, share_a, share_b): """Subtraction of shares. Communication cost: none. Each party ``P_i`` computes:: [z]_i = [x]_i - [y]_i = (x_i - y_i mod p, rho_x,i - rho_y,i mod p, C_x * C_y) """ def is_share(s, field): if not isinstance(s, Share): if not isinstance(s, FieldElement): s = field(s) (v, rhov, Cv) = self._additive_constant(field(0), s) return OrlandiShare(self, field, v, rhov, Cv) return s # Either share_a or share_b must have an attribute called "field". field = getattr(share_a, "field", getattr(share_b, "field", None)) share_a = is_share(share_a, field) share_b = is_share(share_b, field) # Subtract xi and yi, rhoxi and rhoyi, and compute the commitment def compute_subs((x, y)): zi, (rhozi1, rhozi2), Cz = self._minus(x, y) return OrlandiShare(self, field, zi, (rhozi1, rhozi2), Cz) result = gather_shares([share_a, share_b]) result.addCallbacks(compute_subs, self.error_handler) return result
def calc_round_results(self, g1, g2, g3): # Now that everybody has secret shared their inputs we can # compare them. We check to see if any of the players have # guessed another player's secret, in which case they kill # that player, but because this is secrete shared, we don't # learn anything about the guesses of the other players # or the secrets. # TODO: can we do 'or'? print g2 one_dead = (g2 == self.s1) # or (g3 == s1) one_dead_2 = (g3 == self.s1) two_dead = (g1 == self.s2) # or (g3 == s2) two_dead_2 = (g3 == self.s2) three_dead = (g1 == self.s3) #or (g2 == s3) three_dead_2 = (g2 == self.s3) # The results are secret shared, so we must open them before # we can do anything usefull with them. open in this case # means computing # open the secret shared results open_one_dead = self.runtime.open(one_dead) open_one_dead_2 = self.runtime.open(one_dead_2) open_two_dead = self.runtime.open(two_dead) open_two_dead_2 = self.runtime.open(two_dead_2) open_three_dead = self.runtime.open(three_dead) open_three_dead_2 = self.runtime.open(three_dead_2) return gather_shares([ open_one_dead, open_one_dead_2, open_two_dead, open_two_dead_2, open_three_dead, open_three_dead_2 ])
def invert_by_masking(self, byte): bits = bit_decompose(byte) for j in range(len(bits)): bits[j].addCallback(lambda x: 1 - x) # bits[j] = 1 - bits[j] while len(bits) > 1: bits.append(bits.pop(0) * bits.pop(0)) # b == 1 if byte is 0, b == 0 else b = bits[0] r = Share(self.runtime, GF256) c = Share(self.runtime, GF256) def get_masked_byte(c_opened, r_related, c, r, byte): if c_opened == 0: r_trial = self.runtime.prss_share_random(GF256) c_trial = self.runtime.open((byte + b) * r_trial) self.runtime.schedule_callback(c_trial, get_masked_byte, r_trial, c, r, byte) else: r_related.addCallback(r.callback) c.callback(~c_opened) get_masked_byte(0, None, c, r, byte) # necessary to avoid communication in multiplication # was: return c * r - b result = gather_shares([c, r, b]) result.addCallback(lambda (c, r, b): c * r - b) return result
def __init__(self, runtime): self.k = 4 self.runtime = runtime self.ramdom_shares = [ 0 for i in range(self.k * int(math.log(self.k, 2))) ] self.triggers = [ Share(self.runtime, Zp) for i in range(self.k * int(math.log(self.k, 2))) ] self.p = find_prime(2**256, blum=True) print self.p for i in range(self.k * int(math.log(self.k, 2))): r = runtime.prss_share_random(Zp) u = r * r open_u = runtime.open(u) open_u.addCallback(self.calculate_share, r, i) list = [ self.triggers[i] for i in range(self.k * int(math.log(self.k, 2))) ] result = gather_shares(list) result.addCallback(self.preprocess_ready)
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 open(triple): d1 = runtime.open(triple.a) d2 = runtime.open(triple.b) d3 = runtime.open(triple.c) d = gather_shares([d1, d2, d3]) d.addCallback(check) return d
def mul(self, share_a, share_b): """Multiplication of shares.""" field = getattr(share_a, "field", getattr(share_b, "field", None)) k = self.options.security_parameter n = min(self.player.pubkey['n'], self.peer.pubkey['n']) assert field.modulus**2 + 2**k < n, \ "Need bigger Paillier keys to multiply." if not isinstance(share_a, Share): share_a = Share(self, field, share_a) if not isinstance(share_b, Share): share_b = Share(self, field, share_b) def finish_mul((a, b)): pc = tuple(self.program_counter) send_data = self.protocols[self.peer.id].sendData if hash(pc) % 2 == self.id: # We play the role of P1. a1, b1 = a, b enc_a1 = encrypt(a1.value, self.player.pubkey) enc_b1 = encrypt(b1.value, self.player.pubkey) send_data(pc, PAILLIER, str(enc_a1)) send_data(pc, PAILLIER, str(enc_b1)) enc_c1 = Share(self, field) self._expect_data(self.peer.id, PAILLIER, enc_c1) c1 = enc_c1.addCallback(decrypt, self.player.seckey) c1.addCallback(lambda c: long(c) + a1 * b1) return c1 else: # We play the role of P2. a2, b2 = a, b enc_a1 = Deferred() self._expect_data(self.peer.id, PAILLIER, enc_a1) enc_a1.addCallback(long) enc_b1 = Deferred() self._expect_data(self.peer.id, PAILLIER, enc_b1) enc_b1.addCallback(long) nsq = self.peer.pubkey['n']**2 # Calculate a1 * b2 and b1 * a2 inside the encryption. enc_a1_b2 = enc_a1.addCallback(pow, b2.value, nsq) enc_b1_a2 = enc_b1.addCallback(pow, a2.value, nsq) # Chose and encrypt r. r = rand.randint(0, 2 * field.modulus**2 + 2**k) enc_r = encrypt(r, self.peer.pubkey) c1 = gatherResults([enc_a1_b2, enc_b1_a2]) c1.addCallback(lambda (a,b): a * b * enc_r) c1.addCallback(lambda c: send_data(pc, PAILLIER, str(c))) c2 = a2 * b2 - r return Share(self, field, c2) result = gather_shares([share_a, share_b]) result.addCallback(finish_mul) return result
def mul(self, share_x, share_y): """Multiplication of shares. Preprocessing: 1 multiplication triple. Communication: 2 openings. """ assert isinstance(share_x, Share), \ "share_x must be a Share." if not isinstance(share_y, Share): # Local multiplication. share_x always is a Share by # operator overloading in Share. We clone share_x first # to avoid changing it. result = share_x.clone() result.addCallback(lambda x: share_y * x) return result # At this point both share_x and share_y must be Share # objects. We multiply them via a multiplication triple. (a, b, c), _ = self.get_triple(share_x.field) d = self.open(share_x - a) e = self.open(share_y - b) # TODO: We ought to be able to simply do # # return d*e + d*y + e*x + c # # but that leads to infinite recursion since d and e are # Shares, not FieldElements. So we have to do a bit more # work... The following callback also leads to recursion, but # only one level since d and e are FieldElements now, which # means that we return in the above if statements. result = gather_shares([d, e]) result.addCallback(lambda (d, e): d * e + d * b + e * a + c) return result
def greater_than_equal(self, share_a, share_b): """Compute ``share_a >= share_b``. Both arguments must be from the same field. The result is a :class:`~viff.field.GF256` share. :warning: The result type (:class:`~viff.field.GF256`) is different from the argument types (general field elements). """ field = getattr(share_a, "field", getattr(share_b, "field", None)) if not isinstance(share_a, Share): share_a = Share(self, field, share_a) if not isinstance(share_b, Share): share_b = Share(self, field, share_b) l = self.options.bit_length m = l + self.options.security_parameter t = m + 1 assert 2**(l + 1) + 2**t < field.modulus, "2^(l+1) + 2^t < p must hold" assert self.num_players + 2 < 2**l a = share_a - share_b + 2**l b, bits = self.decomposed_random_sharing(field, m) T = self.open(2**t - b + a) result = gather_shares((T, ) + bits) self.schedule_callback(result, self._finish_greater_than_equal, l) return result
def generate_triples(self, field, quantity=1, gather=True): """Generate *quantity* multiplication triples using PRSS. These are random numbers *a*, *b*, and *c* such that ``c = ab``. This function can be used in pre-processing. Returns a tuple with the number of triples generated and a Deferred which will yield a singleton-list with a 3-tuple. """ # This adjusted to the PRF based on SHA1 (160 bits). quantity = min(quantity, max(int(160 / numdigits(field.modulus - 1, 2)), 1)) a_t = self.prss_share_random_multi(field, quantity) b_t = self.prss_share_random_multi(field, quantity) r_t, r_2t = self.prss_double_share(field, quantity) c_t = [0] * quantity for i in range(quantity): # Multiply a and b without resharing. c_2t = gather_shares([a_t[i], b_t[i]]) c_2t.addCallback(lambda (a, b): a * b) d_2t = c_2t - r_2t[i] d = self.open(d_2t, threshold=2 * self.threshold) c_t[i] = r_t[i] + d if gather: return [gatherResults(triple) for triple in zip(a_t, b_t, c_t)] else: return zip(a_t, b_t, c_t)
def decrypt_benchmark(self): self.decrypt_time1 = time.clock() base = gmpy.mpz(self.m) power = gmpy.mpz(self.e) modulus = gmpy.mpz(self.n_revealed) self.c = int(pow(base, power, modulus)) if self.runtime.id == 1: self.c = gmpy.divm(1, self.c, self.n_revealed) base = gmpy.mpz(self.c) if self.runtime.id == 1: power = gmpy.mpz(-self.d) else: power = gmpy.mpz(self.d) modulus = gmpy.mpz(self.n_revealed) self.decrypt = int(pow(base, power, modulus)) c1, c2, c3 = self.runtime.shamir_share([1, 2, 3], self.Zp, self.decrypt) c_tot = c1 * c2 * c3 open_c_tot = self.runtime.open(c_tot) results = gather_shares([open_c_tot]) results.addCallback(self.check_decrypt_benchmark)
def mul(self, share_a, share_b): """Multiplication of shares.""" field = getattr(share_a, "field", getattr(share_b, "field", None)) k = self.options.security_parameter n = min(self.player.pubkey['n'], self.peer.pubkey['n']) assert field.modulus ** 2 + 2 ** k < n, \ "Need bigger Paillier keys to multiply." if not isinstance(share_a, Share): share_a = Share(self, field, share_a) if not isinstance(share_b, Share): share_b = Share(self, field, share_b) def finish_mul((a, b)): pc = tuple(self.program_counter) send_data = self.protocols[self.peer.id].sendData if hash(pc) % 2 == self.id: # We play the role of P1. a1, b1 = a, b enc_a1 = encrypt(a1.value, self.player.pubkey) enc_b1 = encrypt(b1.value, self.player.pubkey) send_data(pc, PAILLIER, str(enc_a1)) send_data(pc, PAILLIER, str(enc_b1)) enc_c1 = Share(self, field) self._expect_data(self.peer.id, PAILLIER, enc_c1) c1 = enc_c1.addCallback(decrypt, self.player.seckey) c1.addCallback(lambda c: long(c) + a1 * b1) return c1 else: # We play the role of P2. a2, b2 = a, b enc_a1 = Deferred() self._expect_data(self.peer.id, PAILLIER, enc_a1) enc_a1.addCallback(long) enc_b1 = Deferred() self._expect_data(self.peer.id, PAILLIER, enc_b1) enc_b1.addCallback(long) nsq = self.peer.pubkey['n']**2 # Calculate a1 * b2 and b1 * a2 inside the encryption. enc_a1_b2 = enc_a1.addCallback(pow, b2.value, nsq) enc_b1_a2 = enc_b1.addCallback(pow, a2.value, nsq) # Chose and encrypt r. r = rand.randint(0, 2 * field.modulus**2 + 2**k) enc_r = encrypt(r, self.peer.pubkey) c1 = gatherResults([enc_a1_b2, enc_b1_a2]) c1.addCallback(lambda (a, b): a * b * enc_r) c1.addCallback(lambda c: send_data(pc, PAILLIER, str(c))) c2 = a2 * b2 - r return Share(self, field, c2) result = gather_shares([share_a, share_b]) result.addCallback(finish_mul) return result
def encrypt(_, rt, key): start = time.time() print "Started at %f." % start aes = AES(rt, options.keylength, use_exponentiation=options.exponentiation) ciphertext = [] for i in range(options.count): ciphertext += aes.encrypt("a" * 16, key, True, prepare_at_once=options.at_once) opened_ciphertext = [rt.open(c) for c in ciphertext] def fin(ciphertext): print "Finished after %f sec." % (time.time() - start) print "Ciphertext:", [hex(c.value) for c in ciphertext] if rt._needed_data and options.preproc: print "Missing pre-processed data:" for (func, args), pcs in rt._needed_data.iteritems(): print "* %s%s:" % (func, args) print " " + pformat(pcs).replace("\n", "\n ") if rt._pool: print "Unused pre-processed data:" pcs = rt._pool.keys() pcs.sort() print " " + pformat(pcs).replace("\n", "\n ") rt.shutdown() g = gather_shares(opened_ciphertext) rt.schedule_complex_callback(g, fin)
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 calculate_powersum(self,item,cnt): #print "generating powersums for %d and cnt %d"%(item,cnt) if self.runtime.id == 1: self.a = self.runtime.shamir_share([1], self.Zp, item) else: self.a = self.runtime.shamir_share([1], self.Zp) #print "generating precomputed powers" if self.runtime.id == 1: self.matrix[0][0] = self.runtime.shamir_share([1], self.Zp,0) self.matrix[0][1] = self.runtime.shamir_share([1], self.Zp, self.b) else: self.matrix[0][0] = self.runtime.shamir_share([1], self.Zp) self.matrix[0][1] = self.runtime.shamir_share([1], self.Zp) for i in range(2,self.k + 1): self.matrix[0][i] = self.matrix[0][i - 1] * self.matrix[0][1] self.matrix[1][0] = self.a self.matrix[1][1] = self.matrix[1][0] * self.matrix[0][1] self.prefix = self.runtime.open(self.a - self.matrix[0][1]) list1 = [self.prefix,self.matrix[1][0],self.matrix[1][1] ] list1 = list1 + [self.matrix[0][i] for i in range(1,self.k + 1)] results = gather_shares(list1) results.addCallback(self.preprocess_ready,cnt)
def begin_MPC(runtime): try: print "Sharing..." shares = share_all(runtime) print "Executing..." global value_map value_map = {n: shares[n] for n in nodes} # All nodes are set to their shares i = 0 for iteration in range(public_diameter): #Graph Distance Algorithm print "it" + str(i) i = i + 1 tmp = {} j = 0 for n in nodes: print "node" + str(j) j = j + 1 val = value_map[n] for nb in edges_map[n]: val = smin(val, value_map[nb] + 1) # Open Weight (1) for nb in gateways_per_party[get_party(n)]: if nb == n: continue w = (nb + ":" + n) if nb < n else (n + ":" + nb) val = smin(val, value_map[nb] + shares[str(w)]) # Secret Distance tmp[n] = val value_map = tmp print "Algorithm Done..." results = [] gathered = [] for node_name in value_map: party = get_party(node_name) share = runtime.open(value_map[node_name], receivers=[party]) if share is not None: gathered.append(share) results.append(node_name) else: value_map[node_name] = "X" def results_ready(opened_results): print "Results Ready" for i in range(len(opened_results)): node_name = results[i] value_map[node_name] = opened_results[ i] if opened_results[i] < INFINITY else float("inf") gathered = gather_shares(gathered) gathered.addCallback(results_ready) print "Opening" runtime.schedule_callback(gathered, lambda _: runtime.shutdown()) except: import traceback traceback.print_exc()
def __init__(self, runtime): # Save the Runtime for later use self.runtime = runtime self.k = 256 self.b = 2 self.threshold = 1 self.matrix = [[0 for x in range(self.k + 1)] for y in range(self.k + 1)] self.openmatrix = [[0 for x in range(self.k + 1)] for y in range(self.k + 1)] self.prefix = 0 # This is the value we will use in the protocol. self.target = 3 Zp = GF(find_prime(2**64)) if runtime.id == 1: a = runtime.shamir_share([1], Zp, self.target) else: a = runtime.shamir_share([1], Zp) self.a = a ''' for i in range(self.k + 1): if runtime.id == 1: self.matrix[0][i] = self.runtime.shamir_share([1], Zp, self.b**i) else: self.matrix[0][i] = self.runtime.shamir_share([1], Zp) ''' #self.matrix[0][1] = TriplesHyperinvertibleMatricesMixin.single_share_random(1,self.threshold,Zp) if runtime.id == 1: self.matrix[0][0] = self.runtime.shamir_share([1], Zp, 0) self.matrix[0][1] = self.runtime.shamir_share([1], Zp, self.b) else: self.matrix[0][0] = self.runtime.shamir_share([1], Zp) self.matrix[0][1] = self.runtime.shamir_share([1], Zp) for i in range(2, self.k + 1): self.matrix[0][i] = self.matrix[0][i - 1] * self.matrix[0][1] #record_stop() for i in range(self.k + 1): self.openmatrix[0][i] = self.runtime.open(self.matrix[0][i]) self.matrix[1][0] = self.a self.matrix[1][1] = self.matrix[1][0] * self.matrix[0][1] self.prefix = self.runtime.open(a - self.matrix[0][1]) list1 = [self.prefix, a, self.matrix[1][1]] list1 = list1 + [self.matrix[0][i] for i in range(1, self.k + 1)] print len(list1) #results = list1 results = gather_shares(list1) results.addCallback(self.preprocess_ready)
def generate_z(self): self.function_count[12] += 1 self.r_z = random.randint(1, self.n_revealed - 1) r1, r2, r3 = self.runtime.shamir_share([1, 2, 3], self.Zp, self.r_z) z = (r1 + r2 + r3) * (-1 + (self.ptot + self.qtot)) self.open_z = self.runtime.open(z) results = gather_shares([self.open_z]) results.addCallback(self.check_z)
def double_share_random(self, T, d1, d2, field): """Double-share a random secret using two polynomials. The guarantee is that a number of shares are made and out of those, the *T* that are returned by this method will be correct double-sharings of a random number using *d1* and *d2* as the polynomial degrees. """ si = rand.randint(0, field.modulus - 1) svec1, rvec1 = self._share_single(si, d1, field) svec2, rvec2 = self._share_single(si, d2, field) result = gather_shares( [gather_shares(svec1[T:]), gather_shares(svec2[T:])]) self.schedule_callback(result, self._exchange_double, rvec1, rvec2, T, field, d1, d2) return result
def begin_MPC(runtime): try: print "Sharing..." shares = share_all(runtime) print "Executing..." global value_map value_map = {n: shares[n] for n in nodes} # All nodes are set to their shares i = 0 for iteration in range(diameter): #Graph Distance Algorithm tmp = dict(value_map) # Print Iteration Number i, j = i + 1, 0 print "it" + str(i) + "/" + str(diameter) # Compute new distance value for a node n for n in nodes: # Print Node Number j = j + 1 print "node" + str(j) + "/" + str(len(nodes)) val = value_map[n] for nb in edges[n]: val = smin(val, value_map[nb] + 1) # Naive, no private weights. tmp[n] = val value_map = tmp print "Algorithm Done..." results = [] gathered = [] for node_name in value_map: party = get_party(node_name) share = runtime.open(value_map[node_name], receivers=[party]) if share is not None: gathered.append(share) results.append(node_name) else: value_map[node_name] = "X" def results_ready(opened_results): print "Results Ready" for i in range(len(opened_results)): node_name = results[i] value_map[node_name] = opened_results[ i] if opened_results[i] < INFINITY else float("inf") gathered = gather_shares(gathered) gathered.addCallback(results_ready) runtime.schedule_callback(gathered, lambda _: runtime.shutdown()) print "Opening" except: import traceback traceback.print_exc()
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_prss_share_random_multi_bit(self, runtime): """Tests the sharing of several 0/1 GF256 elements using PRSS.""" a_list = runtime.prss_share_random_multi(field=GF256, quantity=8, binary=True) for a in a_list: self.assert_type(a, Share) opened_a = runtime.open(a) opened_a.addCallback(self.assertIn, [GF256(0), GF256(1)]) return gather_shares(a_list)
def open_check(self): print"open!!!!" list1 = [] for cnt in range(len(self.target)): for i in range(1 , self.k + 1): self.openmatrix[cnt][i] = self.runtime.open(self.resultmatrix[cnt][i]) list1 = list1 + [self.openmatrix[cnt][i] for i in range(1,self.k + 1)] results = gather_shares(list1) results.addCallback(self.calculation_ready,cnt)
def generate_l(self): self.function_count[14] += 1 self.l = self.phi_i % self.e print "\n\nPRIVATE VARIABLES" print "self.l = " + str(self.l) l1, l2, l3 = self.runtime.shamir_share([1, 2, 3], self.Zp, self.l) l_tot = l1 + l2 + l3 open_l_tot = self.runtime.open(l_tot) results = gather_shares([open_l_tot]) results.addCallback(self.generate_d)
def both_shares(self, share_a, share_b, if_not, if_so): field = share_a.field if not isinstance(share_b, Share): if not isinstance(share_b, FieldElement): share_b = field(share_b) share_a.addCallbacks(if_not, self.error_handler, callbackArgs=(share_b, field)) return share_a else: result = gather_shares([share_a, share_b]) result.addCallbacks(if_so, self.error_handler, callbackArgs=(field,)) return result
def verify(self, runtime, results, expected_results): self.assert_type(results, list) opened_results = [] for result, expected in zip(results, expected_results): self.assert_type(result, Share) opened = runtime.open(result) opened.addCallback(self.assertEquals, expected) opened_results.append(opened) return gather_shares(opened_results)
def begin_MPC(self, runtime): try: self.runtime = runtime self.share() # Share inputs # Evaluate for i in range(len(self.parties_list) - 1): print "COMB" tmp = {} i = 0 for key in self.expressions: print "exp " + str(i) i = i + 1 party, exp = self.expressions[key] tmp[key] = exp.evaluate(self) self.shares.update(tmp) tmp = {} i = 0 for key in self.weight_expressions: print "w" + str(i) i = i + 1 exp = self.weight_expressions[key] tmp[key] = exp.evaluate(self) self.shares.update(tmp) evaluated = {} i = 0 for key in self.expressions: print "." + str(i) i = i + 1 party, exp = self.expressions[key] evaluated[key] = (party, exp.evaluate(self)) # Open gathered = [] self.results = [] self.keys = [] for key in evaluated: party, ev = evaluated[key] share = self.runtime.open(ev, receivers=[party]) if share is not None: gathered.append(share) self.keys.append(key) gathered = gather_shares(gathered) gathered.addCallback(self.results_ready) # Shutdown self.runtime.schedule_callback(gathered, lambda _: self.runtime.shutdown()) except: import traceback traceback.print_exc()
def decomposed_random_sharing(self, field, bits): bits = [self.prss_share_bit_double(field) for _ in range(bits)] int_bits, bit_bits = zip(*bits) def bits_to_int(bits): """Converts a list of bits to an integer.""" return sum([2**i * b for i, b in enumerate(bits)]) int_b = gather_shares(int_bits) int_b.addCallback(bits_to_int) return int_b, bit_bits
def test_prss_shamir_share_bit_double(self, runtime): """Tests Shamir sharing a bit over Zp and GF256.""" bit_p, bit_b = runtime.prss_shamir_share_bit_double(self.Zp) self.assert_type(bit_p, Share) self.assertEquals(bit_p.field, self.Zp) self.assert_type(bit_b, Share) self.assertEquals(bit_b.field, GF256) result = gather_shares([runtime.open(bit_p), runtime.open(bit_b)]) result.addCallback(lambda (a, b): self.assertEquals(a.value, b.value)) return result
def share_recombine(number): shares = shamir.share(number, self.threshold, self.num_players) exchanged_shares = [] for peer_id, share in shares: d = self._exchange_shares(peer_id.value, share) d.addCallback(lambda share, peer_id: (peer_id, share), peer_id) exchanged_shares.append(d) # Recombine the first 2t+1 shares. result = gather_shares(exchanged_shares[:2*self.threshold+1]) result.addCallback(shamir.recombine) return result
def __init__(self, runtime): self.progressbar = self.setup_progress_bar() self.rt = runtime self.comparisons = 0 array = self.make_array() sorted = self.sort(array) array = gather_shares(map(runtime.open, array)) sorted = gather_shares(map(runtime.open, sorted)) self.progressbar.start() def finish(result): self.progressbar.finish() print # This line goes on top of the progressbar dprint("Original array: %s", array) dprint("Sorted array: %s", result) print "Made %d comparisons" % self.comparisons runtime.shutdown() sorted.addCallback(finish)
def test_prss_double_share(self, runtime): """Test double-sharing of random numbers using PRSS.""" r_t, r_2t = zip(*runtime.prss_double_share(self.Zp, 1))[0] self.assert_type(r_t, Share) self.assertEquals(r_t.field, self.Zp) self.assert_type(r_2t, Share) self.assertEquals(r_2t.field, self.Zp) result = gather_shares([runtime.open(r_t), runtime.open(r_2t, threshold=2 * runtime.threshold)]) result.addCallback(lambda (a, b): self.assertEquals(a, b)) return result
def single_share_random(self, T, degree, field): """Share a random secret. The guarantee is that a number of shares are made and out of those, the *T* that are returned by this method will be correct sharings of a random number using *degree* as the polynomial degree. """ si = rand.randint(0, field.modulus - 1) svec, rvec = self._share_single(si, degree, field) result = gather_shares(svec[T:]) self.schedule_callback(result, self._exchange_single, rvec, T, field, degree) return result
def add(self, share_a, share_b): """Addition of shares. Communication cost: none. """ field = getattr(share_a, "field", getattr(share_b, "field", None)) if not isinstance(share_a, Share): share_a = Share(self, field, share_a) if not isinstance(share_b, Share): share_b = Share(self, field, share_b) result = gather_shares([share_a, share_b]) result.addCallback(lambda (a, b): a + b) return result
def run(self, runtime): l = 512 k = 64 print "Generating field... " self.zp = GF(find_prime(2**(l + 1) + 2**(l + k + 1), blum=True)) self.runtime = runtime p = range(1, runtime.num_players + 1) print "Sharing values... " add_shares = runtime.input(p, self.zp, self.address) rep_shares = runtime.input(p, self.zp, self.representative) n = len(rep_shares) for i in range(0, n - 1): for j in range(0, n - i - 1): c = rep_shares[j] < rep_shares[j + 1] p, q = pair_sort(rep_shares[j], rep_shares[j + 1], c) rep_shares[j] = p rep_shares[j + 1] = q r, s = pair_sort(add_shares[j], add_shares[j + 1], c) add_shares[j] = r add_shares[j + 1] = s gather_shares([ self.runtime.open(x) for x in add_shares ]).addCallback(self.done)
def _basic_multiplication(self, share_x, share_y, triple_a, triple_b, triple_c): """Multiplication of shares give a triple. Communication cost: ???. ``d = Open([x] - [a])`` ``e = Open([y] - [b])`` ``[z] = e[x] + d[y] - [de] + [c]`` """ assert isinstance(share_x, Share) or isinstance(share_y, Share), \ "At least one of share_x and share_y must be a Share." self.increment_pc() field = getattr(share_x, "field", getattr(share_y, "field", None)) n = field(0) cmul_result = self._cmul(share_x, share_y, field) if cmul_result is not None: return cmul_result def multiply(ls): x, y, c, (d, e) = ls # [de] de = d * e # e[x] t1 = self._constant_multiply(x, e) # d[y] t2 = self._constant_multiply(y, d) # d[y] - [de] t3 = self._minus_public_right_without_share(t2, de, field) # d[y] - [de] + [c] z = self._plus((t3, c), field) t4 = self._plus((t3, c), field) # [z] = e[x] + d[y] - [de] + [c] z = self._plus((t1, t4), field) return self._wrap_in_share(z, field) # d = Open([x] - [a]) # e = Open([y] - [b]) de = self.open_two_values(share_x - triple_a, share_y - triple_b) # ds = self.open_multiple_values([share_x - triple_a, share_y - triple_b]) result = gather_shares([share_x, share_y, triple_c, de]) result.addCallbacks(multiply, self.error_handler) # do actual communication self.activate_reactor() return result
def test_different_subsets_of_receivers_get_the_same_result(self, runtime): """Test that two different subsets of the players obtain the same result.""" res = [] share = runtime.prss_share_random(self.Zp) a = runtime.open(share) res.append(a) receivers = runtime.players.keys()[0:2] if runtime.id in receivers: b = runtime.open(share, receivers) c = gather_shares([a, b]) c.addCallback(lambda (a, b): self.assertEquals(a, b)) res.append(c) else: runtime.open(share, receivers) return gatherResults(res)
def add(self, share_a, share_b): """Addition of shares. Communication cost: none. """ if not isinstance(share_b, Share): # Addition with constant. share_a always is a Share by # operator overloading in Share. Clone share_a to avoid # changing it. result = share_a.clone() result.addCallback(lambda a, b: b + a, share_b) return result result = gather_shares([share_a, share_b]) result.addCallback(lambda (a, b): a + b) return result
def generate_operation_arguments(self, _): # print "Generate operation arguments", self.rt.program_counter print "Runtime ready, generating shares" self.a_shares = [] self.b_shares = [] for i in range(self.count): inputter = (i % len(self.rt.players)) + 1 if inputter == self.rt.id: a = rand.randint(0, self.field.modulus) b = rand.randint(0, self.field.modulus) else: a, b = None, None self.a_shares.append(self.rt.input([inputter], self.field, a)) self.b_shares.append(self.rt.input([inputter], self.field, b)) shares_ready = gather_shares(self.a_shares + self.b_shares) return shares_ready
def invert(rt): aes = AES(rt, 192, use_exponentiation=options.exponentiation) bytes = [Share(rt, GF256, GF256(random.randint(0, 255))) for i in range(options.count)] start = time.time() done = gather_shares([aes.invert(byte) for byte in bytes]) def finish(_): duration = time.time() - start print "Finished after %.3f s." % duration print "Time per inversion: %.3f ms" % (1000 * duration / options.count) rt.shutdown() done.addCallback(finish)
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_prss_share_bit(self, runtime): """Test sharing of a GF256 element using PRSS.""" a, b, c = runtime.prss_share(runtime.players, GF256.field, 42 + runtime.id) self.assert_type(a, Share) self.assert_type(b, Share) self.assert_type(c, Share) opened_a = runtime.open(a) opened_b = runtime.open(b) opened_c = runtime.open(c) opened_a.addCallback(self.assertEquals, 42 + 1) opened_b.addCallback(self.assertEquals, 42 + 2) opened_c.addCallback(self.assertEquals, 42 + 3) return gather_shares([opened_a, opened_b, opened_c])
def _expect_orlandi_share(self, peer_id, field): """Waits for a number ``x``, ``rho``, and the commitment for ``x``.""" xi = self._expect_share(peer_id, field) Cx = Deferred() rhoi1 = self._expect_share(peer_id, field) rhoi2 = self._expect_share(peer_id, field) self._expect_data(peer_id, TEXT, Cx) sls = gather_shares([xi, rhoi1, rhoi2, Cx]) def combine(ls): xi = ls[0] rhoi1 = ls[1] rhoi2 = ls[2] Cx = ls[3] Cxx = commitment.deserialize(Cx) return OrlandiShare(self, field, xi, (rhoi1, rhoi2), Cxx) sls.addCallbacks(combine, self.error_handler) return sls
def mul(self, share_a, share_b): """Multiplication of shares. Communication cost: 1 Shamir sharing. """ assert isinstance(share_a, Share), \ "share_a must be a Share." if not isinstance(share_b, Share): # Local multiplication. share_a always is a Share by # operator overloading in Share. We clone share_a first # to avoid changing it. result = share_a.clone() result.addCallback(lambda a: share_b * a) return result # At this point both share_a and share_b must be Share # objects. So we wait on them, multiply and reshare. def share_recombine(number): shares = shamir.share(number, self.threshold, self.num_players) exchanged_shares = [] for peer_id, share in shares: d = self._exchange_shares(peer_id.value, share) d.addCallback(lambda share, peer_id: (peer_id, share), peer_id) exchanged_shares.append(d) # Recombine the first 2t+1 shares. result = gather_shares(exchanged_shares[:2*self.threshold+1]) result.addCallback(shamir.recombine) return result result = gather_shares([share_a, share_b]) result.addCallback(lambda (a, b): a * b) self.schedule_callback(result, share_recombine) # do actual communication self.activate_reactor() return result
def make_triple(shares, results): a_t, b_t, (r_t, r_2t) = shares c_2t = [] for i in range(T): # Multiply a[i] and b[i] without resharing. ci = gather_shares([a_t[i], b_t[i]]) ci.addCallback(lambda (ai, bi): ai * bi) c_2t.append(ci) d_2t = [c_2t[i] - r_2t[i] for i in range(T)] d = [self.open(d_2t[i], threshold=2*t) for i in range(T)] c_t = [r_t[i] + d[i] for i in range(T)] if gather: for triple, result in zip(zip(a_t, b_t, c_t), results): gatherResults(triple).chainDeferred(result) else: for triple, result_triple in zip(zip(a_t, b_t, c_t), results): for item, result_item in zip(triple, result_triple): item.chainDeferred(result_item)