def random_bit(self, field): """Generate shares of a uniformly random bit over the field given. Communication cost: 1 open. """ yield declareReturn(self, field) prss_key = self.prss_key() prfs = self.players[self.id].prfs(field.modulus) a = prss(len(self.players), self.id, field, prfs, prss_key) # Open the square and compute a square-root a2 = yield self.open(Share(self, field, a**2), None, 2 * self.threshold) if a2 == 0: returnValue(self.random_bit(field)) else: returnValue((a / a2.sqrt() + 1) / 2)
def prss_share_random(self, field, binary=False): """Generate shares of a uniformly random element from the field given. If binary is True, a 0/1 element is generated. No player learns the value of the element. Communication cost: none if binary=False, 1 open otherwise. """ if field is GF256 and binary: modulus = 2 else: modulus = field.modulus # Key used for PRSS. prss_key = self.prss_key() prfs = self.players[self.id].prfs(modulus) share = prss(self.num_players, self.id, field, prfs, prss_key) if field is GF256 or not binary: return Share(self, field, share) # Open the square and compute a square-root result = self.open(Share(self, field, share * share), threshold=2 * self.threshold) def finish(square, share, binary): if square == 0: # We were unlucky, try again... return self.prss_share_random(field, binary) else: # We can finish the calculation root = square.sqrt() # When the root is computed, we divide the share and # convert the resulting -1/1 share into a 0/1 share. return Share(self, field, (share / root + 1) / 2) self.schedule_callback(result, finish, share, binary) return result
def prss_share_random(self, field, binary=False): """Generate shares of a uniformly random element from the field given. If binary is True, a 0/1 element is generated. No player learns the value of the element. Communication cost: none if binary=False, 1 open otherwise. """ if field is GF256 and binary: modulus = 2 else: modulus = field.modulus # Key used for PRSS. prss_key = self.prss_key() prfs = self.players[self.id].prfs(modulus) share = prss(self.num_players, self.id, field, prfs, prss_key) if field is GF256 or not binary: return Share(self, field, share) # Open the square and compute a square-root result = self.open(Share(self, field, share*share), threshold=2*self.threshold) def finish(square, share, binary): if square == 0: # We were unlucky, try again... return self.prss_share_random(field, binary) else: # We can finish the calculation root = square.sqrt() # When the root is computed, we divide the share and # convert the resulting -1/1 share into a 0/1 share. return Share(self, field, (share/root + 1) / 2) self.schedule_callback(result, finish, share, binary) return result
def random_max(self, field, max): prss_key = self.prss_key() prfs = self.players[self.id].prfs(max) share = prss(len(self.players), self.id, field, prfs, prss_key) return Share(self, field, share)
def prss_share(self, inputters, field, element=None): """Creates pseudo-random secret sharings. This protocol creates a secret sharing for each player in the subset of players specified in *inputters*. Each inputter provides an integer. The result is a list of shares, one for each inputter. The protocol uses the pseudo-random secret sharing technique described in the paper "Share Conversion, Pseudorandom Secret-Sharing and Applications to Secure Computation" by Ronald Cramer, Ivan Damgård, and Yuval Ishai in Proc. of TCC 2005, LNCS 3378. `Download <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>`__ Communication cost: Each inputter does one broadcast. """ # Verifying parameters. if element is None: assert self.id not in inputters, "No element given." else: assert self.id in inputters, \ "Element given, but we are not sharing?" n = self.num_players # Key used for PRSS. key = self.prss_key() # The shares for which we have all the keys. all_shares = [] # Shares we calculate from doing PRSS with the other players. tmp_shares = {} prfs = self.players[self.id].dealer_prfs(field.modulus) # Compute and broadcast correction value. if self.id in inputters: for player in self.players: share = prss(n, player, field, prfs[self.id], key) all_shares.append((field(player), share)) shared = shamir.recombine(all_shares[:self.threshold + 1]) correction = element - shared # if this player is inputter then broadcast correction value # TODO: more efficient broadcast? pc = tuple(self.program_counter) for peer_id in self.players: if self.id != peer_id: self.protocols[peer_id].sendShare(pc, correction) # Receive correction value from inputters and compute share. result = [] for player in inputters: tmp_shares[player] = prss(n, self.id, field, prfs[player], key) if player == self.id: d = Share(self, field, correction) else: d = self._expect_share(player, field) d.addCallback(lambda c, s: s + c, tmp_shares[player]) result.append(d) # Unpack a singleton list. if len(result) == 1: return result[0] else: return result
def test_prss(self): share = prss.prss(None, None, self.field, None, None) self.assertEquals(share, self.field(7))
def prss_share(self, inputters, field, element=None): """Creates pseudo-random secret sharings. This protocol creates a secret sharing for each player in the subset of players specified in *inputters*. Each inputter provides an integer. The result is a list of shares, one for each inputter. The protocol uses the pseudo-random secret sharing technique described in the paper "Share Conversion, Pseudorandom Secret-Sharing and Applications to Secure Computation" by Ronald Cramer, Ivan Damgård, and Yuval Ishai in Proc. of TCC 2005, LNCS 3378. `Download <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>`__ Communication cost: Each inputter does one broadcast. """ # Verifying parameters. if element is None: assert self.id not in inputters, "No element given." else: assert self.id in inputters, \ "Element given, but we are not sharing?" n = self.num_players # Key used for PRSS. key = self.prss_key() # The shares for which we have all the keys. all_shares = [] # Shares we calculate from doing PRSS with the other players. tmp_shares = {} prfs = self.players[self.id].dealer_prfs(field.modulus) # Compute and broadcast correction value. if self.id in inputters: for player in self.players: share = prss(n, player, field, prfs[self.id], key) all_shares.append((field(player), share)) shared = shamir.recombine(all_shares[:self.threshold+1]) correction = element - shared # if this player is inputter then broadcast correction value # TODO: more efficient broadcast? pc = tuple(self.program_counter) for peer_id in self.players: if self.id != peer_id: self.protocols[peer_id].sendShare(pc, correction) # Receive correction value from inputters and compute share. result = [] for player in inputters: tmp_shares[player] = prss(n, self.id, field, prfs[player], key) if player == self.id: d = Share(self, field, correction) else: d = self._expect_share(player, field) d.addCallback(lambda c, s: s + c, tmp_shares[player]) result.append(d) # Unpack a singleton list. if len(result) == 1: return result[0] else: return result