viff

changeset 1516:7beb12b97911

BeDOZa: Added a generate_random_shares method to PartialShareGenerator.
author Janus Dam Nielsen <janus.nielsen@alexandra.dk>
date Thu, 22 Jul 2010 12:21:19 +0200
parents 2fb1e2fc8707
children 054a27514891
files viff/bedoza_triple.py viff/test/test_bedoza_triple.py
diffstat 2 files changed, 67 insertions(+), 32 deletions(-) [+]
line diff
     1.1 --- a/viff/bedoza_triple.py	Wed Jul 21 15:09:55 2010 +0200
     1.2 +++ b/viff/bedoza_triple.py	Thu Jul 22 12:21:19 2010 +0200
     1.3 @@ -117,10 +117,13 @@
     1.4  # to get a PartialShare as input to callbacks, we need this extra level of
     1.5  # wrapper indirection.
     1.6  class PartialShare(Share):
     1.7 -    def __init__(self, runtime, value, enc_shares):
     1.8 -        N_squared_list = [ runtime.players[player_id].pubkey['n_square'] for player_id in runtime.players.keys()]
     1.9 -        partial_share_contents = PartialShareContents(value, enc_shares, N_squared_list)
    1.10 -        Share.__init__(self, runtime, value.field, partial_share_contents)
    1.11 +    def __init__(self, runtime, field, value=None, enc_shares=None):
    1.12 +        if value == None and enc_shares == None:
    1.13 +            Share.__init__(self, runtime, field)
    1.14 +        else:
    1.15 +            N_squared_list = [ runtime.players[player_id].pubkey['n_square'] for player_id in runtime.players.keys()]
    1.16 +            partial_share_contents = PartialShareContents(value, enc_shares, N_squared_list)
    1.17 +            Share.__init__(self, runtime, field, partial_share_contents)
    1.18  
    1.19  
    1.20  class PartialShareGenerator:
    1.21 @@ -143,10 +146,29 @@
    1.22          enc_share = self.paillier.encrypt(share.value)
    1.23          enc_shares = _convolute(self.runtime, enc_share)
    1.24          def create_partial_share(enc_shares, share):
    1.25 -            return PartialShare(self.runtime, share, enc_shares)
    1.26 +            return PartialShare(self.runtime, value.field, share, enc_shares)
    1.27          self.runtime.schedule_callback(enc_shares, create_partial_share, share)
    1.28          return enc_shares
    1.29  
    1.30 +    def generate_random_shares(self, n):
    1.31 +        self.runtime.increment_pc()
    1.32 +        N_squared_list = [ self.runtime.players[player_id].pubkey['n_square'] for player_id in self.runtime.players]
    1.33 +        shares = [PartialShare(self.runtime, self.Zp) for _ in xrange(n)]
    1.34 +        for inx in xrange(n):
    1.35 +            r = self.random.randint(0, self.Zp.modulus - 1)
    1.36 +            ri = self.Zp(r)
    1.37 +            enc_share = self.paillier.encrypt(ri.value)
    1.38 +            enc_shares = _convolute(self.runtime, enc_share)
    1.39 +            def create_partial_share(enc_shares, ri, s, N_squared_list):
    1.40 +                s.callback(PartialShareContents(ri, enc_shares, N_squared_list))
    1.41 +            self.runtime.schedule_callback(enc_shares,
    1.42 +                                           create_partial_share,
    1.43 +                                           ri,
    1.44 +                                           shares[inx],
    1.45 +                                           N_squared_list)
    1.46 +            
    1.47 +        return shares
    1.48 +
    1.49  class ModifiedPaillier(object):
    1.50      """A slight modification of the Paillier cryptosystem.
    1.51  
     2.1 --- a/viff/test/test_bedoza_triple.py	Wed Jul 21 15:09:55 2010 +0200
     2.2 +++ b/viff/test/test_bedoza_triple.py	Thu Jul 22 12:21:19 2010 +0200
     2.3 @@ -31,7 +31,7 @@
     2.4  from viff.config import generate_configs
     2.5  from viff.bedoza import BeDOZaRuntime, BeDOZaShare, BeDOZaKeyList
     2.6  
     2.7 -from viff.bedoza_triple import TripleGenerator, PartialShare, PartialShareContents, ModifiedPaillier
     2.8 +from viff.bedoza_triple import TripleGenerator, PartialShare, PartialShareContents, ModifiedPaillier, PartialShareGenerator
     2.9  from viff.bedoza_triple import _send, _convolute, _convolute_gf_elm
    2.10  
    2.11  from viff.field import FieldElement, GF
    2.12 @@ -68,31 +68,6 @@
    2.13      print "player%d ------> %s" % (rt.id, msg)
    2.14  
    2.15  
    2.16 -# TODO: Code duplication. There should be only one share generator, it should
    2.17 -# be placed along with the tests, and it should be able to generate partial
    2.18 -# as well as full bedoza shares.
    2.19 -class PartialShareGenerator:
    2.20 -
    2.21 -    def __init__(self, Zp, runtime, random, paillier):
    2.22 -        self.paillier = paillier
    2.23 -        self.Zp = Zp
    2.24 -        self.runtime = runtime
    2.25 -        self.random = random
    2.26 -
    2.27 -    def generate_share(self, value):
    2.28 -        r = [self.Zp(self.random.randint(0, self.Zp.modulus - 1)) # TODO: Exclusve?
    2.29 -             for _ in range(self.runtime.num_players - 1)]
    2.30 -        if self.runtime.id == 1:
    2.31 -            share = value - sum(r)
    2.32 -        else:
    2.33 -            share = r[self.runtime.id - 2]
    2.34 -        enc_share = self.paillier.encrypt(share.value)
    2.35 -        enc_shares = _convolute(self.runtime, enc_share)
    2.36 -        def create_partial_share(enc_shares, share):
    2.37 -            return PartialShare(self.runtime, share, enc_shares)
    2.38 -        self.runtime.schedule_callback(enc_shares, create_partial_share, share)
    2.39 -        return enc_shares
    2.40 -
    2.41  class BeDOZaTestCase(RuntimeTestCase):
    2.42  
    2.43      runtime_class = BeDOZaRuntime
    2.44 @@ -226,6 +201,14 @@
    2.45      gen = PartialShareGenerator(Zp, runtime, share_random, paillier)
    2.46      return gen.generate_share(Zp(val))
    2.47  
    2.48 +def partial_random_shares(random, runtime, Zp, n, paillier=None):
    2.49 +    if not paillier:
    2.50 +        paillier_random = Random(random.getrandbits(128))
    2.51 +        paillier = ModifiedPaillier(runtime, paillier_random)
    2.52 +    share_random = Random(random.getrandbits(128))
    2.53 +    gen = PartialShareGenerator(Zp, runtime, share_random, paillier)
    2.54 +    return gen.generate_random_shares(n)
    2.55 +
    2.56  
    2.57  class ParialShareGeneratorTest(BeDOZaTestCase):
    2.58      num_players = 3
    2.59 @@ -251,7 +234,6 @@
    2.60          runtime.schedule_callback(share, convolute)
    2.61          return share
    2.62  
    2.63 -
    2.64      @protocol
    2.65      def test_encrypted_shares_decrypt_correctly(self, runtime):
    2.66          random = Random(3423993)
    2.67 @@ -268,6 +250,37 @@
    2.68          runtime.schedule_callback(share, decrypt)
    2.69          return share
    2.70  
    2.71 +    @protocol
    2.72 +    def test_random_shares_have_correct_type(self, runtime):
    2.73 +        Zp = GF(23)
    2.74 +        shares = partial_random_shares(Random(23499), runtime, Zp, 7)
    2.75 +        for share in shares:
    2.76 +            def test(share):
    2.77 +                self.assertEquals(Zp, share.value.field)
    2.78 +            runtime.schedule_callback(share, test)
    2.79 +            
    2.80 +        return shares
    2.81 + 
    2.82 +    @protocol
    2.83 +    def test_encrypted_random_shares_decrypt_correctly(self, runtime):
    2.84 +        random = Random(3423993)
    2.85 +        modulus = 17
    2.86 +        Zp = GF(modulus)
    2.87 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
    2.88 +        shares = partial_random_shares(random, runtime, Zp, 7, paillier=paillier)
    2.89 +        expected_result = [9,16,7,12,3,5,6]
    2.90 +        for inx, share in enumerate(shares):
    2.91 +            def decrypt(share, expected_result):
    2.92 +                decrypted_share = paillier.decrypt(share.enc_shares[runtime.id - 1])
    2.93 +                decrypted_shares = _convolute(runtime, decrypted_share)
    2.94 +                def test_sum(vals, expected_result):
    2.95 +                    v = Zp(sum(vals))
    2.96 +                    self.assertEquals(expected_result, v)
    2.97 +                runtime.schedule_callback(decrypted_shares, test_sum, expected_result)
    2.98 +            runtime.schedule_callback(share, decrypt, expected_result[inx])
    2.99 +            
   2.100 +        return shares
   2.101 +
   2.102  
   2.103  class TripleTest(BeDOZaTestCase): 
   2.104      num_players = 3