viff

changeset 1503:b120a9dee885

BeDOZa: Implemented preprocessing mul method.
author Janus Dam Nielsen <janus.nielsen@alexandra.dk>
date Mon, 19 Jul 2010 10:42:37 +0200
parents af533d7ae315
children 129b326c3ff1
files viff/bedoza_triple.py viff/test/test_bedoza_triple.py
diffstat 2 files changed, 141 insertions(+), 5 deletions(-) [+]
line diff
     1.1 --- a/viff/bedoza_triple.py	Thu Jul 15 11:37:50 2010 +0200
     1.2 +++ b/viff/bedoza_triple.py	Mon Jul 19 10:42:37 2010 +0200
     1.3 @@ -96,19 +96,21 @@
     1.4        does it mean that the already public values get passed along on the
     1.5        network even though all players already posess them?
     1.6      """
     1.7 -    def __init__(self, value, enc_shares):
     1.8 +    def __init__(self, value, enc_shares, N_squared_list):
     1.9          self.value = value
    1.10          self.enc_shares = enc_shares
    1.11 +        self.N_squared_list = N_squared_list
    1.12  
    1.13      def __str__(self):
    1.14 -        return "PartialShareContents(%d; %s)" % (self.value, self.enc_shares)
    1.15 +        return "PartialShareContents(%d; %s; %s)" % (self.value, self.enc_shares, self.N_squared_list)
    1.16  
    1.17  # In VIFF, callbacks get the *contents* of a share as input. Hence, in order
    1.18  # to get a PartialShare as input to callbacks, we need this extra level of
    1.19  # wrapper indirection.
    1.20  class PartialShare(Share):
    1.21      def __init__(self, runtime, value, enc_shares):
    1.22 -        partial_share_contents = PartialShareContents(value, enc_shares)
    1.23 +        N_squared_list = [ runtime.players[player_id].pubkey['n_square'] for player_id in runtime.players.keys()]
    1.24 +        partial_share_contents = PartialShareContents(value, enc_shares, N_squared_list)
    1.25          Share.__init__(self, runtime, value.field, partial_share_contents)
    1.26  
    1.27  
    1.28 @@ -169,6 +171,11 @@
    1.29          seckey = self.runtime.players[self.runtime.id].seckey
    1.30          return self._f_inverse(pypaillier.decrypt(enc_value, seckey), n)
    1.31  
    1.32 +    def get_modulus(self, player_id):
    1.33 +        return self.runtime.players[player_id].pubkey['n']
    1.34 +
    1.35 +    def get_modulus_square(self, player_id):
    1.36 +        return self.runtime.players[player_id].pubkey['n_square']
    1.37  
    1.38  class TripleGenerator(object):
    1.39  
    1.40 @@ -180,6 +187,7 @@
    1.41          self.p = p
    1.42          self.Zp = GF(p)
    1.43          self.k = self._bit_length_of(p)
    1.44 +        self.u_bound = 2**(4 * self.k)
    1.45  
    1.46          paillier_random = Random(self.random.getrandbits(128))
    1.47          alpha_random = Random(self.random.getrandbits(128))
    1.48 @@ -278,8 +286,63 @@
    1.49          #     receive c from player i and set 
    1.50          #         m^i=Decrypt(c)
    1.51      
    1.52 -    def _mul(self):
    1.53 -        pass
    1.54 +    def _mul(self, inx, jnx, ai=None, cj=None):
    1.55 +        CKIND = 1
    1.56 +        DiKIND = 2
    1.57 +        DjKIND = 3
    1.58 +        
    1.59 +        self.runtime.increment_pc()
    1.60 +
    1.61 +        pc = tuple(self.runtime.program_counter)
    1.62 +            
    1.63 +        deferreds = []
    1.64 +        if self.runtime.id == inx:
    1.65 +            u = rand.randint(0, self.u_bound)
    1.66 +            Ej_u = self.paillier.encrypt(u, jnx)
    1.67 +            Nj_square = self.paillier.get_modulus_square(jnx)
    1.68 +            c = (pow(cj, ai.value, Nj_square) * Ej_u) % Nj_square
    1.69 +            self.runtime.protocols[jnx].sendData(pc, CKIND, str(c))
    1.70 +            zi = self.Zp(-u)
    1.71 +            di = self.paillier.encrypt(zi.value, inx)
    1.72 +            for player_id in self.runtime.players:
    1.73 +                self.runtime.protocols[player_id].sendData(pc, DiKIND, str(di))
    1.74 +            zi_deferred = Deferred()
    1.75 +            zi_deferred.callback(zi)
    1.76 +            deferreds.append(zi_deferred)
    1.77 +
    1.78 +        if self.runtime.id == jnx:
    1.79 +            c = Deferred()
    1.80 +            self.runtime._expect_data(inx, CKIND, c)
    1.81 +            def decrypt(c, pc):
    1.82 +                t = self.paillier.decrypt(long(c))
    1.83 +                zj = self.Zp(t)
    1.84 +                dj = self.paillier.encrypt(zj.value, jnx)
    1.85 +                for player_id in self.runtime.players:
    1.86 +                    self.runtime.protocols[player_id].sendData(pc, DjKIND, str(dj))
    1.87 +                return zj 
    1.88 +            c.addCallback(decrypt, pc)
    1.89 +            deferreds.append(c)
    1.90 +
    1.91 +        di = Deferred()
    1.92 +        self.runtime._expect_data(inx, DiKIND, di)
    1.93 +        dj = Deferred()
    1.94 +        self.runtime._expect_data(jnx, DjKIND, dj)
    1.95 +
    1.96 +        deferreds.append(di)
    1.97 +        deferreds.append(dj)
    1.98 +        r = gatherResults(deferreds)
    1.99 +        def wrap(ls, inx, jnx):
   1.100 +            value = reduce(lambda x, y: x + y, [self.Zp(0)] + ls[0:-2])
   1.101 +            n_square_i = self.paillier.get_modulus_square(inx)
   1.102 +            n_square_j = self.paillier.get_modulus_square(jnx)
   1.103 +            enc_shares = len(self.runtime.players) * [1]
   1.104 +            enc_shares[inx - 1] = (enc_shares[inx - 1] * long(ls[-2])) % n_square_i
   1.105 +            enc_shares[jnx - 1] = (enc_shares[jnx - 1] * long(ls[-1])) % n_square_j
   1.106 +            N_squared_list = [self.paillier.get_modulus_square(player_id) for player_id in self.runtime.players]
   1.107 +            return PartialShareContents(value, enc_shares, N_squared_list)
   1.108 +        r.addCallback(wrap, inx, jnx)
   1.109 +        return r
   1.110 +
   1.111      
   1.112      def _full_mul(self):
   1.113          pass
     2.1 --- a/viff/test/test_bedoza_triple.py	Thu Jul 15 11:37:50 2010 +0200
     2.2 +++ b/viff/test/test_bedoza_triple.py	Mon Jul 19 10:42:37 2010 +0200
     2.3 @@ -317,6 +317,79 @@
     2.4  #    #test_add_macs_preserves_value_of_zero_sharing.skip = "nyi"
     2.5  # 
     2.6  
     2.7 +class MulTest(BeDOZaTestCase): 
     2.8 +    num_players = 3
     2.9 +
    2.10 +    timeout = 10
    2.11 +        
    2.12 +    @protocol
    2.13 +    def test_mul_computes_correct_result(self, runtime):
    2.14 +        p = 17
    2.15 +        random = Random(283883)        
    2.16 +        triple_generator = TripleGenerator(runtime, p, random)
    2.17 +
    2.18 +        Zp = GF(p)
    2.19 +
    2.20 +        a1 = Zp(6)
    2.21 +        b2 = Zp(7)
    2.22 +        c2 = triple_generator.paillier.encrypt(b2.value, 2)
    2.23 +        
    2.24 +        if runtime.id == 1:
    2.25 +            r1 = triple_generator._mul(1, 2, a1, c2)
    2.26 +            def check1(partialShare):
    2.27 +                zi = triple_generator.paillier.decrypt(partialShare.enc_shares[0])
    2.28 +                self.assertEquals(partialShare.value.value, zi)
    2.29 +                pc = tuple(runtime.program_counter)
    2.30 +                runtime.protocols[2].sendData(pc, TEXT, str(zi))
    2.31 +                return True
    2.32 +            r1.addCallback(check1)
    2.33 +            return r1
    2.34 +        else:
    2.35 +            r1 = triple_generator._mul(1, 2)
    2.36 +            def check(partialShare):
    2.37 +                if runtime.id == 2:
    2.38 +                    zj = triple_generator.paillier.decrypt(partialShare.enc_shares[1])
    2.39 +                    self.assertEquals(partialShare.value.value, zj)
    2.40 +                    def check_additivity(zi, zj):
    2.41 +                        self.assertEquals((Zp(long(zi)) + zj).value, 8)
    2.42 +                        return None
    2.43 +                    d = Deferred()
    2.44 +                    d.addCallback(check_additivity, partialShare.value)
    2.45 +                    runtime._expect_data(1, TEXT, d)
    2.46 +                    return d
    2.47 +                else:
    2.48 +                    self.assertEquals(partialShare.value, 0)
    2.49 +                    self.assertNotEquals(partialShare.enc_shares[0], 0)
    2.50 +                    self.assertNotEquals(partialShare.enc_shares[1], 0)
    2.51 +                    self.assertEquals(partialShare.enc_shares[2], 1)
    2.52 +                return True
    2.53 +            r1.addCallback(check)
    2.54 +            return r1
    2.55 +
    2.56 +    @protocol
    2.57 +    def test_mul_same_player_inputs_and_receives(self, runtime):
    2.58 +        p = 17
    2.59 +        random = Random(283883)        
    2.60 +        triple_generator = TripleGenerator(runtime, p, random)
    2.61 +
    2.62 +        Zp = GF(p)
    2.63 +
    2.64 +        a1 = Zp(6)
    2.65 +        b2 = Zp(7)
    2.66 +        c2 = triple_generator.paillier.encrypt(b2.value, 2)
    2.67 +        
    2.68 +        r1 = triple_generator._mul(2, 2, a1, c2)
    2.69 +        def check(partialShareContents):
    2.70 +            if runtime.id == 2:
    2.71 +                zi_enc = Zp(triple_generator.paillier.decrypt(partialShareContents.enc_shares[1]))
    2.72 +                self.assertEquals(zi_enc, partialShareContents.value)
    2.73 +                self.assertEquals(partialShareContents.value, 8)
    2.74 +            return True
    2.75 +            
    2.76 +        r1.addCallback(check)
    2.77 +        return r1
    2.78 +
    2.79 +
    2.80  missing_package = None
    2.81  if not pypaillier:
    2.82      missing_package = "pypaillier"