## viff

BeDOZa: Enabled subtraction with a non-share value as left operand.
author Janus Dam Nielsen Wed, 07 Jul 2010 11:01:14 +0200 a28c7d75c09e 6b96a1fdb751 viff/bedoza.py viff/orlandi.py viff/simplearithmetic.py viff/test/test_bedoza_runtime.py viff/test/test_orlandi_runtime.py 5 files changed, 86 insertions(+), 22 deletions(-) [+]
line diff
```     1.1 --- a/viff/bedoza.py	Tue Jul 06 16:17:16 2010 +0200
1.2 +++ b/viff/bedoza.py	Wed Jul 07 11:01:14 2010 +0200
1.3 @@ -295,12 +295,16 @@
1.4          zms = xms + yms
1.5          return (zi, zks, zms)
1.6
1.7 -    def _minus_public(self, x, c, field):
1.8 +    def _minus_public_right(self, x, c, field):
1.9          (xi, xks, xms) = x
1.10          if self.id == 1:
1.11              xi = xi - c
1.12          xks.keys[0] = xks.keys[0] + xks.alpha * c
1.13          return BeDOZaShare(self, field, xi, xks, xms)
1.14 +
1.15 +    def _minus_public_left(self, x, c, field):
1.16 +        y = self._constant_multiply(x, field(-1))
1.17 +        return self._plus_public(y, c, field)
1.18
1.19      def _minus(self, (x, y), field):
1.20          """Subtraction of share-tuples *x* and *y*.
1.21 @@ -318,7 +322,6 @@
1.22          zms = xms - yms
1.23          return (zi, zks, zms)
1.24
1.25 -
1.26      def _cmul(self, share_x, share_y, field):
1.27          """Multiplication of a share with a constant.
1.28
```
```     2.1 --- a/viff/orlandi.py	Tue Jul 06 16:17:16 2010 +0200
2.2 +++ b/viff/orlandi.py	Wed Jul 07 11:01:14 2010 +0200
2.3 @@ -464,9 +464,13 @@
2.4          Cz = Cx * Cy
2.5          return (zi, (rhozi1, rhozi2), Cz)
2.6
2.7 -    def _minus_public(self, x, c, field):
2.8 +    def _minus_public_right(self, x, c, field):
2.9          return self._do_arithmetic_op(x, c, field, self._minus)
2.10
2.11 +    def _minus_public_left(self, x, c, field):
2.12 +        y = self._constant_multiply(x, field(-1))
2.13 +        return self._do_arithmetic_op(y, c, field, self._plus)
2.14 +
2.15      def _do_arithmetic_op(self, x, c, field, op):
2.16          y = self._convert_public_to_share(c, field)
2.17          (zi, (rhozi1, rhozi2), Cz) = op((x, y), field)
2.18 @@ -595,7 +599,7 @@
2.19          """
2.20          def constant_multiply(x, c):
2.21              assert(isinstance(c, FieldElement))
2.22 -            zi, rhoz, Cx = self._const_mul(c.value, x)
2.23 +            zi, rhoz, Cx = self._constant_multiply(x, c)
2.24              return OrlandiShare(self, field, zi, rhoz, Cx)
2.25          if not isinstance(share_x, Share):
2.26              # Then share_y must be a Share => local multiplication. We
2.27 @@ -614,13 +618,13 @@
2.28              return result
2.29          return None
2.30
2.31 -    def _const_mul(self, c, x):
2.32 +    def _constant_multiply(self, x, c):
2.33          """Multiplication of a share-tuple with a constant c."""
2.34 -        assert(isinstance(c, long) or isinstance(c, int))
2.35 +        assert(isinstance(c, FieldElement))
2.36          xi, (rhoi1, rhoi2), Cx = x
2.37          zi = xi * c
2.38          rhoz = (rhoi1 * c, rhoi2 * c)
2.39 -        Cz = Cx**c
2.40 +        Cz = Cx**c.value
2.41          return (zi, rhoz, Cz)
2.42
2.43      def _get_share(self, field, value):
2.44 @@ -665,9 +669,9 @@
2.45              # [de]
2.46              de = self._convert_public_to_share(d * e, field)
2.47              # e[x]
2.48 -            t1 = self._const_mul(e.value, x)
2.49 +            t1 = self._constant_multiply(x, e)
2.50              # d[y]
2.51 -            t2 = self._const_mul(d.value, y)
2.52 +            t2 = self._constant_multiply(y, d)
2.53              # d[y] - [de]
2.54              t3 = self._minus((t2, de), field)
2.55              # d[y] - [de] + [c]
```
```     3.1 --- a/viff/simplearithmetic.py	Tue Jul 06 16:17:16 2010 +0200
3.2 +++ b/viff/simplearithmetic.py	Wed Jul 07 11:01:14 2010 +0200
3.3 @@ -22,8 +22,11 @@
3.4      """Provides methods for addition and subtraction.
3.5
3.7 -    Requires set: {self._plus((x,y), field), self._minus((x,y), field),
3.8 -                   self._convert_public_to_share_and_do(operation)}.
3.9 +    Requires set: {self._plus((x,y), field),
3.10 +                   self._minus((x,y), field),
3.11 +                   self._plus_public(x, c, field),
3.12 +                   self._minus_public_right(x, c, field),
3.13 +                   self._minus_public_left(x, c, field)}.
3.14      """
3.15
3.17 @@ -31,20 +34,10 @@
3.18
3.19          share_a is assumed to be an instance of Share.
3.20          If share_b is also an instance of Share then self._plus gets called.
3.21 -        If not then self._add_public get called.
3.22 +        If not then self._plus_public get called.
3.23          """
3.24          return self.both_shares(share_a, share_b, self._plus_public, self._plus)
3.25
3.26 -    def sub(self, share_a, share_b):
3.27 -        """Subtraction of shares.
3.28 -
3.29 -        share_a is assumed to be an instance of Share.
3.30 -        If share_b is also an instance of Share then self._minus gets called.
3.31 -        If not then self._sub_public get called.
3.32 -        """
3.33 -        return self.both_shares(share_a, share_b, self._minus_public, self._minus)
3.34 -
3.35 -
3.36      def both_shares(self, share_a, share_b, if_not, if_so):
3.37          field = share_a.field
3.38          if not isinstance(share_b, Share):
3.39 @@ -56,3 +49,28 @@
3.40              result = gather_shares([share_a, share_b])
3.42              return result
3.43 +
3.44 +    def sub(self, share_a, share_b):
3.45 +        """Subtraction of shares.
3.46 +
3.47 +        If share_a is an instance of Share but not share_b, then self._minus_public_right gets called.
3.48 +        If share_b is an instance of Share but not share_b, then self._minus_public_left gets called.
3.49 +        If share_a and share_b are both instances of Share then self._minus get called.
3.50 +        """
3.51 +        if not isinstance(share_b, Share):
3.52 +            field = share_a.field
3.53 +            if not isinstance(share_b, FieldElement):
3.54 +                share_b = field(share_b)
3.55 +            share_a.addCallbacks(self._minus_public_right, self.error_handler, callbackArgs=(share_b, field))
3.56 +            return share_a
3.57 +        elif not isinstance(share_a, Share):
3.58 +            field = share_b.field
3.59 +            if not isinstance(share_a, FieldElement):
3.60 +                share_a = field(share_a)
3.61 +            share_b.addCallbacks(self._minus_public_left, self.error_handler, callbackArgs=(share_a, field))
3.62 +            return share_b
3.63 +        else:
3.64 +            field = share_a.field
3.65 +            result = gather_shares([share_a, share_b])
3.67 +            return result
```
```     4.1 --- a/viff/test/test_bedoza_runtime.py	Tue Jul 06 16:17:16 2010 +0200
4.2 +++ b/viff/test/test_bedoza_runtime.py	Wed Jul 07 11:01:14 2010 +0200
4.3 @@ -276,6 +276,23 @@
4.4          return d
4.5
4.6      @protocol
4.7 +    def test_sub_constant_left(self, runtime):
4.8 +        """Test subtraction of a public number and secret shared number."""
4.9 +
4.10 +        self.Zp = GF(31)
4.11 +
4.12 +        y = 8
4.13 +
4.14 +        def check(v):
4.15 +            self.assertEquals(v, 2)
4.16 +
4.17 +        x2 = runtime.random_share(self.Zp)
4.18 +        z2 = y - x2
4.19 +        d = runtime.open(x2)
4.21 +        return d
4.22 +
4.23 +    @protocol
4.24      def test_constant_multiplication_constant_left(self, runtime):
4.25          """Test multiplication of two numbers."""
4.26
```
```     5.1 --- a/viff/test/test_orlandi_runtime.py	Tue Jul 06 16:17:16 2010 +0200
5.2 +++ b/viff/test/test_orlandi_runtime.py	Wed Jul 07 11:01:14 2010 +0200
5.3 @@ -307,6 +307,28 @@
5.5          return d
5.6
5.7 +    @protocol
5.8 +    def test_sub_constant_left(self, runtime):
5.9 +        """Test subtraction of a public number and secret shared number."""
5.10 +
5.11 +        self.Zp = GF(6277101735386680763835789423176059013767194773182842284081)
5.12 +
5.13 +        x1 = 6
5.14 +        y1 = 8
5.15 +
5.16 +        def check(v):
5.17 +            self.assertEquals(v, y1 - x1)
5.18 +
5.19 +        if 1 == runtime.id:
5.20 +            x2 = runtime.secret_share([1], self.Zp, x1)
5.21 +        else:
5.22 +            x2 = runtime.secret_share([1], self.Zp)
5.23 +
5.24 +        z2 = y1 - x2
5.25 +        d = runtime.open(x2)