viff

changeset 1504:129b326c3ff1

BeDOZa: Implemented preprocessing fullmul method.
author Janus Dam Nielsen <janus.nielsen@alexandra.dk>
date Mon, 19 Jul 2010 10:46:09 +0200
parents b120a9dee885
children 60cbf0d030c7
files viff/bedoza_triple.py viff/test/test_bedoza_triple.py
diffstat 2 files changed, 94 insertions(+), 5 deletions(-) [+]
line diff
     1.1 --- a/viff/bedoza_triple.py	Mon Jul 19 10:42:37 2010 +0200
     1.2 +++ b/viff/bedoza_triple.py	Mon Jul 19 10:46:09 2010 +0200
     1.3 @@ -54,6 +54,8 @@
     1.4      Works as default for integers. If other stuff has to be
     1.5      sent, supply another serialization, deserialition.
     1.6      """
     1.7 +    runtime.increment_pc()
     1.8 +    
     1.9      pc = tuple(runtime.program_counter)
    1.10      for p in runtime.players:
    1.11          msg = serialize(vals[p - 1])
    1.12 @@ -85,8 +87,6 @@
    1.13                   deserialize=lambda x: gf_elm.field(int(x)))
    1.14  
    1.15  
    1.16 -
    1.17 -
    1.18  class PartialShareContents(object):
    1.19      """A BeDOZa share without macs, e.g. < a >.
    1.20      TODO: BeDOZaShare should extend this class?
    1.21 @@ -104,6 +104,13 @@
    1.22      def __str__(self):
    1.23          return "PartialShareContents(%d; %s; %s)" % (self.value, self.enc_shares, self.N_squared_list)
    1.24  
    1.25 +    def __add__(self, other):
    1.26 +        z = self.value + other.value
    1.27 +        z_enc_shares = []
    1.28 +        for x, y, N_squared in zip(self.enc_shares, other.enc_shares, self.N_squared_list):
    1.29 +            z_enc_shares.append((x * y) % N_squared)
    1.30 +        return PartialShareContents(z, z_enc_shares, self.N_squared_list)
    1.31 +
    1.32  # In VIFF, callbacks get the *contents* of a share as input. Hence, in order
    1.33  # to get a PartialShare as input to callbacks, we need this extra level of
    1.34  # wrapper indirection.
    1.35 @@ -343,9 +350,27 @@
    1.36          r.addCallback(wrap, inx, jnx)
    1.37          return r
    1.38  
    1.39 -    
    1.40 -    def _full_mul(self):
    1.41 -        pass
    1.42 +    def _full_mul(self, a, b):
    1.43 +        self.runtime.increment_pc()
    1.44 +        
    1.45 +        def do_full_mul((contents_a, contents_b)):
    1.46 +            deferreds = []
    1.47 +            for inx in xrange(0, len(self.runtime.players)):
    1.48 +                for jnx in xrange(0, len(self.runtime.players)):
    1.49 +                    deferreds.append(self._mul(inx + 1, jnx + 1, contents_a.value, contents_b.enc_shares[jnx]))
    1.50 +            def compute_share(partialShares):
    1.51 +                partialShareContents = reduce(lambda x, y: x + y, partialShares)
    1.52 +                pid = self.runtime.id
    1.53 +                share = partialShareContents.enc_shares[pid - 1]
    1.54 +                share = self.paillier.decrypt(share)
    1.55 +                share = self.Zp(share)
    1.56 +                return PartialShare(self.runtime, partialShareContents.value, partialShareContents.enc_shares)
    1.57 +            d = gatherResults(deferreds)
    1.58 +            d.addCallback(compute_share)
    1.59 +            return d
    1.60 +        s = gatherResults([a, b])
    1.61 +        self.runtime.schedule_callback(s, do_full_mul)
    1.62 +        return s
    1.63  
    1.64  
    1.65  # TODO: Represent all numbers by GF objects, Zp, Zn, etc.
     2.1 --- a/viff/test/test_bedoza_triple.py	Mon Jul 19 10:42:37 2010 +0200
     2.2 +++ b/viff/test/test_bedoza_triple.py	Mon Jul 19 10:46:09 2010 +0200
     2.3 @@ -18,6 +18,8 @@
     2.4  import sys
     2.5  from exceptions import AssertionError
     2.6  
     2.7 +import operator
     2.8 +
     2.9  # We don't need secure random numbers for test purposes.
    2.10  from random import Random
    2.11  
    2.12 @@ -390,6 +392,68 @@
    2.13          return r1
    2.14  
    2.15  
    2.16 +class FullMulTest(BeDOZaTestCase): 
    2.17 +    num_players = 3
    2.18 +    
    2.19 +    @protocol
    2.20 +    def test_fullmul_computes_the_correct_result(self, runtime):
    2.21 +        p = 17
    2.22 +
    2.23 +        Zp = GF(p)
    2.24 +        
    2.25 +        random = Random(283883)        
    2.26 +        triple_generator = TripleGenerator(runtime, p, random)
    2.27 +
    2.28 +        paillier = triple_generator.paillier
    2.29 +        
    2.30 +        share_a = partial_share(random, runtime, GF(p), 6, paillier=paillier)
    2.31 +        share_b = partial_share(random, runtime, GF(p), 7, paillier=paillier)
    2.32 +
    2.33 +        share_z = triple_generator._full_mul(share_a, share_b)
    2.34 +        def check(share):
    2.35 +            def test_sum(ls):
    2.36 +                vals = ls[0]
    2.37 +                self.assertEquals(8, Zp(sum(vals)))
    2.38 +            value = _convolute(runtime, share.value.value)
    2.39 +            runtime.schedule_callback(gatherResults([value]), test_sum)
    2.40 +            return True
    2.41 +            
    2.42 +        share_z.addCallback(check)
    2.43 +        return share_z
    2.44 +
    2.45 +    @protocol
    2.46 +    def test_fullmul_encrypted_values_are_the_same_as_the_share(self, runtime):
    2.47 +        p = 17
    2.48 +
    2.49 +        Zp = GF(p)
    2.50 +        
    2.51 +        random = Random(283883)        
    2.52 +        triple_generator = TripleGenerator(runtime, p, random)
    2.53 +
    2.54 +        paillier = triple_generator.paillier
    2.55 +        
    2.56 +        share_a = partial_share(random, runtime, GF(p), 6, paillier=paillier)
    2.57 +        share_b = partial_share(random, runtime, GF(p), 7, paillier=paillier)
    2.58 +
    2.59 +        share_z = triple_generator._full_mul(share_a, share_b)
    2.60 +        def check(share):
    2.61 +            def test_enc(enc_shares, value):
    2.62 +                all_the_same, zi_enc = reduce(lambda x, y: (x[0] and x[1] == y, y), enc_shares, (True, enc_shares[0]))
    2.63 +                zi_enc = triple_generator.paillier.decrypt(zi_enc)
    2.64 +                self.assertEquals(value, Zp(zi_enc))
    2.65 +                return True
    2.66 +            all_enc_shares = []
    2.67 +            for inx, enc_share in enumerate(share.enc_shares):
    2.68 +                d = _convolute(runtime, enc_share)
    2.69 +                if runtime.id == inx + 1:
    2.70 +                    d.addCallback(test_enc, share.value)
    2.71 +                all_enc_shares.append(d)
    2.72 +            return gatherResults(all_enc_shares)
    2.73 +            
    2.74 +        share_z.addCallback(check)
    2.75 +        return share_z
    2.76 +
    2.77 +
    2.78  missing_package = None
    2.79  if not pypaillier:
    2.80      missing_package = "pypaillier"