changeset 1396:866a0167ddeb

Merged with Martin.
author Janus Dam Nielsen <janus.nielsen@alexandra.dk>
date Thu, 12 Nov 2009 11:40:17 +0100
parents b4b94221beee 3ede8d56ae64
children bf8b5b8a5a43 44ac3a04f413
files
diffstat 2 files changed, 108 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/viff/orlandi.py	Thu Nov 05 12:03:59 2009 +0100
+++ b/viff/orlandi.py	Thu Nov 12 11:40:17 2009 +0100
@@ -28,7 +28,7 @@
 from hash_broadcast import HashBroadcastMixin
 
 try:
-    from pypaillier import encrypt_r, decrypt
+    from pypaillier import encrypt_r, decrypt, tripple
     import commitment
     commitment.set_reference_string(23434347834783478783478L,
                                     489237823478234783478020L)
@@ -282,6 +282,81 @@
         if self.id in receivers:
             return result
 
+    def open_multiple_values(self, shares, receivers=None):
+        """Share reconstruction.
+
+        Open multiple values in one burst. 
+        If called with one value it is slower than the open method.
+        If called with more than two values it is faster than using 
+        multiple calls to the open method. 
+
+        Every partyi broadcasts a share pair ``(x_i', rho_x,i')``.
+
+        The parties compute the sums ``x'``, ``rho_x'`` and check
+        ``Com_ck(x',rho_x') = C_x``.
+
+        If yes, return ``x = x'``, else else return :const:`None`.
+        """
+        assert shares
+        # all players receive result by default
+        if receivers is None:
+            receivers = self.players.keys()
+
+        field = shares[0].field
+
+        self.increment_pc()
+
+        def recombine_value((shares, Cx)):
+            x = 0
+            rho1 = 0
+            rho2 = 0
+            for xi, rhoi1, rhoi2 in shares:
+                x += xi
+                rho1 += rhoi1
+                rho2 += rhoi2
+            Cx1 = commitment.commit(x.value, rho1.value, rho2.value)
+            if Cx1 == Cx:
+                return x
+            else:
+                #return x
+                raise OrlandiException("Wrong commitment for value %s, %s, %s, found %s expected %s." %
+                                       (x, rho1, rho2, Cx1, Cx))
+
+        def deserialize(ls, commitments):
+            def convert_from_string_to_field(s):
+                def field_long(x):
+                    return field(long(x))
+                xs = s[0:-1].split(';')
+                ys = [x.split(':') for x in xs]
+                return [map(field_long, xs) for xs in ys]
+            shares = map(convert_from_string_to_field, ls)
+            return map(recombine_value, zip(zip(*shares), commitments))
+
+        def exchange(ls, receivers):
+            commitments = [None] * len(ls)
+            broadcast_string = ""
+            for inx, (xi, (rhoi1, rhoi2), Cx) in enumerate(ls):
+                broadcast_string += "%s:%s:%s;" % (xi.value, rhoi1.value, rhoi2.value)
+                commitments[inx] = (Cx)
+            # Send share to all receivers.
+            ds = self.broadcast(self.players.keys(), receivers, broadcast_string)
+
+            if self.id in receivers:
+                result = gatherResults(ds)
+                result.addCallbacks(deserialize, self.error_handler,
+                                    callbackArgs=(commitments,))
+                return result
+
+        result = gather_shares(shares)
+        self.schedule_callback(result, exchange, receivers)
+        result.addErrback(self.error_handler)
+
+        # do actual communication
+        self.activate_reactor()
+
+        if self.id in receivers:
+            return result
+
     def random_share(self, field):
         """Generate a random share in the field, field.
 
@@ -611,7 +686,9 @@
         if cmul_result is  not None:
             return cmul_result
 
-        def multiply((x, y, d, e, c)):
+        def multiply((x, y, ds, c)):
+            d = ds[0]
+            e = ds[1]
             # [de]
             de = self._additive_constant(field(0), d * e)
             # e[x]
@@ -627,10 +704,9 @@
             return OrlandiShare(self, field, zi, rhoz, Cz)
 
         # d = Open([x] - [a])
-        d = self.open(share_x - triple_a)
         # e = Open([y] - [b])
-        e = self.open(share_y - triple_b)
-        result = gather_shares([share_x, share_y, d, e, triple_c])
+        ds = self.open_multiple_values([share_x - triple_a, share_y - triple_b])
+        result = gather_shares([share_x, share_y, ds, triple_c])
         result.addCallbacks(multiply, self.error_handler)
 
         # do actual communication
@@ -881,17 +957,10 @@
             pc = tuple(self.program_counter)
             p3 = field.modulus**3
             for pi in self.players.keys():
-                n = self.players[pi].pubkey['n']
-                nsq = n * n
                 # choose random d_i,j in Z_p^3
                 dij = random_number(p3)
-                # Enc_ek_i(1;1)^d_ij
-                enc = encrypt_r(1, 1, self.players[pi].pubkey)
-                t1 = pow(enc, dij.value, nsq)
-                # alpha_i^b_j.
-                t2 = pow(alphas[pi - 1], bj.value, nsq)
                 # gamma_ij = alpha_i^b_j Enc_ek_i(1;1)^d_ij
-                gammaij = (t2 * t1) % nsq
+                gammaij = tripple(alphas[pi - 1], bj.value, dij.value, self.players[pi].pubkey)
                 # Broadcast gamma_ij
                 if pi != self.id:
                     self.protocols[pi].sendData(pc, PAILLIER, str(gammaij))
@@ -1139,20 +1208,15 @@
 
                 # 3) the gammaij he received is equal to the gammaij
                 # he now computes based on the values he reveives
+                modulus_3 = field.modulus**3
                 for j in xrange(len(ais)):
-                    n = self.players[self.id].pubkey['n']
-                    nsq = n * n
                     dij = dijs[j]
                     # 5) ... and dij < p^3.
-                    if dij >= (field.modulus**3):
+                    if dij >= (modulus_3):
                         raise OrlandiException("Inconsistent random value dij %i from player %i" % (dij, j + 1))
-                    # Enc_ek_i(1;1)^d_ij
-                    enc = encrypt_r(1, 1, self.players[self.id].pubkey)
-                    t1 = pow(enc, dij.value, nsq)
-                    # alpha_i^b_j.
-                    t2 = pow(alphas[self.id - 1], bis[j][0].value, nsq)
                     # gamma_ij = alpha_i^b_j Enc_ek_i(1;1)^d_ij
-                    gammaij = (t2) * (t1) % nsq
+                    gammaij = tripple(alphas[self.id - 1], bis[j][0].value, 
+                                      dij.value, self.players[self.id].pubkey)
                     if gammaij != gammas[j]:
                         raise OrlandiException("Inconsistent gammaij, %i, %i" % (gammaij, gammas[j]))
 
--- a/viff/test/test_orlandi_runtime.py	Thu Nov 05 12:03:59 2009 +0100
+++ b/viff/test/test_orlandi_runtime.py	Thu Nov 12 11:40:17 2009 +0100
@@ -92,6 +92,28 @@
         return d
 
     @protocol
+    def test_open_multiple_secret_share(self, runtime):
+        """Test sharing and open of a number."""
+
+        self.Zp = GF(6277101735386680763835789423176059013767194773182842284081)
+
+        def check(ls):
+            for inx, v in enumerate(ls):
+                self.assertEquals(v, (inx + 1) * 42)
+
+        if 1 == runtime.id:
+            x = runtime.secret_share([1], self.Zp, 42)
+        else:
+            x = runtime.secret_share([1], self.Zp)
+        if 1 == runtime.id:
+            y = runtime.secret_share([1], self.Zp, 84)
+        else:
+            y = runtime.secret_share([1], self.Zp)
+        d = runtime.open_multiple_values([x, y])
+        d.addCallback(check)
+        return d
+
+    @protocol
     def test_random_share(self, runtime):
         """Test creation of a random shared number."""