viff

changeset 1549:9a89c3397c9a

BeDOZa: Moved tests to separate folder.
author Thomas P Jakobsen <tpj@cs.au.dk>
date Thu, 23 Sep 2010 10:07:35 +0200
parents 6191f86d814b
children c8e7c5ee1583
files viff/test/bedoza/__init__.py viff/test/bedoza/test_bedoza_runtime.py viff/test/bedoza/test_bedoza_triple.py viff/test/test_bedoza_runtime.py viff/test/test_bedoza_triple.py
diffstat 5 files changed, 1213 insertions(+), 1197 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/viff/test/bedoza/__init__.py	Thu Sep 23 10:07:35 2010 +0200
     1.3 @@ -0,0 +1,16 @@
     1.4 +# Copyright 2007, 2010 VIFF Development Team.
     1.5 +#
     1.6 +# This file is part of VIFF, the Virtual Ideal Functionality Framework.
     1.7 +#
     1.8 +# VIFF is free software: you can redistribute it and/or modify it
     1.9 +# under the terms of the GNU Lesser General Public License (LGPL) as
    1.10 +# published by the Free Software Foundation, either version 3 of the
    1.11 +# License, or (at your option) any later version.
    1.12 +#
    1.13 +# VIFF is distributed in the hope that it will be useful, but WITHOUT
    1.14 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    1.15 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
    1.16 +# Public License for more details.
    1.17 +#
    1.18 +# You should have received a copy of the GNU Lesser General Public
    1.19 +# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/viff/test/bedoza/test_bedoza_runtime.py	Thu Sep 23 10:07:35 2010 +0200
     2.3 @@ -0,0 +1,562 @@
     2.4 +# Copyright 2010 VIFF Development Team.
     2.5 +#
     2.6 +# This file is part of VIFF, the Virtual Ideal Functionality Framework.
     2.7 +#
     2.8 +# VIFF is free software: you can redistribute it and/or modify it
     2.9 +# under the terms of the GNU Lesser General Public License (LGPL) as
    2.10 +# published by the Free Software Foundation, either version 3 of the
    2.11 +# License, or (at your option) any later version.
    2.12 +#
    2.13 +# VIFF is distributed in the hope that it will be useful, but WITHOUT
    2.14 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    2.15 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
    2.16 +# Public License for more details.
    2.17 +#
    2.18 +# You should have received a copy of the GNU Lesser General Public
    2.19 +# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    2.20 +
    2.21 +import sys
    2.22 +
    2.23 +# We don't need secure random numbers for test purposes.
    2.24 +from random import Random
    2.25 +
    2.26 +from twisted.internet.defer import gatherResults, DeferredList
    2.27 +
    2.28 +from viff.test.util import RuntimeTestCase, protocol
    2.29 +from viff.runtime import gather_shares, Share
    2.30 +from viff.config import generate_configs
    2.31 +from viff.bedoza.bedoza import BeDOZaRuntime
    2.32 +from viff.bedoza.shares import BeDOZaShare, BeDOZaShareContents
    2.33 +from viff.bedoza.keylist import BeDOZaKeyList
    2.34 +from viff.bedoza.maclist import BeDOZaMACList
    2.35 +from viff.field import FieldElement, GF
    2.36 +from viff.util import rand
    2.37 +from viff.bedoza.modified_paillier import ModifiedPaillier
    2.38 +from viff.bedoza.share_generators import ShareGenerator
    2.39 +from viff.bedoza.bedoza_triple import TripleGenerator
    2.40 +from viff.bedoza.zero_knowledge import ZKProof
    2.41 +
    2.42 +# The PyPaillier and commitment packages are not standard parts of VIFF so we
    2.43 +# skip them instead of letting them fail if the packages are not available. 
    2.44 +try:
    2.45 +    import pypaillier
    2.46 +except ImportError:
    2.47 +    pypaillier = None
    2.48 +
    2.49 +# HACK: The paillier keys that are available as standard in VIFF tests
    2.50 +# are not suited for use with pypaillier. Hence, we use NaClPaillier
    2.51 +# to generate test keys. This confusion will disappear when pypaillier
    2.52 +# replaces the current Python-based paillier implementation.
    2.53 +from viff.paillierutil import NaClPaillier
    2.54 +
    2.55 +# HACK^2: Currently, the NaClPaillier hack only works when triple is
    2.56 +# imported. It should ideally work without the triple package.
    2.57 +try:
    2.58 +    import tripple
    2.59 +except ImportError:
    2.60 +    tripple = None
    2.61 +
    2.62 +
    2.63 +class BeDOZaBasicCommandsTest(RuntimeTestCase):
    2.64 +    """Test for basic commands."""
    2.65 +
    2.66 +    # Number of players.
    2.67 +    num_players = 3
    2.68 +
    2.69 +    timeout = 3
    2.70 +
    2.71 +    runtime_class = BeDOZaRuntime
    2.72 +
    2.73 +    # TODO: During test, we would like generation of Paillier keys to
    2.74 +    # be deterministic. How do we obtain that?
    2.75 +    def generate_configs(self, *args):
    2.76 +        # In production, paillier keys should be something like 2000
    2.77 +        # bit. For test purposes, it is ok to use small keys.
    2.78 +        # TODO: paillier freezes if key size is too small, e.g. 13.
    2.79 +        return generate_configs(paillier=NaClPaillier(250), *args)
    2.80 +
    2.81 +    def setUp(self):
    2.82 +        RuntimeTestCase.setUp(self)
    2.83 +        self.Zp = GF(17)
    2.84 +        bits_in_p = 5
    2.85 +        self.security_parameter = 32
    2.86 +        self.u_bound = 2**(self.security_parameter + 4 * bits_in_p)
    2.87 +        self.alpha = 15
    2.88 +
    2.89 +    @protocol
    2.90 +    def test_plus(self, runtime):
    2.91 +        """Test addition of two numbers."""
    2.92 +
    2.93 +        Zp = self.Zp
    2.94 +       
    2.95 +        x = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(3), Zp(4), Zp(1)]), BeDOZaMACList([Zp(2), Zp(74), Zp(23), Zp(2)]))
    2.96 +        y = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(5), Zp(2), Zp(7)]), BeDOZaMACList([Zp(2), Zp(74), Zp(23), Zp(2)]))
    2.97 +        z = runtime._plus((x, y), Zp)
    2.98 +        self.assertEquals(z.get_value(), Zp(4))
    2.99 +        self.assertEquals(z.get_keys(), BeDOZaKeyList(Zp(23), [Zp(8), Zp(6), Zp(8)]))
   2.100 +        self.assertEquals(z.get_macs(), BeDOZaMACList([Zp(4), Zp(148), Zp(46), Zp(4)]))
   2.101 +
   2.102 +    @protocol
   2.103 +    def test_sum(self, runtime):
   2.104 +        """Test addition of two numbers."""       
   2.105 +
   2.106 +        def check(v):
   2.107 +            self.assertEquals(v, 0)
   2.108 +
   2.109 +        random = Random(3423993)
   2.110 +        share_random = Random(random.getrandbits(128))
   2.111 +        
   2.112 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.113 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.114 +                             paillier, self.u_bound, self.alpha)
   2.115 +        
   2.116 +        x2 = gen.generate_share(8)
   2.117 +        y2 = gen.generate_share(9)
   2.118 +        z2 = runtime.add(x2, y2)
   2.119 +        d = runtime.open(z2)
   2.120 +        d.addCallback(check)
   2.121 +        return d
   2.122 +
   2.123 +    @protocol
   2.124 +    def test_sum_plus(self, runtime):
   2.125 +        """Test addition of two numbers."""
   2.126 +
   2.127 +        def check(v):
   2.128 +            self.assertEquals(v, 11)
   2.129 +
   2.130 +        random = Random(3423993)
   2.131 +        share_random = Random(random.getrandbits(128))
   2.132 +        
   2.133 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.134 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.135 +                             paillier, self.u_bound, self.alpha)
   2.136 +        
   2.137 +        x2 = gen.generate_share(2)
   2.138 +        y2 = gen.generate_share(9)
   2.139 +        z2 = x2 + y2
   2.140 +        d = runtime.open(z2)
   2.141 +        d.addCallback(check)
   2.142 +        return d
   2.143 +
   2.144 +    @protocol
   2.145 +    def test_sum_constant_right(self, runtime):
   2.146 +        """Test addition of secret shared number and a public number."""
   2.147 +
   2.148 +        y1 = 7
   2.149 +
   2.150 +        def check(v):
   2.151 +            self.assertEquals(v, 15)
   2.152 +
   2.153 +        random = Random(3423993)
   2.154 +        share_random = Random(random.getrandbits(128))
   2.155 +        
   2.156 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.157 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.158 +                             paillier, self.u_bound, self.alpha)
   2.159 +        
   2.160 +        x2 = gen.generate_share(8)
   2.161 +        z2 = x2 + y1
   2.162 +        d = runtime.open(z2)
   2.163 +        d.addCallback(check)
   2.164 +        return d
   2.165 +
   2.166 +    @protocol
   2.167 +    def test_sum_constant_left(self, runtime):
   2.168 +        """Test addition of a public number and secret shared number."""
   2.169 +
   2.170 +        y1 = 7
   2.171 +
   2.172 +        def check(v):
   2.173 +            self.assertEquals(v, 15)
   2.174 +
   2.175 +        random = Random(3423993)
   2.176 +        share_random = Random(random.getrandbits(128))
   2.177 +        
   2.178 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.179 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.180 +                             paillier, self.u_bound, self.alpha)
   2.181 +        
   2.182 +        x2 = gen.generate_share(8)
   2.183 +        z2 = y1 + x2
   2.184 +        d = runtime.open(z2)
   2.185 +        d.addCallback(check)
   2.186 +        return d
   2.187 +
   2.188 +    @protocol
   2.189 +    def test_minus(self, runtime):
   2.190 +        """Test subtraction of two numbers."""
   2.191 +
   2.192 +        Zp = self.Zp
   2.193 +       
   2.194 +        x = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(5), Zp(4), Zp(7)]), BeDOZaMACList([Zp(2), Zp(75), Zp(23), Zp(2)]))
   2.195 +        y = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(3), Zp(2), Zp(1)]), BeDOZaMACList([Zp(2), Zp(74), Zp(23), Zp(2)]))
   2.196 +        z = runtime._minus((x, y), Zp)
   2.197 +        self.assertEquals(z.get_value(), Zp(0))
   2.198 +        self.assertEquals(z.get_keys(), BeDOZaKeyList(Zp(23), [Zp(2), Zp(2), Zp(6)]))
   2.199 +        self.assertEquals(z.get_macs(), BeDOZaMACList([Zp(0), Zp(1), Zp(0), Zp(0)]))
   2.200 +
   2.201 +    @protocol
   2.202 +    def test_sub(self, runtime):
   2.203 +        """Test subtraction of two numbers."""
   2.204 +
   2.205 +        def check(v):
   2.206 +            self.assertEquals(v, 1)
   2.207 +
   2.208 +        random = Random(3423993)
   2.209 +        share_random = Random(random.getrandbits(128))
   2.210 +        
   2.211 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.212 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.213 +                             paillier, self.u_bound, self.alpha)
   2.214 +        
   2.215 +        x2 = gen.generate_share(9)
   2.216 +        y2 = gen.generate_share(8)
   2.217 +        z2 = runtime.sub(x2, y2)
   2.218 +        d = runtime.open(z2)
   2.219 +        d.addCallback(check)
   2.220 +        return d
   2.221 +
   2.222 +    @protocol
   2.223 +    def test_sub_minus(self, runtime):
   2.224 +        """Test subtraction of two numbers."""
   2.225 +
   2.226 +        def check(v):
   2.227 +            self.assertEquals(v, 1)
   2.228 +
   2.229 +        random = Random(3423993)
   2.230 +        share_random = Random(random.getrandbits(128))
   2.231 +        
   2.232 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.233 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.234 +                             paillier, self.u_bound, self.alpha)
   2.235 +        
   2.236 +        x2 = gen.generate_share(9)
   2.237 +        y2 = gen.generate_share(8)
   2.238 +        z2 = x2 - y2
   2.239 +        d = runtime.open(z2)
   2.240 +        d.addCallback(check)
   2.241 +        return d
   2.242 +
   2.243 +    @protocol
   2.244 +    def test_sub_constant_right(self, runtime):
   2.245 +        """Test subtraction of secret shared number and a public number."""
   2.246 +
   2.247 +        y = 4
   2.248 +
   2.249 +        def check(v):
   2.250 +            self.assertEquals(v, 4)
   2.251 +
   2.252 +        random = Random(3423993)
   2.253 +        share_random = Random(random.getrandbits(128))
   2.254 +        
   2.255 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.256 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.257 +                             paillier, self.u_bound, self.alpha)
   2.258 +        
   2.259 +        x2 = gen.generate_share(8)
   2.260 +        z2 = x2 - y
   2.261 +        d = runtime.open(x2)
   2.262 +        d.addCallback(check)
   2.263 +        return d
   2.264 +
   2.265 +    @protocol
   2.266 +    def test_sub_constant_left(self, runtime):
   2.267 +        """Test subtraction of a public number and secret shared number."""
   2.268 +
   2.269 +        y = 8
   2.270 +
   2.271 +        def check(v):
   2.272 +            self.assertEquals(v, 3)
   2.273 +
   2.274 +        random = Random(3423993)
   2.275 +        share_random = Random(random.getrandbits(128))
   2.276 +        
   2.277 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.278 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.279 +                             paillier, self.u_bound, self.alpha)
   2.280 +        
   2.281 +        x2 = gen.generate_share(5)
   2.282 +        z2 = y - x2
   2.283 +        d = runtime.open(x2)
   2.284 +        d.addCallback(check)
   2.285 +        return d
   2.286 +
   2.287 +    @protocol
   2.288 +    def test_constant_multiplication_constant_left(self, runtime):
   2.289 +        """Test multiplication of two numbers."""
   2.290 +
   2.291 +        x1 = 6
   2.292 +        y1 = 7
   2.293 +
   2.294 +        def check(v):
   2.295 +            self.assertEquals(v, self.Zp(x1 * y1))
   2.296 +
   2.297 +        random = Random(3423993)
   2.298 +        share_random = Random(random.getrandbits(128))
   2.299 +        
   2.300 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.301 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.302 +                             paillier, self.u_bound, self.alpha)
   2.303 +        
   2.304 +        x2 = gen.generate_share(x1)
   2.305 +
   2.306 +        z2 = runtime._cmul(self.Zp(y1), x2, self.Zp)
   2.307 +        d = runtime.open(z2)
   2.308 +        d.addCallback(check)
   2.309 +        return d
   2.310 +
   2.311 +    @protocol
   2.312 +    def test_constant_multiplication_constant_right(self, runtime):
   2.313 +        """Test multiplication of two numbers."""
   2.314 +
   2.315 +        x1 = 6
   2.316 +        y1 = 7
   2.317 +
   2.318 +        def check(v):
   2.319 +            self.assertEquals(v, self.Zp(x1 * y1))
   2.320 +
   2.321 +        random = Random(3423993)
   2.322 +        share_random = Random(random.getrandbits(128))
   2.323 +        
   2.324 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.325 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.326 +                             paillier, self.u_bound, self.alpha)
   2.327 +        
   2.328 +        x2 = gen.generate_share(x1)
   2.329 +
   2.330 +        z2 = runtime._cmul(x2, self.Zp(y1), self.Zp)
   2.331 +        d = runtime.open(z2)
   2.332 +        d.addCallback(check)
   2.333 +        return d
   2.334 +
   2.335 +    @protocol
   2.336 +    def test_get_triple(self, runtime):
   2.337 +        """Test generation of a triple."""
   2.338 +
   2.339 +        def check((a, b, c)):
   2.340 +            self.assertEquals(c, a * b)
   2.341 +
   2.342 +        def open(triple):
   2.343 +            d1 = runtime.open(triple.a)
   2.344 +            d2 = runtime.open(triple.b)
   2.345 +            d3 = runtime.open(triple.c)
   2.346 +            d = gather_shares([d1, d2, d3])
   2.347 +            d.addCallback(check)
   2.348 +            return d
   2.349 +
   2.350 +        random = Random(3423993)
   2.351 +        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, random)
   2.352 +        [triple] = gen.generate_triples(1)
   2.353 +        triple.addCallback(open)
   2.354 +        return triple
   2.355 +
   2.356 +    @protocol
   2.357 +    def test_basic_multiply(self, runtime):
   2.358 +        """Test multiplication of two numbers."""
   2.359 +
   2.360 +        x1 = 6
   2.361 +        y1 = 6
   2.362 +
   2.363 +        def check(v):
   2.364 +            self.assertEquals(v, self.Zp(x1 * y1))
   2.365 +
   2.366 +        def do_stuff(triple, alpha):
   2.367 +            random = Random(3423993)
   2.368 +            share_random = Random(random.getrandbits(128))
   2.369 +        
   2.370 +            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.371 +            gen = ShareGenerator(self.Zp, runtime, share_random,
   2.372 +                                 paillier, self.u_bound, alpha)
   2.373 +        
   2.374 +            x2 = gen.generate_share(x1)
   2.375 +            y2 = gen.generate_share(y1)
   2.376 +            z2 = runtime._basic_multiplication(x2, y2,
   2.377 +                                               triple.a,
   2.378 +                                               triple.b,
   2.379 +                                               triple.c)
   2.380 +            d = runtime.open(z2)
   2.381 +            d.addCallback(check)
   2.382 +            return d
   2.383 +
   2.384 +        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   2.385 +        alpha = gen.alpha
   2.386 +        [triple] = gen.generate_triples(1)
   2.387 +        runtime.schedule_callback(triple, do_stuff, alpha)
   2.388 +        return triple
   2.389 +
   2.390 +    @protocol
   2.391 +    def test_mul_mul(self, runtime):
   2.392 +        """Test multiplication of two numbers."""
   2.393 +
   2.394 +        x1 = 6
   2.395 +        y1 = 6
   2.396 +
   2.397 +        def check(v):
   2.398 +            self.assertEquals(v, self.Zp(x1 * y1))
   2.399 +
   2.400 +        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   2.401 +        alpha = gen.alpha
   2.402 +        triples = gen.generate_triples(1)
   2.403 +        
   2.404 +        def do_mult(triples, alpha):
   2.405 +            runtime.triples = triples
   2.406 +            random = Random(3423993)
   2.407 +            share_random = Random(random.getrandbits(128))
   2.408 +            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.409 +            gen = ShareGenerator(self.Zp, runtime, share_random,
   2.410 +                                 paillier, self.u_bound, alpha)
   2.411 +        
   2.412 +            x2 = gen.generate_share(x1)
   2.413 +            y2 = gen.generate_share(y1)
   2.414 +        
   2.415 +            z2 = x2 * y2
   2.416 +            d = runtime.open(z2)
   2.417 +            d.addCallback(check)
   2.418 +            return d
   2.419 +        r = gatherResults(triples)
   2.420 +        runtime.schedule_callback(r, do_mult, alpha)
   2.421 +        return r
   2.422 +    
   2.423 +    @protocol
   2.424 +    def test_basic_multiply_constant_right(self, runtime):
   2.425 +        """Test multiplication of two numbers."""
   2.426 +
   2.427 +        x1 = 6
   2.428 +        y1 = 6
   2.429 +
   2.430 +        def check(v):
   2.431 +            self.assertEquals(v, self.Zp(x1 * y1))
   2.432 +
   2.433 +        def do_stuff(triple, alpha):
   2.434 +            random = Random(3423993)
   2.435 +            share_random = Random(random.getrandbits(128))
   2.436 +        
   2.437 +            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.438 +            gen = ShareGenerator(self.Zp, runtime, share_random,
   2.439 +                                 paillier, self.u_bound, alpha)
   2.440 +        
   2.441 +            x2 = gen.generate_share(x1)
   2.442 +            y2 = gen.generate_share(y1)
   2.443 +            z2 = runtime._basic_multiplication(x2, self.Zp(y1),
   2.444 +                                               triple.a,
   2.445 +                                               triple.b,
   2.446 +                                               triple.c)
   2.447 +            d = runtime.open(z2)
   2.448 +            d.addCallback(check)
   2.449 +            return d
   2.450 +
   2.451 +        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   2.452 +        alpha = gen.alpha
   2.453 +        [triple] = gen.generate_triples(1)
   2.454 +        runtime.schedule_callback(triple, do_stuff, alpha)
   2.455 +        return triple
   2.456 +
   2.457 +    @protocol
   2.458 +    def test_basic_multiply_constant_left(self, runtime):
   2.459 +        """Test multiplication of two numbers."""
   2.460 +
   2.461 +        x1 = 6
   2.462 +        y1 = 6
   2.463 +
   2.464 +        def check(v):
   2.465 +            self.assertEquals(v, self.Zp(x1 * y1))
   2.466 +
   2.467 +        def do_stuff(triple, alpha):
   2.468 +            random = Random(3423993)
   2.469 +            share_random = Random(random.getrandbits(128))
   2.470 +        
   2.471 +            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.472 +            gen = ShareGenerator(self.Zp, runtime, share_random,
   2.473 +                                 paillier, self.u_bound, alpha)
   2.474 +        
   2.475 +            x2 = gen.generate_share(x1)
   2.476 +            y2 = gen.generate_share(y1)
   2.477 +            z2 = runtime._basic_multiplication(self.Zp(x1), y2,
   2.478 +                                               triple.a,
   2.479 +                                               triple.b,
   2.480 +                                               triple.c)
   2.481 +            d = runtime.open(z2)
   2.482 +            d.addCallback(check)
   2.483 +            return d
   2.484 +
   2.485 +        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   2.486 +        alpha = gen.alpha
   2.487 +        [triple] = gen.generate_triples(1)
   2.488 +        runtime.schedule_callback(triple, do_stuff, alpha)
   2.489 +        return triple
   2.490 +
   2.491 +    @protocol
   2.492 +    def test_open_multiple_secret_share(self, runtime):
   2.493 +        """Test sharing and open of a number."""
   2.494 +
   2.495 +        def check(ls):
   2.496 +            for v in ls:
   2.497 +                self.assertEquals(v, 6)
   2.498 +
   2.499 +        random = Random(3423993)
   2.500 +        share_random = Random(random.getrandbits(128))
   2.501 +        
   2.502 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.503 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.504 +                             paillier, self.u_bound, self.alpha)
   2.505 +        
   2.506 +        x = gen.generate_share(6)
   2.507 +        y = gen.generate_share(6)
   2.508 +        d = runtime.open_multiple_values([x, y])
   2.509 +        d.addCallback(check)
   2.510 +        return d
   2.511 +
   2.512 +    @protocol
   2.513 +    def test_open_two_secret_share(self, runtime):
   2.514 +        """Test sharing and open of a number."""
   2.515 +
   2.516 +        def check((a, b)):
   2.517 +            self.assertEquals(a, 6)
   2.518 +            self.assertEquals(b, 6)
   2.519 +
   2.520 +        random = Random(3423993)
   2.521 +        share_random = Random(random.getrandbits(128))
   2.522 +        
   2.523 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   2.524 +        gen = ShareGenerator(self.Zp, runtime, share_random,
   2.525 +                             paillier, self.u_bound, self.alpha)
   2.526 +        
   2.527 +        x = gen.generate_share(6)
   2.528 +        y = gen.generate_share(6)
   2.529 +        d = runtime.open_two_values(x, y)
   2.530 +        d.addCallback(check)
   2.531 +        return d
   2.532 +
   2.533 +
   2.534 +# TODO: Move to test.bedoza.test_zero_knowledge.
   2.535 +class BeDOZaZeroKnowledgeTest(RuntimeTestCase):
   2.536 +
   2.537 +    num_players = 3
   2.538 +
   2.539 +    timeout = 3
   2.540 +
   2.541 +    runtime_class = BeDOZaRuntime
   2.542 +
   2.543 +    def test_zk_matrix_entries_are_correct(self):
   2.544 +        zk = ZKProof(None, None)
   2.545 +        zk._set_e([1, 0, 0, 1, 1])
   2.546 +        for i in range(zk.s):
   2.547 +            for j in range(zk.m):
   2.548 +                if j >= i and j < i + zk.s:
   2.549 +                    self.assertEquals(zk.e[j - i], zk._E(j, i))
   2.550 +                else:
   2.551 +                    self.assertEquals(0, zk._E(j, i))
   2.552 +
   2.553 +    def test_vec_pow_is_correct(self):
   2.554 +        Zn = GF(17)
   2.555 +        y = [Zn(i) for i in range(1, 6)]
   2.556 +        zk = ZKProof(None, Zn)
   2.557 +        zk._set_e([1, 0, 1, 1, 0])
   2.558 +        y_pow_E = zk.vec_pow_E(y)
   2.559 +        self.assertEquals([Zn(v) for v in [1, 2, 3, 8, 13, 12, 3, 5, 1]],
   2.560 +                          y_pow_E)
   2.561 +def skip_tests(module_name):
   2.562 +    BeDOZaBasicCommandsTest.skip = "Skipped due to missing " + module_name + " module."
   2.563 +
   2.564 +if not pypaillier:
   2.565 +    skip_tests("pypaillier")
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/viff/test/bedoza/test_bedoza_triple.py	Thu Sep 23 10:07:35 2010 +0200
     3.3 @@ -0,0 +1,635 @@
     3.4 +# Copyright 2010 VIFF Development Team.
     3.5 +#
     3.6 +# This file is part of VIFF, the Virtual Ideal Functionality Framework.
     3.7 +#
     3.8 +# VIFF is free software: you can redistribute it and/or modify it
     3.9 +# under the terms of the GNU Lesser General Public License (LGPL) as
    3.10 +# published by the Free Software Foundation, either version 3 of the
    3.11 +# License, or (at your option) any later version.
    3.12 +#
    3.13 +# VIFF is distributed in the hope that it will be useful, but WITHOUT
    3.14 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    3.15 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
    3.16 +# Public License for more details.
    3.17 +#
    3.18 +# You should have received a copy of the GNU Lesser General Public
    3.19 +# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    3.20 +
    3.21 +import sys
    3.22 +from exceptions import AssertionError
    3.23 +
    3.24 +import operator
    3.25 +
    3.26 +# We don't need secure random numbers for test purposes.
    3.27 +from random import Random
    3.28 +
    3.29 +from twisted.internet.defer import gatherResults, Deferred, DeferredList
    3.30 +
    3.31 +from viff.test.util import RuntimeTestCase, protocol
    3.32 +from viff.constants import TEXT
    3.33 +from viff.runtime import gather_shares, Share
    3.34 +from viff.config import generate_configs
    3.35 +
    3.36 +from viff.bedoza.bedoza import BeDOZaRuntime, BeDOZaShare
    3.37 +from viff.bedoza.keylist import BeDOZaKeyList
    3.38 +from viff.bedoza.bedoza_triple import TripleGenerator, ModifiedPaillier
    3.39 +from viff.bedoza.share_generators import PartialShareGenerator, ShareGenerator
    3.40 +from viff.bedoza.shares import PartialShare, PartialShareContents
    3.41 +from viff.bedoza.util import _send, _convolute, _convolute_gf_elm
    3.42 +from viff.bedoza.add_macs import add_macs
    3.43 +
    3.44 +from viff.field import FieldElement, GF
    3.45 +from viff.config import generate_configs
    3.46 +
    3.47 +
    3.48 +# Ok to use non-secure random generator in tests.
    3.49 +#from viff.util import rand
    3.50 +import random
    3.51 +
    3.52 +# The PyPaillier and commitment packages are not standard parts of VIFF so we
    3.53 +# skip them instead of letting them fail if the packages are not available. 
    3.54 +try:
    3.55 +    import pypaillier
    3.56 +except ImportError:
    3.57 +    pypaillier = None
    3.58 +
    3.59 +# HACK: The paillier keys that are available as standard in VIFF tests
    3.60 +# are not suited for use with pypaillier. Hence, we use NaClPaillier
    3.61 +# to generate test keys. This confusion will disappear when pypaillier
    3.62 +# replaces the current Python-based paillier implementation.
    3.63 +from viff.paillierutil import NaClPaillier
    3.64 +
    3.65 +# HACK^2: Currently, the NaClPaillier hack only works when triple is
    3.66 +# imported. It should ideally work without the triple package.
    3.67 +try:
    3.68 +    import tripple
    3.69 +except ImportError:
    3.70 +    tripple = None
    3.71 +
    3.72 +
    3.73 +
    3.74 +def _log(rt, msg):
    3.75 +    print "player%d ------> %s" % (rt.id, msg)
    3.76 +
    3.77 +
    3.78 +class BeDOZaTestCase(RuntimeTestCase):
    3.79 +
    3.80 +    runtime_class = BeDOZaRuntime
    3.81 +
    3.82 +    def setUp(self):
    3.83 +        RuntimeTestCase.setUp(self)
    3.84 +        self.security_parameter = 32
    3.85 +
    3.86 +    # TODO: During test, we would like generation of Paillier keys to
    3.87 +    # be deterministic. How do we obtain that?
    3.88 +    def generate_configs(self, *args):
    3.89 +        # In production, paillier keys should be something like 2000
    3.90 +        # bit. For test purposes, it is ok to use small keys.
    3.91 +        # TODO: paillier freezes if key size is too small, e.g. 13.
    3.92 +        return generate_configs(paillier=NaClPaillier(250), *args)
    3.93 +
    3.94 +
    3.95 +class DataTransferTest(BeDOZaTestCase):
    3.96 +    num_players = 3
    3.97 +
    3.98 +    @protocol
    3.99 +    def test_convolute_int(self, runtime):
   3.100 +        res = _convolute(runtime, runtime.id)
   3.101 +        def verify(result):
   3.102 +            self.assertEquals(runtime.players.keys(), result)
   3.103 +        runtime.schedule_callback(res, verify)
   3.104 +        return res
   3.105 +
   3.106 +    @protocol
   3.107 +    def test_send(self, runtime):
   3.108 +        msg_send = [100 * p + runtime.id for p in runtime.players]
   3.109 +        msg_receive = [100 * runtime.id + p for p in runtime.players]
   3.110 +        res = _send(runtime, msg_send)
   3.111 +        def verify(result):
   3.112 +            self.assertEquals(msg_receive, result)
   3.113 +        runtime.schedule_callback(res, verify)
   3.114 +        return res
   3.115 + 
   3.116 +    @protocol
   3.117 +    def test_convolute_field_element(self, runtime):
   3.118 +        Zp = GF(17)
   3.119 +        res = _convolute_gf_elm(runtime, Zp(runtime.id))
   3.120 +        def verify(result):
   3.121 +            self.assertEquals(runtime.players.keys(), result)
   3.122 +        runtime.schedule_callback(res, verify)
   3.123 +        return res
   3.124 +
   3.125 +
   3.126 +class ModifiedPaillierTest(BeDOZaTestCase):
   3.127 +    num_players = 3
   3.128 +
   3.129 +    @protocol
   3.130 +    def test_modified_paillier_can_decrypt_encrypted_one(self, runtime):
   3.131 +        paillier = ModifiedPaillier(runtime, Random(234838))
   3.132 +        val = 1
   3.133 +        encrypted_val = paillier.encrypt(val)
   3.134 +        decrypted_val = paillier.decrypt(encrypted_val)
   3.135 +        self.assertEquals(val, decrypted_val)
   3.136 +
   3.137 +    @protocol
   3.138 +    def test_modified_paillier_can_decrypt_encrypted_zero(self, runtime):
   3.139 +        paillier = ModifiedPaillier(runtime, Random(338301))
   3.140 +        val = 0
   3.141 +        encrypted_val = paillier.encrypt(val)
   3.142 +        decrypted_val = paillier.decrypt(encrypted_val)
   3.143 +        self.assertEquals(val, decrypted_val)
   3.144 +
   3.145 +    @protocol
   3.146 +    def test_modified_paillier_can_decrypt_encrypted_minus_one(self, runtime):
   3.147 +        paillier = ModifiedPaillier(runtime, Random(19623))
   3.148 +        val = -1
   3.149 +        encrypted_val = paillier.encrypt(val)
   3.150 +        decrypted_val = paillier.decrypt(encrypted_val)
   3.151 +        self.assertEquals(val, decrypted_val)
   3.152 +
   3.153 +    @protocol
   3.154 +    def test_modified_paillier_can_decrypt_encrypted_max_val(self, runtime):
   3.155 +        paillier = ModifiedPaillier(runtime, Random(825604))
   3.156 +        n = runtime.players[runtime.id].pubkey['n']
   3.157 +        val = (n - 1) / 2
   3.158 +        encrypted_val = paillier.encrypt(val)
   3.159 +        decrypted_val = paillier.decrypt(encrypted_val)
   3.160 +        self.assertEquals(val, decrypted_val)
   3.161 +
   3.162 +    @protocol
   3.163 +    def test_modified_paillier_can_decrypt_encrypted_min_val(self, runtime):
   3.164 +        paillier = ModifiedPaillier(runtime, Random(554424))
   3.165 +        n = runtime.players[runtime.id].pubkey['n']
   3.166 +        val = -(n - 1) / 2
   3.167 +        encrypted_val = paillier.encrypt(val)
   3.168 +        decrypted_val = paillier.decrypt(encrypted_val)
   3.169 +        self.assertEquals(val, decrypted_val)
   3.170 + 
   3.171 +    @protocol
   3.172 +    def test_modified_paillier_can_decrypt_encrypted_positive(self, runtime):
   3.173 +        paillier = ModifiedPaillier(runtime, Random(777737))
   3.174 +        val = 73423
   3.175 +        encrypted_val = paillier.encrypt(val)
   3.176 +        decrypted_val = paillier.decrypt(encrypted_val)
   3.177 +        self.assertEquals(val, decrypted_val)
   3.178 +
   3.179 +    @protocol
   3.180 +    def test_encrypting_too_large_number_raises_exception(self, runtime):
   3.181 +        paillier = ModifiedPaillier(runtime, Random(825604))
   3.182 +        n = runtime.players[runtime.id].pubkey['n']
   3.183 +        val = 1 + (n - 1) / 2
   3.184 +        self.assertRaises(AssertionError, paillier.encrypt, val)
   3.185 +
   3.186 +    @protocol
   3.187 +    def test_encrypting_too_small_number_raises_exception(self, runtime):
   3.188 +        paillier = ModifiedPaillier(runtime, Random(554424))
   3.189 +        n = runtime.players[runtime.id].pubkey['n']
   3.190 +        val = -(n - 1) / 2 - 1
   3.191 +        self.assertRaises(AssertionError, paillier.encrypt, val)
   3.192 +
   3.193 +    @protocol
   3.194 +    def test_modified_paillier_can_encrypt_to_other(self, runtime):
   3.195 +        paillier = ModifiedPaillier(runtime, Random(57503))
   3.196 +        msg = []
   3.197 +        for p in runtime.players:
   3.198 +            msg.append(paillier.encrypt(runtime.id, player_id=p))
   3.199 +        received = _send(runtime, msg)
   3.200 +        def verify(enc):
   3.201 +            plain = [paillier.decrypt(e) for e in enc]
   3.202 +            self.assertEquals(range(1, self.num_players + 1), plain)
   3.203 +        runtime.schedule_callback(received, verify)
   3.204 +        return received
   3.205 +
   3.206 +
   3.207 +def partial_share(random, runtime, Zp, val, paillier=None):
   3.208 +    if not paillier:
   3.209 +        paillier_random = Random(random.getrandbits(128))
   3.210 +        paillier = ModifiedPaillier(runtime, paillier_random)
   3.211 +    share_random = Random(random.getrandbits(128))
   3.212 +    gen = PartialShareGenerator(Zp, runtime, share_random, paillier)
   3.213 +    return gen.generate_share(Zp(val))
   3.214 +
   3.215 +def partial_random_shares(random, runtime, Zp, n, paillier=None):
   3.216 +    if not paillier:
   3.217 +        paillier_random = Random(random.getrandbits(128))
   3.218 +        paillier = ModifiedPaillier(runtime, paillier_random)
   3.219 +    share_random = Random(random.getrandbits(128))
   3.220 +    gen = PartialShareGenerator(Zp, runtime, share_random, paillier)
   3.221 +    return gen.generate_random_shares(n)
   3.222 +
   3.223 +class PartialShareGeneratorTest(BeDOZaTestCase):
   3.224 +    num_players = 3
   3.225 + 
   3.226 +    @protocol
   3.227 +    def test_shares_have_correct_type(self, runtime):
   3.228 +        Zp = GF(23)
   3.229 +        share = partial_share(Random(23499), runtime, Zp, 7)
   3.230 +        def test(share):
   3.231 +            self.assertEquals(Zp, share.value.field)
   3.232 +        runtime.schedule_callback(share, test)
   3.233 +        return share
   3.234 + 
   3.235 +    @protocol
   3.236 +    def test_shares_are_additive(self, runtime):
   3.237 +        secret = 7
   3.238 +        share = partial_share(Random(34993), runtime, GF(23), secret)
   3.239 +        def convolute(share):
   3.240 +            values = _convolute_gf_elm(runtime, share.value)
   3.241 +            def test_sum(vals):
   3.242 +                self.assertEquals(secret, sum(vals))
   3.243 +            runtime.schedule_callback(values, test_sum)
   3.244 +        runtime.schedule_callback(share, convolute)
   3.245 +        return share
   3.246 +
   3.247 +    @protocol
   3.248 +    def test_encrypted_shares_decrypt_correctly(self, runtime):
   3.249 +        random = Random(3423993)
   3.250 +        modulus = 17
   3.251 +        secret = 7
   3.252 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   3.253 +        share = partial_share(Random(random.getrandbits(128)), runtime, GF(modulus), secret, paillier=paillier)
   3.254 +        def decrypt(share):
   3.255 +            decrypted_share = paillier.decrypt(share.enc_shares[runtime.id - 1])
   3.256 +            decrypted_shares = _convolute(runtime, decrypted_share)
   3.257 +            def test_sum(vals):
   3.258 +                self.assertEquals(secret, sum(vals) % modulus)
   3.259 +            runtime.schedule_callback(decrypted_shares, test_sum)
   3.260 +        runtime.schedule_callback(share, decrypt)
   3.261 +        return share
   3.262 +
   3.263 +    @protocol
   3.264 +    def test_random_shares_have_correct_type(self, runtime):
   3.265 +        Zp = GF(23)
   3.266 +        shares = partial_random_shares(Random(23499), runtime, Zp, 7)
   3.267 +        for share in shares:
   3.268 +            def test(share):
   3.269 +                self.assertEquals(Zp, share.value.field)
   3.270 +            runtime.schedule_callback(share, test)
   3.271 +            
   3.272 +        return shares
   3.273 + 
   3.274 +    @protocol
   3.275 +    def test_encrypted_random_shares_decrypt_correctly(self, runtime):
   3.276 +        random = Random(3423993)
   3.277 +        modulus = 17
   3.278 +        Zp = GF(modulus)
   3.279 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   3.280 +        shares = partial_random_shares(random, runtime, Zp, 7, paillier=paillier)
   3.281 +        expected_result = [9,16,7,12,3,5,6]
   3.282 +        for inx, share in enumerate(shares):
   3.283 +            def decrypt(share, expected_result):
   3.284 +                decrypted_share = paillier.decrypt(share.enc_shares[runtime.id - 1])
   3.285 +                decrypted_shares = _convolute(runtime, decrypted_share)
   3.286 +                def test_sum(vals, expected_result):
   3.287 +                    v = Zp(sum(vals))
   3.288 +                    self.assertEquals(expected_result, v)
   3.289 +                runtime.schedule_callback(decrypted_shares, test_sum, expected_result)
   3.290 +            runtime.schedule_callback(share, decrypt, expected_result[inx])
   3.291 +            
   3.292 +        return shares
   3.293 +
   3.294 +class ShareGeneratorTest(BeDOZaTestCase):
   3.295 +    num_players = 3
   3.296 +
   3.297 +    @protocol
   3.298 +    def test_encrypted_real_share_open_correctly(self, runtime):
   3.299 +        random = Random(3423993)
   3.300 +        modulus = 17
   3.301 +        Zp = GF(modulus)
   3.302 +        bits_in_p = 5
   3.303 +        u_bound = 2**(4 * bits_in_p)
   3.304 +        alpha = 15
   3.305 +        
   3.306 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   3.307 +
   3.308 +        share_random = Random(random.getrandbits(128))
   3.309 +        gen = ShareGenerator(Zp, runtime, share_random, paillier, u_bound, alpha)
   3.310 +        share = gen.generate_share(7)
   3.311 +        def check(v):
   3.312 +            self.assertEquals(7, v)
   3.313 +        r = runtime.open(share)
   3.314 +        runtime.schedule_callback(r, check)
   3.315 +        return r
   3.316 +
   3.317 +    @protocol
   3.318 +    def test_encrypted_random_real_shares_open_correctly(self, runtime):
   3.319 +        random = Random(3423993)
   3.320 +        modulus = 17
   3.321 +        Zp = GF(modulus)
   3.322 +        bits_in_p = 5
   3.323 +        u_bound = 2**(4 * bits_in_p)
   3.324 +        alpha = 15
   3.325 +        
   3.326 +        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   3.327 +
   3.328 +        share_random = Random(random.getrandbits(128))
   3.329 +        gen = ShareGenerator(Zp, runtime, share_random, paillier, u_bound, alpha)
   3.330 +        shares = gen.generate_random_shares(7)
   3.331 +        expected_result = [9,16,7,12,3,5,6]
   3.332 +        results = []
   3.333 +        for inx, share in enumerate(shares):
   3.334 +            def check(v, expected_result):
   3.335 +                self.assertEquals(expected_result, v)
   3.336 +            r = runtime.open(share)
   3.337 +            results.append(r)
   3.338 +            runtime.schedule_callback(r, check, expected_result[inx])
   3.339 +        return gather_shares(results)
   3.340 +
   3.341 +class AddMacsTest(BeDOZaTestCase): 
   3.342 +    num_players = 3
   3.343 +
   3.344 +    timeout = 10
   3.345 +
   3.346 +    @protocol
   3.347 +    def test_add_macs_produces_correct_sharing(self, runtime):
   3.348 +        # TODO: Here we use the open method of the BeDOZa runtime in
   3.349 +        # order to verify the macs of the generated full share. In
   3.350 +        # order to be more unit testish, this test should use its own
   3.351 +        # way of verifying these.
   3.352 +        p = 17
   3.353 +        Zp = GF(p)
   3.354 +        secret = 6
   3.355 +        random = Random(283883)
   3.356 +        paillier_random = Random(random.getrandbits(128))
   3.357 +        paillier = ModifiedPaillier(runtime, random)
   3.358 +
   3.359 +        add_macs_random = Random(random.getrandbits(128))
   3.360 +
   3.361 +        shares_random = Random(random.getrandbits(128))
   3.362 +        shares = []
   3.363 +        shares.append(partial_share(shares_random, runtime, Zp, secret, paillier=paillier))
   3.364 +        shares.append(partial_share(shares_random, runtime, Zp, secret + 1, paillier=paillier))
   3.365 +        shares.append(partial_share(shares_random, runtime, Zp, secret + 2, paillier=paillier))
   3.366 +        shares.append(partial_share(shares_random, runtime, Zp, secret + 3, paillier=paillier))
   3.367 +
   3.368 +        bits_in_p = 5
   3.369 +        u_bound = 2**(4 * bits_in_p)
   3.370 +        alpha = 15
   3.371 +
   3.372 +        zs = add_macs(runtime, Zp, u_bound, alpha,
   3.373 +                      add_macs_random, paillier, shares)
   3.374 +        def verify(open_shares):
   3.375 +            inx = secret
   3.376 +            for open_share in open_shares:
   3.377 +                self.assertEquals(inx, open_share.value)
   3.378 +                inx += 1
   3.379 +
   3.380 +        opened_shares = []
   3.381 +        for s in zs:
   3.382 +            opened_shares.append(runtime.open(s))
   3.383 +        d = gather_shares(opened_shares)
   3.384 +        d.addCallback(verify)
   3.385 +        return d
   3.386 +
   3.387 +        
   3.388 +#    @protocol
   3.389 +#    def test_add_macs_preserves_value_of_sharing(self, runtime):
   3.390 +#        partial_share = self._generate_partial_share_of(42)
   3.391 +#        full_share = TripleGenerator()._add_macs(partial_share)
   3.392 +#        secret = self._open_sharing(full_share)
   3.393 +#        self.assertEquals(42, secret)
   3.394 +#        return partial_share
   3.395 +#    #test_add_macs_preserves_value_of_sharing.skip = "nyi"
   3.396 +#        
   3.397 +#    @protocol
   3.398 +#    def test_add_macs_preserves_value_of_zero_sharing(self, runtime):
   3.399 +#        partial_share = self._generate_partial_share_of(0)
   3.400 +#        full_share = TripleGenerator()._add_macs(partial_share)
   3.401 +#        secret = self._open_sharing(full_share)
   3.402 +#        self.assertEquals(0, secret)
   3.403 +#        return partial_share
   3.404 +#    #test_add_macs_preserves_value_of_zero_sharing.skip = "nyi"
   3.405 +# 
   3.406 +
   3.407 +class TripleTest(BeDOZaTestCase): 
   3.408 +    num_players = 3
   3.409 +
   3.410 +    timeout = 25
   3.411 +
   3.412 +    @protocol
   3.413 +    def test_generate_triples_generates_correct_triples(self, runtime):
   3.414 +        p = 17
   3.415 +
   3.416 +        Zp = GF(p)
   3.417 +      
   3.418 +        random = Random(283883)        
   3.419 +        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   3.420 +
   3.421 +        triples = triple_generator.generate_triples(10)
   3.422 +
   3.423 +        def check((a, b, c)):
   3.424 +            self.assertEquals(c, a * b)
   3.425 +
   3.426 +        def open(triple):
   3.427 +            d1 = runtime.open(triple.a)
   3.428 +            d2 = runtime.open(triple.b)
   3.429 +            d3 = runtime.open(triple.c)
   3.430 +            d = gatherResults([d1, d2, d3])
   3.431 +            runtime.schedule_callback(d, check)
   3.432 +            return d
   3.433 +
   3.434 +        for triple in triples:
   3.435 +            runtime.schedule_callback(triple, open)
   3.436 +        return gatherResults(triples)
   3.437 +
   3.438 +    @protocol
   3.439 +    def test_passive_triples_generates_correct_triples(self, runtime):
   3.440 +        p = 17
   3.441 +
   3.442 +        Zp = GF(p)
   3.443 +       
   3.444 +        random = Random(283883)        
   3.445 +        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   3.446 +
   3.447 +        triples = triple_generator._generate_passive_triples(5)
   3.448 +        def verify(triples):
   3.449 +            for inx in xrange(len(triples) // 3):
   3.450 +                self.assertEquals(triples[10 + inx], triples[inx] * triples[5 + inx])
   3.451 +        opened_shares = []
   3.452 +        for s in triples:
   3.453 +            opened_shares.append(runtime.open(s))
   3.454 +        d = gather_shares(opened_shares)
   3.455 +        d.addCallback(verify)
   3.456 +        return d
   3.457 +
   3.458 +class MulTest(BeDOZaTestCase): 
   3.459 +    num_players = 3
   3.460 +
   3.461 +    timeout = 10
   3.462 +        
   3.463 +    @protocol
   3.464 +    def test_mul_computes_correct_result(self, runtime):
   3.465 +        p = 17
   3.466 +       
   3.467 +        random = Random(283883)        
   3.468 +        triple_generator = TripleGenerator(runtime, 32, p, random)
   3.469 +
   3.470 +        Zp = GF(p)
   3.471 +
   3.472 +        ais = [Zp(6), Zp(6), Zp(6), Zp(6)]
   3.473 +        b2 = Zp(7)
   3.474 +        cs = []
   3.475 +        for ai in ais:
   3.476 +            cs.append(triple_generator.paillier.encrypt(b2.value, 2))      
   3.477 +
   3.478 +        n = len(ais)
   3.479 +        
   3.480 +        if runtime.id == 1:
   3.481 +            r1 = triple_generator._mul(1, 2, n, ais, cs)
   3.482 +            def check1(shares):
   3.483 +                for share in shares:
   3.484 +                    pc = tuple(runtime.program_counter)
   3.485 +                    runtime.protocols[2].sendData(pc, TEXT, str(share.value))
   3.486 +                return True
   3.487 +            r1.addCallback(check1)
   3.488 +            return r1
   3.489 +        else:
   3.490 +            r1 = triple_generator._mul(1, 2, n)
   3.491 +            def check(shares):
   3.492 +                deferreds = []
   3.493 +                for share in shares:
   3.494 +                    if runtime.id == 2:
   3.495 +                        def check_additivity(zi, zj):
   3.496 +                            self.assertEquals((Zp(long(zi)) + zj).value, 8)
   3.497 +                            return None
   3.498 +                        d = Deferred()
   3.499 +                        d.addCallback(check_additivity, share.value)
   3.500 +                        runtime._expect_data(1, TEXT, d)
   3.501 +                        deferreds.append(d)
   3.502 +                    else:
   3.503 +                        self.assertEquals(share.value, 0)
   3.504 +                return gatherResults(deferreds)
   3.505 +            r1.addCallback(check)
   3.506 +            return r1
   3.507 +
   3.508 +    @protocol
   3.509 +    def test_mul_same_player_inputs_and_receives(self, runtime):
   3.510 +        p = 17
   3.511 +      
   3.512 +        random = Random(283883)        
   3.513 +        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   3.514 +
   3.515 +        Zp = GF(p)
   3.516 +
   3.517 +        ais = [Zp(6), Zp(6), Zp(6), Zp(6)]
   3.518 +        b2 = Zp(7)
   3.519 +        cs = []
   3.520 +        for ai in ais:
   3.521 +            cs.append(triple_generator.paillier.encrypt(b2.value, 2))
   3.522 +
   3.523 +        n = len(ais)
   3.524 +        
   3.525 +        r1 = triple_generator._mul(2, 2, n, ais, cs)
   3.526 +        def check(shares):
   3.527 +            for share in shares:
   3.528 +                if runtime.id == 2:
   3.529 +                    self.assertEquals(share.value, 8)
   3.530 +            return True
   3.531 +            
   3.532 +        r1.addCallback(check)
   3.533 +        return r1
   3.534 +
   3.535 +
   3.536 +class FullMulTest(BeDOZaTestCase): 
   3.537 +    num_players = 3
   3.538 +
   3.539 +    timeout = 10
   3.540 +        
   3.541 +    @protocol
   3.542 +    def test_fullmul_computes_the_correct_result(self, runtime):
   3.543 +        p = 17
   3.544 +
   3.545 +        Zp = GF(p)
   3.546 +        
   3.547 +        random = Random(283883)        
   3.548 +        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   3.549 +
   3.550 +        paillier = triple_generator.paillier
   3.551 +        
   3.552 +        share_as = []
   3.553 +        share_bs = []      
   3.554 +        share_as.append(partial_share(random, runtime, GF(p), 6, paillier=paillier))
   3.555 +        share_bs.append(partial_share(random, runtime, GF(p), 7, paillier=paillier))
   3.556 +        share_as.append(partial_share(random, runtime, GF(p), 5, paillier=paillier))
   3.557 +        share_bs.append(partial_share(random, runtime, GF(p), 4, paillier=paillier))
   3.558 +        share_as.append(partial_share(random, runtime, GF(p), 2, paillier=paillier))
   3.559 +        share_bs.append(partial_share(random, runtime, GF(p), 3, paillier=paillier))
   3.560 +
   3.561 +
   3.562 +        share_zs = triple_generator._full_mul(share_as, share_bs)
   3.563 +        def check(shares):
   3.564 +            def test_sum(ls):
   3.565 +                self.assertEquals(8, Zp(sum(ls[0])))
   3.566 +                self.assertEquals(3, Zp(sum(ls[1])))
   3.567 +                self.assertEquals(6, Zp(sum(ls[2])))
   3.568 +            values = []
   3.569 +            for share in shares:
   3.570 +                value = _convolute(runtime, share.value.value)
   3.571 +                values.append(value)
   3.572 +            d = gatherResults(values)
   3.573 +            runtime.schedule_callback(d, test_sum)
   3.574 +            return d
   3.575 +            
   3.576 +        d = gatherResults(share_zs)
   3.577 +        d.addCallback(check)
   3.578 +        return d
   3.579 +
   3.580 +    @protocol
   3.581 +    def test_fullmul_encrypted_values_are_the_same_as_the_share(self, runtime):
   3.582 +        p = 17
   3.583 +
   3.584 +        Zp = GF(p)
   3.585 +        
   3.586 +        random = Random(283883)        
   3.587 +        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   3.588 +
   3.589 +        paillier = triple_generator.paillier
   3.590 +
   3.591 +        share_as = []
   3.592 +        share_bs = []      
   3.593 +        share_as.append(partial_share(random, runtime, GF(p), 6, paillier=paillier))
   3.594 +        share_bs.append(partial_share(random, runtime, GF(p), 7, paillier=paillier))
   3.595 +        share_as.append(partial_share(random, runtime, GF(p), 5, paillier=paillier))
   3.596 +        share_bs.append(partial_share(random, runtime, GF(p), 4, paillier=paillier))
   3.597 +        share_as.append(partial_share(random, runtime, GF(p), 2, paillier=paillier))
   3.598 +        share_bs.append(partial_share(random, runtime, GF(p), 3, paillier=paillier))
   3.599 +
   3.600 +        share_zs = triple_generator._full_mul(share_as, share_bs)
   3.601 +        def check(shares):
   3.602 +            all_enc_shares = []
   3.603 +            for share in shares:
   3.604 +                def test_enc(enc_shares, value):
   3.605 +                    all_the_same, zi_enc = reduce(lambda x, y: (x[0] and x[1] == y, y), enc_shares, (True, enc_shares[0]))
   3.606 +                    zi_enc = triple_generator.paillier.decrypt(zi_enc)
   3.607 +                    self.assertEquals(value, Zp(zi_enc))
   3.608 +                    return True
   3.609 +                for inx, enc_share in enumerate(share.enc_shares):
   3.610 +                    d = _convolute(runtime, enc_share)
   3.611 +                    if runtime.id == inx + 1:
   3.612 +                        d.addCallback(test_enc, share.value)
   3.613 +                all_enc_shares.append(d)
   3.614 +            return gatherResults(all_enc_shares)
   3.615 +        
   3.616 +        d = gatherResults(share_zs)
   3.617 +        d.addCallback(check)
   3.618 +        return d
   3.619 +        
   3.620 +
   3.621 +
   3.622 +missing_package = None
   3.623 +if not pypaillier:
   3.624 +    missing_package = "pypaillier"
   3.625 +if not tripple:
   3.626 +    missing_package = "tripple"
   3.627 +if missing_package:
   3.628 +    test_cases = [ModifiedPaillierTest,
   3.629 +                  PartialShareGeneratorTest,
   3.630 +                  TripleTest,
   3.631 +                  DataTransferTest,
   3.632 +                  MulTest,
   3.633 +                  FullMulTest,
   3.634 +                  ShareGeneratorTest,
   3.635 +                  AddMacsTest
   3.636 +                  ]
   3.637 +    for test_case in test_cases:
   3.638 +        test_case.skip =  "Skipped due to missing %s package." % missing_package
     4.1 --- a/viff/test/test_bedoza_runtime.py	Tue Sep 21 15:42:57 2010 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,562 +0,0 @@
     4.4 -# Copyright 2010 VIFF Development Team.
     4.5 -#
     4.6 -# This file is part of VIFF, the Virtual Ideal Functionality Framework.
     4.7 -#
     4.8 -# VIFF is free software: you can redistribute it and/or modify it
     4.9 -# under the terms of the GNU Lesser General Public License (LGPL) as
    4.10 -# published by the Free Software Foundation, either version 3 of the
    4.11 -# License, or (at your option) any later version.
    4.12 -#
    4.13 -# VIFF is distributed in the hope that it will be useful, but WITHOUT
    4.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    4.15 -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
    4.16 -# Public License for more details.
    4.17 -#
    4.18 -# You should have received a copy of the GNU Lesser General Public
    4.19 -# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    4.20 -
    4.21 -import sys
    4.22 -
    4.23 -# We don't need secure random numbers for test purposes.
    4.24 -from random import Random
    4.25 -
    4.26 -from twisted.internet.defer import gatherResults, DeferredList
    4.27 -
    4.28 -from viff.test.util import RuntimeTestCase, protocol
    4.29 -from viff.runtime import gather_shares, Share
    4.30 -from viff.config import generate_configs
    4.31 -from viff.bedoza.bedoza import BeDOZaRuntime
    4.32 -from viff.bedoza.shares import BeDOZaShare, BeDOZaShareContents
    4.33 -from viff.bedoza.keylist import BeDOZaKeyList
    4.34 -from viff.bedoza.maclist import BeDOZaMACList
    4.35 -from viff.field import FieldElement, GF
    4.36 -from viff.util import rand
    4.37 -from viff.bedoza.modified_paillier import ModifiedPaillier
    4.38 -from viff.bedoza.share_generators import ShareGenerator
    4.39 -from viff.bedoza.bedoza_triple import TripleGenerator
    4.40 -from viff.bedoza.zero_knowledge import ZKProof
    4.41 -
    4.42 -# The PyPaillier and commitment packages are not standard parts of VIFF so we
    4.43 -# skip them instead of letting them fail if the packages are not available. 
    4.44 -try:
    4.45 -    import pypaillier
    4.46 -except ImportError:
    4.47 -    pypaillier = None
    4.48 -
    4.49 -# HACK: The paillier keys that are available as standard in VIFF tests
    4.50 -# are not suited for use with pypaillier. Hence, we use NaClPaillier
    4.51 -# to generate test keys. This confusion will disappear when pypaillier
    4.52 -# replaces the current Python-based paillier implementation.
    4.53 -from viff.paillierutil import NaClPaillier
    4.54 -
    4.55 -# HACK^2: Currently, the NaClPaillier hack only works when triple is
    4.56 -# imported. It should ideally work without the triple package.
    4.57 -try:
    4.58 -    import tripple
    4.59 -except ImportError:
    4.60 -    tripple = None
    4.61 -
    4.62 -
    4.63 -class BeDOZaBasicCommandsTest(RuntimeTestCase):
    4.64 -    """Test for basic commands."""
    4.65 -
    4.66 -    # Number of players.
    4.67 -    num_players = 3
    4.68 -
    4.69 -    timeout = 3
    4.70 -
    4.71 -    runtime_class = BeDOZaRuntime
    4.72 -
    4.73 -    # TODO: During test, we would like generation of Paillier keys to
    4.74 -    # be deterministic. How do we obtain that?
    4.75 -    def generate_configs(self, *args):
    4.76 -        # In production, paillier keys should be something like 2000
    4.77 -        # bit. For test purposes, it is ok to use small keys.
    4.78 -        # TODO: paillier freezes if key size is too small, e.g. 13.
    4.79 -        return generate_configs(paillier=NaClPaillier(250), *args)
    4.80 -
    4.81 -    def setUp(self):
    4.82 -        RuntimeTestCase.setUp(self)
    4.83 -        self.Zp = GF(17)
    4.84 -        bits_in_p = 5
    4.85 -        self.security_parameter = 32
    4.86 -        self.u_bound = 2**(self.security_parameter + 4 * bits_in_p)
    4.87 -        self.alpha = 15
    4.88 -
    4.89 -    @protocol
    4.90 -    def test_plus(self, runtime):
    4.91 -        """Test addition of two numbers."""
    4.92 -
    4.93 -        Zp = self.Zp
    4.94 -       
    4.95 -        x = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(3), Zp(4), Zp(1)]), BeDOZaMACList([Zp(2), Zp(74), Zp(23), Zp(2)]))
    4.96 -        y = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(5), Zp(2), Zp(7)]), BeDOZaMACList([Zp(2), Zp(74), Zp(23), Zp(2)]))
    4.97 -        z = runtime._plus((x, y), Zp)
    4.98 -        self.assertEquals(z.get_value(), Zp(4))
    4.99 -        self.assertEquals(z.get_keys(), BeDOZaKeyList(Zp(23), [Zp(8), Zp(6), Zp(8)]))
   4.100 -        self.assertEquals(z.get_macs(), BeDOZaMACList([Zp(4), Zp(148), Zp(46), Zp(4)]))
   4.101 -
   4.102 -    @protocol
   4.103 -    def test_sum(self, runtime):
   4.104 -        """Test addition of two numbers."""       
   4.105 -
   4.106 -        def check(v):
   4.107 -            self.assertEquals(v, 0)
   4.108 -
   4.109 -        random = Random(3423993)
   4.110 -        share_random = Random(random.getrandbits(128))
   4.111 -        
   4.112 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.113 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.114 -                             paillier, self.u_bound, self.alpha)
   4.115 -        
   4.116 -        x2 = gen.generate_share(8)
   4.117 -        y2 = gen.generate_share(9)
   4.118 -        z2 = runtime.add(x2, y2)
   4.119 -        d = runtime.open(z2)
   4.120 -        d.addCallback(check)
   4.121 -        return d
   4.122 -
   4.123 -    @protocol
   4.124 -    def test_sum_plus(self, runtime):
   4.125 -        """Test addition of two numbers."""
   4.126 -
   4.127 -        def check(v):
   4.128 -            self.assertEquals(v, 11)
   4.129 -
   4.130 -        random = Random(3423993)
   4.131 -        share_random = Random(random.getrandbits(128))
   4.132 -        
   4.133 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.134 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.135 -                             paillier, self.u_bound, self.alpha)
   4.136 -        
   4.137 -        x2 = gen.generate_share(2)
   4.138 -        y2 = gen.generate_share(9)
   4.139 -        z2 = x2 + y2
   4.140 -        d = runtime.open(z2)
   4.141 -        d.addCallback(check)
   4.142 -        return d
   4.143 -
   4.144 -    @protocol
   4.145 -    def test_sum_constant_right(self, runtime):
   4.146 -        """Test addition of secret shared number and a public number."""
   4.147 -
   4.148 -        y1 = 7
   4.149 -
   4.150 -        def check(v):
   4.151 -            self.assertEquals(v, 15)
   4.152 -
   4.153 -        random = Random(3423993)
   4.154 -        share_random = Random(random.getrandbits(128))
   4.155 -        
   4.156 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.157 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.158 -                             paillier, self.u_bound, self.alpha)
   4.159 -        
   4.160 -        x2 = gen.generate_share(8)
   4.161 -        z2 = x2 + y1
   4.162 -        d = runtime.open(z2)
   4.163 -        d.addCallback(check)
   4.164 -        return d
   4.165 -
   4.166 -    @protocol
   4.167 -    def test_sum_constant_left(self, runtime):
   4.168 -        """Test addition of a public number and secret shared number."""
   4.169 -
   4.170 -        y1 = 7
   4.171 -
   4.172 -        def check(v):
   4.173 -            self.assertEquals(v, 15)
   4.174 -
   4.175 -        random = Random(3423993)
   4.176 -        share_random = Random(random.getrandbits(128))
   4.177 -        
   4.178 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.179 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.180 -                             paillier, self.u_bound, self.alpha)
   4.181 -        
   4.182 -        x2 = gen.generate_share(8)
   4.183 -        z2 = y1 + x2
   4.184 -        d = runtime.open(z2)
   4.185 -        d.addCallback(check)
   4.186 -        return d
   4.187 -
   4.188 -    @protocol
   4.189 -    def test_minus(self, runtime):
   4.190 -        """Test subtraction of two numbers."""
   4.191 -
   4.192 -        Zp = self.Zp
   4.193 -       
   4.194 -        x = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(5), Zp(4), Zp(7)]), BeDOZaMACList([Zp(2), Zp(75), Zp(23), Zp(2)]))
   4.195 -        y = BeDOZaShareContents(Zp(2), BeDOZaKeyList(Zp(23), [Zp(3), Zp(2), Zp(1)]), BeDOZaMACList([Zp(2), Zp(74), Zp(23), Zp(2)]))
   4.196 -        z = runtime._minus((x, y), Zp)
   4.197 -        self.assertEquals(z.get_value(), Zp(0))
   4.198 -        self.assertEquals(z.get_keys(), BeDOZaKeyList(Zp(23), [Zp(2), Zp(2), Zp(6)]))
   4.199 -        self.assertEquals(z.get_macs(), BeDOZaMACList([Zp(0), Zp(1), Zp(0), Zp(0)]))
   4.200 -
   4.201 -    @protocol
   4.202 -    def test_sub(self, runtime):
   4.203 -        """Test subtraction of two numbers."""
   4.204 -
   4.205 -        def check(v):
   4.206 -            self.assertEquals(v, 1)
   4.207 -
   4.208 -        random = Random(3423993)
   4.209 -        share_random = Random(random.getrandbits(128))
   4.210 -        
   4.211 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.212 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.213 -                             paillier, self.u_bound, self.alpha)
   4.214 -        
   4.215 -        x2 = gen.generate_share(9)
   4.216 -        y2 = gen.generate_share(8)
   4.217 -        z2 = runtime.sub(x2, y2)
   4.218 -        d = runtime.open(z2)
   4.219 -        d.addCallback(check)
   4.220 -        return d
   4.221 -
   4.222 -    @protocol
   4.223 -    def test_sub_minus(self, runtime):
   4.224 -        """Test subtraction of two numbers."""
   4.225 -
   4.226 -        def check(v):
   4.227 -            self.assertEquals(v, 1)
   4.228 -
   4.229 -        random = Random(3423993)
   4.230 -        share_random = Random(random.getrandbits(128))
   4.231 -        
   4.232 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.233 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.234 -                             paillier, self.u_bound, self.alpha)
   4.235 -        
   4.236 -        x2 = gen.generate_share(9)
   4.237 -        y2 = gen.generate_share(8)
   4.238 -        z2 = x2 - y2
   4.239 -        d = runtime.open(z2)
   4.240 -        d.addCallback(check)
   4.241 -        return d
   4.242 -
   4.243 -    @protocol
   4.244 -    def test_sub_constant_right(self, runtime):
   4.245 -        """Test subtraction of secret shared number and a public number."""
   4.246 -
   4.247 -        y = 4
   4.248 -
   4.249 -        def check(v):
   4.250 -            self.assertEquals(v, 4)
   4.251 -
   4.252 -        random = Random(3423993)
   4.253 -        share_random = Random(random.getrandbits(128))
   4.254 -        
   4.255 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.256 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.257 -                             paillier, self.u_bound, self.alpha)
   4.258 -        
   4.259 -        x2 = gen.generate_share(8)
   4.260 -        z2 = x2 - y
   4.261 -        d = runtime.open(x2)
   4.262 -        d.addCallback(check)
   4.263 -        return d
   4.264 -
   4.265 -    @protocol
   4.266 -    def test_sub_constant_left(self, runtime):
   4.267 -        """Test subtraction of a public number and secret shared number."""
   4.268 -
   4.269 -        y = 8
   4.270 -
   4.271 -        def check(v):
   4.272 -            self.assertEquals(v, 3)
   4.273 -
   4.274 -        random = Random(3423993)
   4.275 -        share_random = Random(random.getrandbits(128))
   4.276 -        
   4.277 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.278 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.279 -                             paillier, self.u_bound, self.alpha)
   4.280 -        
   4.281 -        x2 = gen.generate_share(5)
   4.282 -        z2 = y - x2
   4.283 -        d = runtime.open(x2)
   4.284 -        d.addCallback(check)
   4.285 -        return d
   4.286 -
   4.287 -    @protocol
   4.288 -    def test_constant_multiplication_constant_left(self, runtime):
   4.289 -        """Test multiplication of two numbers."""
   4.290 -
   4.291 -        x1 = 6
   4.292 -        y1 = 7
   4.293 -
   4.294 -        def check(v):
   4.295 -            self.assertEquals(v, self.Zp(x1 * y1))
   4.296 -
   4.297 -        random = Random(3423993)
   4.298 -        share_random = Random(random.getrandbits(128))
   4.299 -        
   4.300 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.301 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.302 -                             paillier, self.u_bound, self.alpha)
   4.303 -        
   4.304 -        x2 = gen.generate_share(x1)
   4.305 -
   4.306 -        z2 = runtime._cmul(self.Zp(y1), x2, self.Zp)
   4.307 -        d = runtime.open(z2)
   4.308 -        d.addCallback(check)
   4.309 -        return d
   4.310 -
   4.311 -    @protocol
   4.312 -    def test_constant_multiplication_constant_right(self, runtime):
   4.313 -        """Test multiplication of two numbers."""
   4.314 -
   4.315 -        x1 = 6
   4.316 -        y1 = 7
   4.317 -
   4.318 -        def check(v):
   4.319 -            self.assertEquals(v, self.Zp(x1 * y1))
   4.320 -
   4.321 -        random = Random(3423993)
   4.322 -        share_random = Random(random.getrandbits(128))
   4.323 -        
   4.324 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.325 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.326 -                             paillier, self.u_bound, self.alpha)
   4.327 -        
   4.328 -        x2 = gen.generate_share(x1)
   4.329 -
   4.330 -        z2 = runtime._cmul(x2, self.Zp(y1), self.Zp)
   4.331 -        d = runtime.open(z2)
   4.332 -        d.addCallback(check)
   4.333 -        return d
   4.334 -
   4.335 -    @protocol
   4.336 -    def test_get_triple(self, runtime):
   4.337 -        """Test generation of a triple."""
   4.338 -
   4.339 -        def check((a, b, c)):
   4.340 -            self.assertEquals(c, a * b)
   4.341 -
   4.342 -        def open(triple):
   4.343 -            d1 = runtime.open(triple.a)
   4.344 -            d2 = runtime.open(triple.b)
   4.345 -            d3 = runtime.open(triple.c)
   4.346 -            d = gather_shares([d1, d2, d3])
   4.347 -            d.addCallback(check)
   4.348 -            return d
   4.349 -
   4.350 -        random = Random(3423993)
   4.351 -        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, random)
   4.352 -        [triple] = gen.generate_triples(1)
   4.353 -        triple.addCallback(open)
   4.354 -        return triple
   4.355 -
   4.356 -    @protocol
   4.357 -    def test_basic_multiply(self, runtime):
   4.358 -        """Test multiplication of two numbers."""
   4.359 -
   4.360 -        x1 = 6
   4.361 -        y1 = 6
   4.362 -
   4.363 -        def check(v):
   4.364 -            self.assertEquals(v, self.Zp(x1 * y1))
   4.365 -
   4.366 -        def do_stuff(triple, alpha):
   4.367 -            random = Random(3423993)
   4.368 -            share_random = Random(random.getrandbits(128))
   4.369 -        
   4.370 -            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.371 -            gen = ShareGenerator(self.Zp, runtime, share_random,
   4.372 -                                 paillier, self.u_bound, alpha)
   4.373 -        
   4.374 -            x2 = gen.generate_share(x1)
   4.375 -            y2 = gen.generate_share(y1)
   4.376 -            z2 = runtime._basic_multiplication(x2, y2,
   4.377 -                                               triple.a,
   4.378 -                                               triple.b,
   4.379 -                                               triple.c)
   4.380 -            d = runtime.open(z2)
   4.381 -            d.addCallback(check)
   4.382 -            return d
   4.383 -
   4.384 -        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   4.385 -        alpha = gen.alpha
   4.386 -        [triple] = gen.generate_triples(1)
   4.387 -        runtime.schedule_callback(triple, do_stuff, alpha)
   4.388 -        return triple
   4.389 -
   4.390 -    @protocol
   4.391 -    def test_mul_mul(self, runtime):
   4.392 -        """Test multiplication of two numbers."""
   4.393 -
   4.394 -        x1 = 6
   4.395 -        y1 = 6
   4.396 -
   4.397 -        def check(v):
   4.398 -            self.assertEquals(v, self.Zp(x1 * y1))
   4.399 -
   4.400 -        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   4.401 -        alpha = gen.alpha
   4.402 -        triples = gen.generate_triples(1)
   4.403 -        
   4.404 -        def do_mult(triples, alpha):
   4.405 -            runtime.triples = triples
   4.406 -            random = Random(3423993)
   4.407 -            share_random = Random(random.getrandbits(128))
   4.408 -            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.409 -            gen = ShareGenerator(self.Zp, runtime, share_random,
   4.410 -                                 paillier, self.u_bound, alpha)
   4.411 -        
   4.412 -            x2 = gen.generate_share(x1)
   4.413 -            y2 = gen.generate_share(y1)
   4.414 -        
   4.415 -            z2 = x2 * y2
   4.416 -            d = runtime.open(z2)
   4.417 -            d.addCallback(check)
   4.418 -            return d
   4.419 -        r = gatherResults(triples)
   4.420 -        runtime.schedule_callback(r, do_mult, alpha)
   4.421 -        return r
   4.422 -    
   4.423 -    @protocol
   4.424 -    def test_basic_multiply_constant_right(self, runtime):
   4.425 -        """Test multiplication of two numbers."""
   4.426 -
   4.427 -        x1 = 6
   4.428 -        y1 = 6
   4.429 -
   4.430 -        def check(v):
   4.431 -            self.assertEquals(v, self.Zp(x1 * y1))
   4.432 -
   4.433 -        def do_stuff(triple, alpha):
   4.434 -            random = Random(3423993)
   4.435 -            share_random = Random(random.getrandbits(128))
   4.436 -        
   4.437 -            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.438 -            gen = ShareGenerator(self.Zp, runtime, share_random,
   4.439 -                                 paillier, self.u_bound, alpha)
   4.440 -        
   4.441 -            x2 = gen.generate_share(x1)
   4.442 -            y2 = gen.generate_share(y1)
   4.443 -            z2 = runtime._basic_multiplication(x2, self.Zp(y1),
   4.444 -                                               triple.a,
   4.445 -                                               triple.b,
   4.446 -                                               triple.c)
   4.447 -            d = runtime.open(z2)
   4.448 -            d.addCallback(check)
   4.449 -            return d
   4.450 -
   4.451 -        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   4.452 -        alpha = gen.alpha
   4.453 -        [triple] = gen.generate_triples(1)
   4.454 -        runtime.schedule_callback(triple, do_stuff, alpha)
   4.455 -        return triple
   4.456 -
   4.457 -    @protocol
   4.458 -    def test_basic_multiply_constant_left(self, runtime):
   4.459 -        """Test multiplication of two numbers."""
   4.460 -
   4.461 -        x1 = 6
   4.462 -        y1 = 6
   4.463 -
   4.464 -        def check(v):
   4.465 -            self.assertEquals(v, self.Zp(x1 * y1))
   4.466 -
   4.467 -        def do_stuff(triple, alpha):
   4.468 -            random = Random(3423993)
   4.469 -            share_random = Random(random.getrandbits(128))
   4.470 -        
   4.471 -            paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.472 -            gen = ShareGenerator(self.Zp, runtime, share_random,
   4.473 -                                 paillier, self.u_bound, alpha)
   4.474 -        
   4.475 -            x2 = gen.generate_share(x1)
   4.476 -            y2 = gen.generate_share(y1)
   4.477 -            z2 = runtime._basic_multiplication(self.Zp(x1), y2,
   4.478 -                                               triple.a,
   4.479 -                                               triple.b,
   4.480 -                                               triple.c)
   4.481 -            d = runtime.open(z2)
   4.482 -            d.addCallback(check)
   4.483 -            return d
   4.484 -
   4.485 -        gen = TripleGenerator(runtime, self.security_parameter, self.Zp.modulus, Random(3423993))
   4.486 -        alpha = gen.alpha
   4.487 -        [triple] = gen.generate_triples(1)
   4.488 -        runtime.schedule_callback(triple, do_stuff, alpha)
   4.489 -        return triple
   4.490 -
   4.491 -    @protocol
   4.492 -    def test_open_multiple_secret_share(self, runtime):
   4.493 -        """Test sharing and open of a number."""
   4.494 -
   4.495 -        def check(ls):
   4.496 -            for v in ls:
   4.497 -                self.assertEquals(v, 6)
   4.498 -
   4.499 -        random = Random(3423993)
   4.500 -        share_random = Random(random.getrandbits(128))
   4.501 -        
   4.502 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.503 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.504 -                             paillier, self.u_bound, self.alpha)
   4.505 -        
   4.506 -        x = gen.generate_share(6)
   4.507 -        y = gen.generate_share(6)
   4.508 -        d = runtime.open_multiple_values([x, y])
   4.509 -        d.addCallback(check)
   4.510 -        return d
   4.511 -
   4.512 -    @protocol
   4.513 -    def test_open_two_secret_share(self, runtime):
   4.514 -        """Test sharing and open of a number."""
   4.515 -
   4.516 -        def check((a, b)):
   4.517 -            self.assertEquals(a, 6)
   4.518 -            self.assertEquals(b, 6)
   4.519 -
   4.520 -        random = Random(3423993)
   4.521 -        share_random = Random(random.getrandbits(128))
   4.522 -        
   4.523 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))          
   4.524 -        gen = ShareGenerator(self.Zp, runtime, share_random,
   4.525 -                             paillier, self.u_bound, self.alpha)
   4.526 -        
   4.527 -        x = gen.generate_share(6)
   4.528 -        y = gen.generate_share(6)
   4.529 -        d = runtime.open_two_values(x, y)
   4.530 -        d.addCallback(check)
   4.531 -        return d
   4.532 -
   4.533 -
   4.534 -# TODO: Move to test.bedoza.test_zero_knowledge.
   4.535 -class BeDOZaZeroKnowledgeTest(RuntimeTestCase):
   4.536 -
   4.537 -    num_players = 3
   4.538 -
   4.539 -    timeout = 3
   4.540 -
   4.541 -    runtime_class = BeDOZaRuntime
   4.542 -
   4.543 -    def test_zk_matrix_entries_are_correct(self):
   4.544 -        zk = ZKProof(None, None)
   4.545 -        zk._set_e([1, 0, 0, 1, 1])
   4.546 -        for i in range(zk.s):
   4.547 -            for j in range(zk.m):
   4.548 -                if j >= i and j < i + zk.s:
   4.549 -                    self.assertEquals(zk.e[j - i], zk._E(j, i))
   4.550 -                else:
   4.551 -                    self.assertEquals(0, zk._E(j, i))
   4.552 -
   4.553 -    def test_vec_pow_is_correct(self):
   4.554 -        Zn = GF(17)
   4.555 -        y = [Zn(i) for i in range(1, 6)]
   4.556 -        zk = ZKProof(None, Zn)
   4.557 -        zk._set_e([1, 0, 1, 1, 0])
   4.558 -        y_pow_E = zk.vec_pow_E(y)
   4.559 -        self.assertEquals([Zn(v) for v in [1, 2, 3, 8, 13, 12, 3, 5, 1]],
   4.560 -                          y_pow_E)
   4.561 -def skip_tests(module_name):
   4.562 -    BeDOZaBasicCommandsTest.skip = "Skipped due to missing " + module_name + " module."
   4.563 -
   4.564 -if not pypaillier:
   4.565 -    skip_tests("pypaillier")
     5.1 --- a/viff/test/test_bedoza_triple.py	Tue Sep 21 15:42:57 2010 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,635 +0,0 @@
     5.4 -# Copyright 2010 VIFF Development Team.
     5.5 -#
     5.6 -# This file is part of VIFF, the Virtual Ideal Functionality Framework.
     5.7 -#
     5.8 -# VIFF is free software: you can redistribute it and/or modify it
     5.9 -# under the terms of the GNU Lesser General Public License (LGPL) as
    5.10 -# published by the Free Software Foundation, either version 3 of the
    5.11 -# License, or (at your option) any later version.
    5.12 -#
    5.13 -# VIFF is distributed in the hope that it will be useful, but WITHOUT
    5.14 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    5.15 -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
    5.16 -# Public License for more details.
    5.17 -#
    5.18 -# You should have received a copy of the GNU Lesser General Public
    5.19 -# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    5.20 -
    5.21 -import sys
    5.22 -from exceptions import AssertionError
    5.23 -
    5.24 -import operator
    5.25 -
    5.26 -# We don't need secure random numbers for test purposes.
    5.27 -from random import Random
    5.28 -
    5.29 -from twisted.internet.defer import gatherResults, Deferred, DeferredList
    5.30 -
    5.31 -from viff.test.util import RuntimeTestCase, protocol
    5.32 -from viff.constants import TEXT
    5.33 -from viff.runtime import gather_shares, Share
    5.34 -from viff.config import generate_configs
    5.35 -
    5.36 -from viff.bedoza.bedoza import BeDOZaRuntime, BeDOZaShare
    5.37 -from viff.bedoza.keylist import BeDOZaKeyList
    5.38 -from viff.bedoza.bedoza_triple import TripleGenerator, ModifiedPaillier
    5.39 -from viff.bedoza.share_generators import PartialShareGenerator, ShareGenerator
    5.40 -from viff.bedoza.shares import PartialShare, PartialShareContents
    5.41 -from viff.bedoza.util import _send, _convolute, _convolute_gf_elm
    5.42 -from viff.bedoza.add_macs import add_macs
    5.43 -
    5.44 -from viff.field import FieldElement, GF
    5.45 -from viff.config import generate_configs
    5.46 -
    5.47 -
    5.48 -# Ok to use non-secure random generator in tests.
    5.49 -#from viff.util import rand
    5.50 -import random
    5.51 -
    5.52 -# The PyPaillier and commitment packages are not standard parts of VIFF so we
    5.53 -# skip them instead of letting them fail if the packages are not available. 
    5.54 -try:
    5.55 -    import pypaillier
    5.56 -except ImportError:
    5.57 -    pypaillier = None
    5.58 -
    5.59 -# HACK: The paillier keys that are available as standard in VIFF tests
    5.60 -# are not suited for use with pypaillier. Hence, we use NaClPaillier
    5.61 -# to generate test keys. This confusion will disappear when pypaillier
    5.62 -# replaces the current Python-based paillier implementation.
    5.63 -from viff.paillierutil import NaClPaillier
    5.64 -
    5.65 -# HACK^2: Currently, the NaClPaillier hack only works when triple is
    5.66 -# imported. It should ideally work without the triple package.
    5.67 -try:
    5.68 -    import tripple
    5.69 -except ImportError:
    5.70 -    tripple = None
    5.71 -
    5.72 -
    5.73 -
    5.74 -def _log(rt, msg):
    5.75 -    print "player%d ------> %s" % (rt.id, msg)
    5.76 -
    5.77 -
    5.78 -class BeDOZaTestCase(RuntimeTestCase):
    5.79 -
    5.80 -    runtime_class = BeDOZaRuntime
    5.81 -
    5.82 -    def setUp(self):
    5.83 -        RuntimeTestCase.setUp(self)
    5.84 -        self.security_parameter = 32
    5.85 -
    5.86 -    # TODO: During test, we would like generation of Paillier keys to
    5.87 -    # be deterministic. How do we obtain that?
    5.88 -    def generate_configs(self, *args):
    5.89 -        # In production, paillier keys should be something like 2000
    5.90 -        # bit. For test purposes, it is ok to use small keys.
    5.91 -        # TODO: paillier freezes if key size is too small, e.g. 13.
    5.92 -        return generate_configs(paillier=NaClPaillier(250), *args)
    5.93 -
    5.94 -
    5.95 -class DataTransferTest(BeDOZaTestCase):
    5.96 -    num_players = 3
    5.97 -
    5.98 -    @protocol
    5.99 -    def test_convolute_int(self, runtime):
   5.100 -        res = _convolute(runtime, runtime.id)
   5.101 -        def verify(result):
   5.102 -            self.assertEquals(runtime.players.keys(), result)
   5.103 -        runtime.schedule_callback(res, verify)
   5.104 -        return res
   5.105 -
   5.106 -    @protocol
   5.107 -    def test_send(self, runtime):
   5.108 -        msg_send = [100 * p + runtime.id for p in runtime.players]
   5.109 -        msg_receive = [100 * runtime.id + p for p in runtime.players]
   5.110 -        res = _send(runtime, msg_send)
   5.111 -        def verify(result):
   5.112 -            self.assertEquals(msg_receive, result)
   5.113 -        runtime.schedule_callback(res, verify)
   5.114 -        return res
   5.115 - 
   5.116 -    @protocol
   5.117 -    def test_convolute_field_element(self, runtime):
   5.118 -        Zp = GF(17)
   5.119 -        res = _convolute_gf_elm(runtime, Zp(runtime.id))
   5.120 -        def verify(result):
   5.121 -            self.assertEquals(runtime.players.keys(), result)
   5.122 -        runtime.schedule_callback(res, verify)
   5.123 -        return res
   5.124 -
   5.125 -
   5.126 -class ModifiedPaillierTest(BeDOZaTestCase):
   5.127 -    num_players = 3
   5.128 -
   5.129 -    @protocol
   5.130 -    def test_modified_paillier_can_decrypt_encrypted_one(self, runtime):
   5.131 -        paillier = ModifiedPaillier(runtime, Random(234838))
   5.132 -        val = 1
   5.133 -        encrypted_val = paillier.encrypt(val)
   5.134 -        decrypted_val = paillier.decrypt(encrypted_val)
   5.135 -        self.assertEquals(val, decrypted_val)
   5.136 -
   5.137 -    @protocol
   5.138 -    def test_modified_paillier_can_decrypt_encrypted_zero(self, runtime):
   5.139 -        paillier = ModifiedPaillier(runtime, Random(338301))
   5.140 -        val = 0
   5.141 -        encrypted_val = paillier.encrypt(val)
   5.142 -        decrypted_val = paillier.decrypt(encrypted_val)
   5.143 -        self.assertEquals(val, decrypted_val)
   5.144 -
   5.145 -    @protocol
   5.146 -    def test_modified_paillier_can_decrypt_encrypted_minus_one(self, runtime):
   5.147 -        paillier = ModifiedPaillier(runtime, Random(19623))
   5.148 -        val = -1
   5.149 -        encrypted_val = paillier.encrypt(val)
   5.150 -        decrypted_val = paillier.decrypt(encrypted_val)
   5.151 -        self.assertEquals(val, decrypted_val)
   5.152 -
   5.153 -    @protocol
   5.154 -    def test_modified_paillier_can_decrypt_encrypted_max_val(self, runtime):
   5.155 -        paillier = ModifiedPaillier(runtime, Random(825604))
   5.156 -        n = runtime.players[runtime.id].pubkey['n']
   5.157 -        val = (n - 1) / 2
   5.158 -        encrypted_val = paillier.encrypt(val)
   5.159 -        decrypted_val = paillier.decrypt(encrypted_val)
   5.160 -        self.assertEquals(val, decrypted_val)
   5.161 -
   5.162 -    @protocol
   5.163 -    def test_modified_paillier_can_decrypt_encrypted_min_val(self, runtime):
   5.164 -        paillier = ModifiedPaillier(runtime, Random(554424))
   5.165 -        n = runtime.players[runtime.id].pubkey['n']
   5.166 -        val = -(n - 1) / 2
   5.167 -        encrypted_val = paillier.encrypt(val)
   5.168 -        decrypted_val = paillier.decrypt(encrypted_val)
   5.169 -        self.assertEquals(val, decrypted_val)
   5.170 - 
   5.171 -    @protocol
   5.172 -    def test_modified_paillier_can_decrypt_encrypted_positive(self, runtime):
   5.173 -        paillier = ModifiedPaillier(runtime, Random(777737))
   5.174 -        val = 73423
   5.175 -        encrypted_val = paillier.encrypt(val)
   5.176 -        decrypted_val = paillier.decrypt(encrypted_val)
   5.177 -        self.assertEquals(val, decrypted_val)
   5.178 -
   5.179 -    @protocol
   5.180 -    def test_encrypting_too_large_number_raises_exception(self, runtime):
   5.181 -        paillier = ModifiedPaillier(runtime, Random(825604))
   5.182 -        n = runtime.players[runtime.id].pubkey['n']
   5.183 -        val = 1 + (n - 1) / 2
   5.184 -        self.assertRaises(AssertionError, paillier.encrypt, val)
   5.185 -
   5.186 -    @protocol
   5.187 -    def test_encrypting_too_small_number_raises_exception(self, runtime):
   5.188 -        paillier = ModifiedPaillier(runtime, Random(554424))
   5.189 -        n = runtime.players[runtime.id].pubkey['n']
   5.190 -        val = -(n - 1) / 2 - 1
   5.191 -        self.assertRaises(AssertionError, paillier.encrypt, val)
   5.192 -
   5.193 -    @protocol
   5.194 -    def test_modified_paillier_can_encrypt_to_other(self, runtime):
   5.195 -        paillier = ModifiedPaillier(runtime, Random(57503))
   5.196 -        msg = []
   5.197 -        for p in runtime.players:
   5.198 -            msg.append(paillier.encrypt(runtime.id, player_id=p))
   5.199 -        received = _send(runtime, msg)
   5.200 -        def verify(enc):
   5.201 -            plain = [paillier.decrypt(e) for e in enc]
   5.202 -            self.assertEquals(range(1, self.num_players + 1), plain)
   5.203 -        runtime.schedule_callback(received, verify)
   5.204 -        return received
   5.205 -
   5.206 -
   5.207 -def partial_share(random, runtime, Zp, val, paillier=None):
   5.208 -    if not paillier:
   5.209 -        paillier_random = Random(random.getrandbits(128))
   5.210 -        paillier = ModifiedPaillier(runtime, paillier_random)
   5.211 -    share_random = Random(random.getrandbits(128))
   5.212 -    gen = PartialShareGenerator(Zp, runtime, share_random, paillier)
   5.213 -    return gen.generate_share(Zp(val))
   5.214 -
   5.215 -def partial_random_shares(random, runtime, Zp, n, paillier=None):
   5.216 -    if not paillier:
   5.217 -        paillier_random = Random(random.getrandbits(128))
   5.218 -        paillier = ModifiedPaillier(runtime, paillier_random)
   5.219 -    share_random = Random(random.getrandbits(128))
   5.220 -    gen = PartialShareGenerator(Zp, runtime, share_random, paillier)
   5.221 -    return gen.generate_random_shares(n)
   5.222 -
   5.223 -class PartialShareGeneratorTest(BeDOZaTestCase):
   5.224 -    num_players = 3
   5.225 - 
   5.226 -    @protocol
   5.227 -    def test_shares_have_correct_type(self, runtime):
   5.228 -        Zp = GF(23)
   5.229 -        share = partial_share(Random(23499), runtime, Zp, 7)
   5.230 -        def test(share):
   5.231 -            self.assertEquals(Zp, share.value.field)
   5.232 -        runtime.schedule_callback(share, test)
   5.233 -        return share
   5.234 - 
   5.235 -    @protocol
   5.236 -    def test_shares_are_additive(self, runtime):
   5.237 -        secret = 7
   5.238 -        share = partial_share(Random(34993), runtime, GF(23), secret)
   5.239 -        def convolute(share):
   5.240 -            values = _convolute_gf_elm(runtime, share.value)
   5.241 -            def test_sum(vals):
   5.242 -                self.assertEquals(secret, sum(vals))
   5.243 -            runtime.schedule_callback(values, test_sum)
   5.244 -        runtime.schedule_callback(share, convolute)
   5.245 -        return share
   5.246 -
   5.247 -    @protocol
   5.248 -    def test_encrypted_shares_decrypt_correctly(self, runtime):
   5.249 -        random = Random(3423993)
   5.250 -        modulus = 17
   5.251 -        secret = 7
   5.252 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   5.253 -        share = partial_share(Random(random.getrandbits(128)), runtime, GF(modulus), secret, paillier=paillier)
   5.254 -        def decrypt(share):
   5.255 -            decrypted_share = paillier.decrypt(share.enc_shares[runtime.id - 1])
   5.256 -            decrypted_shares = _convolute(runtime, decrypted_share)
   5.257 -            def test_sum(vals):
   5.258 -                self.assertEquals(secret, sum(vals) % modulus)
   5.259 -            runtime.schedule_callback(decrypted_shares, test_sum)
   5.260 -        runtime.schedule_callback(share, decrypt)
   5.261 -        return share
   5.262 -
   5.263 -    @protocol
   5.264 -    def test_random_shares_have_correct_type(self, runtime):
   5.265 -        Zp = GF(23)
   5.266 -        shares = partial_random_shares(Random(23499), runtime, Zp, 7)
   5.267 -        for share in shares:
   5.268 -            def test(share):
   5.269 -                self.assertEquals(Zp, share.value.field)
   5.270 -            runtime.schedule_callback(share, test)
   5.271 -            
   5.272 -        return shares
   5.273 - 
   5.274 -    @protocol
   5.275 -    def test_encrypted_random_shares_decrypt_correctly(self, runtime):
   5.276 -        random = Random(3423993)
   5.277 -        modulus = 17
   5.278 -        Zp = GF(modulus)
   5.279 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   5.280 -        shares = partial_random_shares(random, runtime, Zp, 7, paillier=paillier)
   5.281 -        expected_result = [9,16,7,12,3,5,6]
   5.282 -        for inx, share in enumerate(shares):
   5.283 -            def decrypt(share, expected_result):
   5.284 -                decrypted_share = paillier.decrypt(share.enc_shares[runtime.id - 1])
   5.285 -                decrypted_shares = _convolute(runtime, decrypted_share)
   5.286 -                def test_sum(vals, expected_result):
   5.287 -                    v = Zp(sum(vals))
   5.288 -                    self.assertEquals(expected_result, v)
   5.289 -                runtime.schedule_callback(decrypted_shares, test_sum, expected_result)
   5.290 -            runtime.schedule_callback(share, decrypt, expected_result[inx])
   5.291 -            
   5.292 -        return shares
   5.293 -
   5.294 -class ShareGeneratorTest(BeDOZaTestCase):
   5.295 -    num_players = 3
   5.296 -
   5.297 -    @protocol
   5.298 -    def test_encrypted_real_share_open_correctly(self, runtime):
   5.299 -        random = Random(3423993)
   5.300 -        modulus = 17
   5.301 -        Zp = GF(modulus)
   5.302 -        bits_in_p = 5
   5.303 -        u_bound = 2**(4 * bits_in_p)
   5.304 -        alpha = 15
   5.305 -        
   5.306 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   5.307 -
   5.308 -        share_random = Random(random.getrandbits(128))
   5.309 -        gen = ShareGenerator(Zp, runtime, share_random, paillier, u_bound, alpha)
   5.310 -        share = gen.generate_share(7)
   5.311 -        def check(v):
   5.312 -            self.assertEquals(7, v)
   5.313 -        r = runtime.open(share)
   5.314 -        runtime.schedule_callback(r, check)
   5.315 -        return r
   5.316 -
   5.317 -    @protocol
   5.318 -    def test_encrypted_random_real_shares_open_correctly(self, runtime):
   5.319 -        random = Random(3423993)
   5.320 -        modulus = 17
   5.321 -        Zp = GF(modulus)
   5.322 -        bits_in_p = 5
   5.323 -        u_bound = 2**(4 * bits_in_p)
   5.324 -        alpha = 15
   5.325 -        
   5.326 -        paillier = ModifiedPaillier(runtime, Random(random.getrandbits(128)))
   5.327 -
   5.328 -        share_random = Random(random.getrandbits(128))
   5.329 -        gen = ShareGenerator(Zp, runtime, share_random, paillier, u_bound, alpha)
   5.330 -        shares = gen.generate_random_shares(7)
   5.331 -        expected_result = [9,16,7,12,3,5,6]
   5.332 -        results = []
   5.333 -        for inx, share in enumerate(shares):
   5.334 -            def check(v, expected_result):
   5.335 -                self.assertEquals(expected_result, v)
   5.336 -            r = runtime.open(share)
   5.337 -            results.append(r)
   5.338 -            runtime.schedule_callback(r, check, expected_result[inx])
   5.339 -        return gather_shares(results)
   5.340 -
   5.341 -class AddMacsTest(BeDOZaTestCase): 
   5.342 -    num_players = 3
   5.343 -
   5.344 -    timeout = 10
   5.345 -
   5.346 -    @protocol
   5.347 -    def test_add_macs_produces_correct_sharing(self, runtime):
   5.348 -        # TODO: Here we use the open method of the BeDOZa runtime in
   5.349 -        # order to verify the macs of the generated full share. In
   5.350 -        # order to be more unit testish, this test should use its own
   5.351 -        # way of verifying these.
   5.352 -        p = 17
   5.353 -        Zp = GF(p)
   5.354 -        secret = 6
   5.355 -        random = Random(283883)
   5.356 -        paillier_random = Random(random.getrandbits(128))
   5.357 -        paillier = ModifiedPaillier(runtime, random)
   5.358 -
   5.359 -        add_macs_random = Random(random.getrandbits(128))
   5.360 -
   5.361 -        shares_random = Random(random.getrandbits(128))
   5.362 -        shares = []
   5.363 -        shares.append(partial_share(shares_random, runtime, Zp, secret, paillier=paillier))
   5.364 -        shares.append(partial_share(shares_random, runtime, Zp, secret + 1, paillier=paillier))
   5.365 -        shares.append(partial_share(shares_random, runtime, Zp, secret + 2, paillier=paillier))
   5.366 -        shares.append(partial_share(shares_random, runtime, Zp, secret + 3, paillier=paillier))
   5.367 -
   5.368 -        bits_in_p = 5
   5.369 -        u_bound = 2**(4 * bits_in_p)
   5.370 -        alpha = 15
   5.371 -
   5.372 -        zs = add_macs(runtime, Zp, u_bound, alpha,
   5.373 -                      add_macs_random, paillier, shares)
   5.374 -        def verify(open_shares):
   5.375 -            inx = secret
   5.376 -            for open_share in open_shares:
   5.377 -                self.assertEquals(inx, open_share.value)
   5.378 -                inx += 1
   5.379 -
   5.380 -        opened_shares = []
   5.381 -        for s in zs:
   5.382 -            opened_shares.append(runtime.open(s))
   5.383 -        d = gather_shares(opened_shares)
   5.384 -        d.addCallback(verify)
   5.385 -        return d
   5.386 -
   5.387 -        
   5.388 -#    @protocol
   5.389 -#    def test_add_macs_preserves_value_of_sharing(self, runtime):
   5.390 -#        partial_share = self._generate_partial_share_of(42)
   5.391 -#        full_share = TripleGenerator()._add_macs(partial_share)
   5.392 -#        secret = self._open_sharing(full_share)
   5.393 -#        self.assertEquals(42, secret)
   5.394 -#        return partial_share
   5.395 -#    #test_add_macs_preserves_value_of_sharing.skip = "nyi"
   5.396 -#        
   5.397 -#    @protocol
   5.398 -#    def test_add_macs_preserves_value_of_zero_sharing(self, runtime):
   5.399 -#        partial_share = self._generate_partial_share_of(0)
   5.400 -#        full_share = TripleGenerator()._add_macs(partial_share)
   5.401 -#        secret = self._open_sharing(full_share)
   5.402 -#        self.assertEquals(0, secret)
   5.403 -#        return partial_share
   5.404 -#    #test_add_macs_preserves_value_of_zero_sharing.skip = "nyi"
   5.405 -# 
   5.406 -
   5.407 -class TripleTest(BeDOZaTestCase): 
   5.408 -    num_players = 3
   5.409 -
   5.410 -    timeout = 25
   5.411 -
   5.412 -    @protocol
   5.413 -    def test_generate_triples_generates_correct_triples(self, runtime):
   5.414 -        p = 17
   5.415 -
   5.416 -        Zp = GF(p)
   5.417 -      
   5.418 -        random = Random(283883)        
   5.419 -        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   5.420 -
   5.421 -        triples = triple_generator.generate_triples(10)
   5.422 -
   5.423 -        def check((a, b, c)):
   5.424 -            self.assertEquals(c, a * b)
   5.425 -
   5.426 -        def open(triple):
   5.427 -            d1 = runtime.open(triple.a)
   5.428 -            d2 = runtime.open(triple.b)
   5.429 -            d3 = runtime.open(triple.c)
   5.430 -            d = gatherResults([d1, d2, d3])
   5.431 -            runtime.schedule_callback(d, check)
   5.432 -            return d
   5.433 -
   5.434 -        for triple in triples:
   5.435 -            runtime.schedule_callback(triple, open)
   5.436 -        return gatherResults(triples)
   5.437 -
   5.438 -    @protocol
   5.439 -    def test_passive_triples_generates_correct_triples(self, runtime):
   5.440 -        p = 17
   5.441 -
   5.442 -        Zp = GF(p)
   5.443 -       
   5.444 -        random = Random(283883)        
   5.445 -        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   5.446 -
   5.447 -        triples = triple_generator._generate_passive_triples(5)
   5.448 -        def verify(triples):
   5.449 -            for inx in xrange(len(triples) // 3):
   5.450 -                self.assertEquals(triples[10 + inx], triples[inx] * triples[5 + inx])
   5.451 -        opened_shares = []
   5.452 -        for s in triples:
   5.453 -            opened_shares.append(runtime.open(s))
   5.454 -        d = gather_shares(opened_shares)
   5.455 -        d.addCallback(verify)
   5.456 -        return d
   5.457 -
   5.458 -class MulTest(BeDOZaTestCase): 
   5.459 -    num_players = 3
   5.460 -
   5.461 -    timeout = 10
   5.462 -        
   5.463 -    @protocol
   5.464 -    def test_mul_computes_correct_result(self, runtime):
   5.465 -        p = 17
   5.466 -       
   5.467 -        random = Random(283883)        
   5.468 -        triple_generator = TripleGenerator(runtime, 32, p, random)
   5.469 -
   5.470 -        Zp = GF(p)
   5.471 -
   5.472 -        ais = [Zp(6), Zp(6), Zp(6), Zp(6)]
   5.473 -        b2 = Zp(7)
   5.474 -        cs = []
   5.475 -        for ai in ais:
   5.476 -            cs.append(triple_generator.paillier.encrypt(b2.value, 2))      
   5.477 -
   5.478 -        n = len(ais)
   5.479 -        
   5.480 -        if runtime.id == 1:
   5.481 -            r1 = triple_generator._mul(1, 2, n, ais, cs)
   5.482 -            def check1(shares):
   5.483 -                for share in shares:
   5.484 -                    pc = tuple(runtime.program_counter)
   5.485 -                    runtime.protocols[2].sendData(pc, TEXT, str(share.value))
   5.486 -                return True
   5.487 -            r1.addCallback(check1)
   5.488 -            return r1
   5.489 -        else:
   5.490 -            r1 = triple_generator._mul(1, 2, n)
   5.491 -            def check(shares):
   5.492 -                deferreds = []
   5.493 -                for share in shares:
   5.494 -                    if runtime.id == 2:
   5.495 -                        def check_additivity(zi, zj):
   5.496 -                            self.assertEquals((Zp(long(zi)) + zj).value, 8)
   5.497 -                            return None
   5.498 -                        d = Deferred()
   5.499 -                        d.addCallback(check_additivity, share.value)
   5.500 -                        runtime._expect_data(1, TEXT, d)
   5.501 -                        deferreds.append(d)
   5.502 -                    else:
   5.503 -                        self.assertEquals(share.value, 0)
   5.504 -                return gatherResults(deferreds)
   5.505 -            r1.addCallback(check)
   5.506 -            return r1
   5.507 -
   5.508 -    @protocol
   5.509 -    def test_mul_same_player_inputs_and_receives(self, runtime):
   5.510 -        p = 17
   5.511 -      
   5.512 -        random = Random(283883)        
   5.513 -        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   5.514 -
   5.515 -        Zp = GF(p)
   5.516 -
   5.517 -        ais = [Zp(6), Zp(6), Zp(6), Zp(6)]
   5.518 -        b2 = Zp(7)
   5.519 -        cs = []
   5.520 -        for ai in ais:
   5.521 -            cs.append(triple_generator.paillier.encrypt(b2.value, 2))
   5.522 -
   5.523 -        n = len(ais)
   5.524 -        
   5.525 -        r1 = triple_generator._mul(2, 2, n, ais, cs)
   5.526 -        def check(shares):
   5.527 -            for share in shares:
   5.528 -                if runtime.id == 2:
   5.529 -                    self.assertEquals(share.value, 8)
   5.530 -            return True
   5.531 -            
   5.532 -        r1.addCallback(check)
   5.533 -        return r1
   5.534 -
   5.535 -
   5.536 -class FullMulTest(BeDOZaTestCase): 
   5.537 -    num_players = 3
   5.538 -
   5.539 -    timeout = 10
   5.540 -        
   5.541 -    @protocol
   5.542 -    def test_fullmul_computes_the_correct_result(self, runtime):
   5.543 -        p = 17
   5.544 -
   5.545 -        Zp = GF(p)
   5.546 -        
   5.547 -        random = Random(283883)        
   5.548 -        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   5.549 -
   5.550 -        paillier = triple_generator.paillier
   5.551 -        
   5.552 -        share_as = []
   5.553 -        share_bs = []      
   5.554 -        share_as.append(partial_share(random, runtime, GF(p), 6, paillier=paillier))
   5.555 -        share_bs.append(partial_share(random, runtime, GF(p), 7, paillier=paillier))
   5.556 -        share_as.append(partial_share(random, runtime, GF(p), 5, paillier=paillier))
   5.557 -        share_bs.append(partial_share(random, runtime, GF(p), 4, paillier=paillier))
   5.558 -        share_as.append(partial_share(random, runtime, GF(p), 2, paillier=paillier))
   5.559 -        share_bs.append(partial_share(random, runtime, GF(p), 3, paillier=paillier))
   5.560 -
   5.561 -
   5.562 -        share_zs = triple_generator._full_mul(share_as, share_bs)
   5.563 -        def check(shares):
   5.564 -            def test_sum(ls):
   5.565 -                self.assertEquals(8, Zp(sum(ls[0])))
   5.566 -                self.assertEquals(3, Zp(sum(ls[1])))
   5.567 -                self.assertEquals(6, Zp(sum(ls[2])))
   5.568 -            values = []
   5.569 -            for share in shares:
   5.570 -                value = _convolute(runtime, share.value.value)
   5.571 -                values.append(value)
   5.572 -            d = gatherResults(values)
   5.573 -            runtime.schedule_callback(d, test_sum)
   5.574 -            return d
   5.575 -            
   5.576 -        d = gatherResults(share_zs)
   5.577 -        d.addCallback(check)
   5.578 -        return d
   5.579 -
   5.580 -    @protocol
   5.581 -    def test_fullmul_encrypted_values_are_the_same_as_the_share(self, runtime):
   5.582 -        p = 17
   5.583 -
   5.584 -        Zp = GF(p)
   5.585 -        
   5.586 -        random = Random(283883)        
   5.587 -        triple_generator = TripleGenerator(runtime, self.security_parameter, p, random)
   5.588 -
   5.589 -        paillier = triple_generator.paillier
   5.590 -
   5.591 -        share_as = []
   5.592 -        share_bs = []      
   5.593 -        share_as.append(partial_share(random, runtime, GF(p), 6, paillier=paillier))
   5.594 -        share_bs.append(partial_share(random, runtime, GF(p), 7, paillier=paillier))
   5.595 -        share_as.append(partial_share(random, runtime, GF(p), 5, paillier=paillier))
   5.596 -        share_bs.append(partial_share(random, runtime, GF(p), 4, paillier=paillier))
   5.597 -        share_as.append(partial_share(random, runtime, GF(p), 2, paillier=paillier))
   5.598 -        share_bs.append(partial_share(random, runtime, GF(p), 3, paillier=paillier))
   5.599 -
   5.600 -        share_zs = triple_generator._full_mul(share_as, share_bs)
   5.601 -        def check(shares):
   5.602 -            all_enc_shares = []
   5.603 -            for share in shares:
   5.604 -                def test_enc(enc_shares, value):
   5.605 -                    all_the_same, zi_enc = reduce(lambda x, y: (x[0] and x[1] == y, y), enc_shares, (True, enc_shares[0]))
   5.606 -                    zi_enc = triple_generator.paillier.decrypt(zi_enc)
   5.607 -                    self.assertEquals(value, Zp(zi_enc))
   5.608 -                    return True
   5.609 -                for inx, enc_share in enumerate(share.enc_shares):
   5.610 -                    d = _convolute(runtime, enc_share)
   5.611 -                    if runtime.id == inx + 1:
   5.612 -                        d.addCallback(test_enc, share.value)
   5.613 -                all_enc_shares.append(d)
   5.614 -            return gatherResults(all_enc_shares)
   5.615 -        
   5.616 -        d = gatherResults(share_zs)
   5.617 -        d.addCallback(check)
   5.618 -        return d
   5.619 -        
   5.620 -
   5.621 -
   5.622 -missing_package = None
   5.623 -if not pypaillier:
   5.624 -    missing_package = "pypaillier"
   5.625 -if not tripple:
   5.626 -    missing_package = "tripple"
   5.627 -if missing_package:
   5.628 -    test_cases = [ModifiedPaillierTest,
   5.629 -                  PartialShareGeneratorTest,
   5.630 -                  TripleTest,
   5.631 -                  DataTransferTest,
   5.632 -                  MulTest,
   5.633 -                  FullMulTest,
   5.634 -                  ShareGeneratorTest,
   5.635 -                  AddMacsTest
   5.636 -                  ]
   5.637 -    for test_case in test_cases:
   5.638 -        test_case.skip =  "Skipped due to missing %s package." % missing_package