Discussion:
Division
Sigurd Torkel Meldgaard
2008-10-08 13:33:54 UTC
Permalink
An (proof-of-concept) app doing secret shared division.
It is a very simple algorithm (basically finding one bit of the result
at a time by doing comparisons), and could probably be put in the
runtime, but I am not sure exactly where, because it requires an
precision parameter, and thus does not lend itself well to operator
overloading.

Sigurd
Martin Geisler
2008-10-08 22:03:10 UTC
Permalink
"Sigurd Torkel Meldgaard" <***@daimi.au.dk> writes:

Hi Sigurd
An (proof-of-concept) app doing secret shared division. It is a very
simple algorithm (basically finding one bit of the result at a time by
doing comparisons), and could probably be put in the runtime, but I am
not sure exactly where, because it requires an precision parameter,
and thus does not lend itself well to operator overloading.
I've not yet looked at it in detail (it sounds great!), but just wanted
to say that it is better if you could send patches using the 'hg email'
command (from the patchbomb extension) or at least attach patches with a
mime-type of text/x-patch and Content-Disposition of inline.
--
Martin Geisler

VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multi-Party Computation) to Python. See: http://viff.dk/.
Martin Geisler
2008-10-24 09:56:22 UTC
Permalink
Post by Sigurd Torkel Meldgaard
An (proof-of-concept) app doing secret shared division.
Very nice! I've tried it and -- gasp! -- it works :-)

Tord might have a fancy log(l) comparison protocol, but until that is
written or implemented somewhere I definitely think we should include
this example.

As usual, I have some comments below... :-) Please let me know if you
agree and send an updated patch when you get around to it.
Post by Sigurd Torkel Meldgaard
It is a very simple algorithm (basically finding one bit of the
result at a time by doing comparisons), and could probably be put in
the runtime, but I am not sure exactly where, because it requires an
precision parameter, and thus does not lend itself well to operator
overloading.
Right. But don't we know the precision parameter from the field size?
So using math.log(x.field.modulus, 2) would work, wouldn't it? That
could be done in the __div__ method on Share so as to not mess up the
nice property that divide works with both ints and Shares.
Post by Sigurd Torkel Meldgaard
Sigurd
Added application doing division.
diff -r bf314f0580fc apps/divide.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/divide.py Wed Oct 08 14:16:40 2008 +0200
@@ -0,0 +1,132 @@
+#!/usr/bin/python
+
+# Copyright 2008 VIFF Development Team.
+#
+# This file is part of VIFF, the Virtual Ideal Functionality Framework.
+#
+# VIFF is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License (LGPL) as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# VIFF is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""This program does a secret division between two secret shared
+values It is of course mostly meaningless for this example (you can
Missing full stop.
Post by Sigurd Torkel Meldgaard
+compute the inputs from your own value and the output)
Ditto :-)
Post by Sigurd Torkel Meldgaard
+
+The program can be run as follows for each player (min 3) where 24 is
+
+$ python equality.py player-X.ini -n 24
+
+Only the numbers of player 1 and player 2 are actually compared, but
+more players are necessary for the security.
"compared" looks like a cut-and-paste mistake?
Post by Sigurd Torkel Meldgaard
+"""
+
+from optparse import OptionParser
+from twisted.internet import reactor
+
+from viff.field import GF
+from viff.runtime import Runtime, create_runtime
+from viff.runtime import make_runtime_class
+from viff.comparison import ComparisonToft07Mixin
+from viff.config import load_config
+from viff.util import find_prime, dprint
+
+
+ b_r = bits[:]
+ b_r.reverse()
+ return sum([2**i * b for (i, b) in enumerate(b_r)])
+
+
+ """Returns a share of of `x*y` (rounded down).
+
+ Precondition: `2**l * y < x.field.modulus.`
+
+ If `y == 0` return `(2**(l+1) - 1)`.
+
+ The division is done by making a comparison for every
+ i with `(2**i)*y` and *x*.
+
+ Communication cost: *l* rounds of comparison.
+
+
Double empty line.
Post by Sigurd Torkel Meldgaard
+ >>>divide(3, 3, 2)
+ 1
+ >>>divide(50, 10, 10)
+ 10"""
Oh, that is cool -- a function that works on int and Share arguments!
I guess that says something about how well our overloading works and
how nice our FieldElement objects behave...
Post by Sigurd Torkel Meldgaard
+ bits = []
+ t = 2**i * y
+ cmp = t <= x
+ bits.append(cmp)
+ x = x - t * cmp
+ return bits_to_val(bits)
+
+
+ # Parse command line arguments.
+ parser = OptionParser(usage=__doc__)
+
+
+ parser.add_option("--modulus",
+ help="lower limit for modulus (can be an expression)")
+ parser.add_option("-n", "--number", type="int",
+ help="number to compare")
This "option" is not an option at all, it is a required argument :-)
The optparse documentation has something to say about this:

http://docs.python.org/library/optparse.html#what-are-positional-arguments-for
Post by Sigurd Torkel Meldgaard
+ parser.set_defaults(modulus=2**65, number=None)
+
+ Runtime.add_options(parser)
+
+ options, args = parser.parse_args()
+
+ parser.error("you must specify a config file")
+
+ Zp = GF(find_prime(options.modulus, blum=True))
+
+ # Load configuration file.
+ id, players = load_config(args[0])
+
+ runtime_class = make_runtime_class(mixins=[ComparisonToft07Mixin])
+ pre_runtime = create_runtime(id, players, 1, options, runtime_class)
+
+ print "Connected."
+
+ # Is our player id among the two first?
+ print "My number: %d." % options.number
+ # Players 1 and two are doing a sharing over the field ZP
+ # our input is options number
+ (x, y) = runtime.shamir_share([1, 2], Zp, options.number)
+ print "I do not have a number."
+ (x, y) = runtime.shamir_share([1, 2], Zp, None)
+
+ # Do the secret computation
+ result = divide(x, y, 27) # 27 bits for the result
+
+ # Now open the result so that we can see it
+ dprint("The two numbers divided are: %s", runtime.open(result))
+
+ result.addCallback(lambda _: runtime.shutdown())
+
+ pre_runtime.addCallback(run)
+
+ # Start the Twisted event loop.
+ reactor.run()
+
+ main()
--
Martin Geisler

VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/.
Sigurd Torkel Meldgaard
2008-10-24 11:45:08 UTC
Permalink
Thanks for the review
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
An (proof-of-concept) app doing secret shared division.
Very nice! I've tried it and -- gasp! -- it works :-)
Tord might have a fancy log(l) comparison protocol, but until that is
written or implemented somewhere I definitely think we should include
this example.
As usual, I have some comments below... :-) Please let me know if you
agree and send an updated patch when you get around to it.
Post by Sigurd Torkel Meldgaard
It is a very simple algorithm (basically finding one bit of the
result at a time by doing comparisons), and could probably be put in
the runtime, but I am not sure exactly where, because it requires an
precision parameter, and thus does not lend itself well to operator
overloading.
Right. But don't we know the precision parameter from the field size?
So using math.log(x.field.modulus, 2) would work, wouldn't it? That
could be done in the __div__ method on Share so as to not mess up the
nice property that divide works with both ints and Shares.
That could be done, but unfortunately the limits are lower, it seems
it stops working at around 27-28-bits, you mentioned the other day
that comparisons can only be done in half of the bits, is that true?

Anyway the precision parameter times y must be less than the number of
bits in the field (or half the number of bits) so I guess it is only
rarely useful to do the division without specifying the precision. But
maybe we can find an acceptable default.
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
Sigurd
Added application doing division.
diff -r bf314f0580fc apps/divide.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/divide.py Wed Oct 08 14:16:40 2008 +0200
@@ -0,0 +1,132 @@
+#!/usr/bin/python
+
+# Copyright 2008 VIFF Development Team.
+#
+# This file is part of VIFF, the Virtual Ideal Functionality Framework.
+#
+# VIFF is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License (LGPL) as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# VIFF is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""This program does a secret division between two secret shared
+values It is of course mostly meaningless for this example (you can
Missing full stop.
Post by Sigurd Torkel Meldgaard
+compute the inputs from your own value and the output)
Ditto :-)
You are really sharp, I should install a spell-and-grammar-checker for
my comments.
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+
+The program can be run as follows for each player (min 3) where 24 is
+
+$ python equality.py player-X.ini -n 24
+
+Only the numbers of player 1 and player 2 are actually compared, but
+more players are necessary for the security.
"compared" looks like a cut-and-paste mistake?
It is of course!
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+"""
+
+from optparse import OptionParser
+from twisted.internet import reactor
+
+from viff.field import GF
+from viff.runtime import Runtime, create_runtime
+from viff.runtime import make_runtime_class
+from viff.comparison import ComparisonToft07Mixin
+from viff.config import load_config
+from viff.util import find_prime, dprint
+
+
+ b_r = bits[:]
+ b_r.reverse()
+ return sum([2**i * b for (i, b) in enumerate(b_r)])
+
+
+ """Returns a share of of `x*y` (rounded down).
+
+ Precondition: `2**l * y < x.field.modulus.`
+
+ If `y == 0` return `(2**(l+1) - 1)`.
+
+ The division is done by making a comparison for every
+ i with `(2**i)*y` and *x*.
+
+ Communication cost: *l* rounds of comparison.
+
+
Double empty line.
Post by Sigurd Torkel Meldgaard
+ >>>divide(3, 3, 2)
+ 1
+ >>>divide(50, 10, 10)
+ 10"""
Oh, that is cool -- a function that works on int and Share arguments!
I guess that says something about how well our overloading works and
how nice our FieldElement objects behave...
Post by Sigurd Torkel Meldgaard
+ bits = []
+ t = 2**i * y
+ cmp = t <= x
+ bits.append(cmp)
+ x = x - t * cmp
+ return bits_to_val(bits)
+
+
+ # Parse command line arguments.
+ parser = OptionParser(usage=__doc__)
+
+
+ parser.add_option("--modulus",
+ help="lower limit for modulus (can be an expression)")
+ parser.add_option("-n", "--number", type="int",
+ help="number to compare")
This "option" is not an option at all, it is a required argument :-)
http://docs.python.org/library/optparse.html#what-are-positional-arguments-for
Hmm, the players with id above 2 should not input a number. But I
guess it makes sense to make it a positional argument anyway.
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+ parser.set_defaults(modulus=2**65, number=None)
+
+ Runtime.add_options(parser)
+
+ options, args = parser.parse_args()
+
+ parser.error("you must specify a config file")
+
+ Zp = GF(find_prime(options.modulus, blum=True))
+
+ # Load configuration file.
+ id, players = load_config(args[0])
+
+ runtime_class = make_runtime_class(mixins=[ComparisonToft07Mixin])
+ pre_runtime = create_runtime(id, players, 1, options, runtime_class)
+
+ print "Connected."
+
+ # Is our player id among the two first?
+ print "My number: %d." % options.number
+ # Players 1 and two are doing a sharing over the field ZP
+ # our input is options number
+ (x, y) = runtime.shamir_share([1, 2], Zp, options.number)
+ print "I do not have a number."
+ (x, y) = runtime.shamir_share([1, 2], Zp, None)
+
+ # Do the secret computation
+ result = divide(x, y, 27) # 27 bits for the result
+
+ # Now open the result so that we can see it
+ dprint("The two numbers divided are: %s", runtime.open(result))
+
+ result.addCallback(lambda _: runtime.shutdown())
+
+ pre_runtime.addCallback(run)
+
+ # Start the Twisted event loop.
+ reactor.run()
+
+ main()
--
Martin Geisler
VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/.
_______________________________________________
viff-patches mailing list
http://lists.viff.dk/listinfo.cgi/viff-patches-viff.dk
Attached is a revised patch - I am sorry my email client (gmail) does
not allow me to specify the Mime-type...

Sigurd
Martin Geisler
2008-10-24 12:11:12 UTC
Permalink
Post by Sigurd Torkel Meldgaard
Thanks for the review
No problem! I love looking at code...
Post by Sigurd Torkel Meldgaard
Post by Martin Geisler
Right. But don't we know the precision parameter from the field
size? So using math.log(x.field.modulus, 2) would work, wouldn't
it? That could be done in the __div__ method on Share so as to not
mess up the nice property that divide works with both ints and
Shares.
That could be done, but unfortunately the limits are lower, it seems
it stops working at around 27-28-bits, you mentioned the other day
that comparisons can only be done in half of the bits, is that true?
Yes, the comparison protocols need some "head-room" in the field. The
bit_length parameter (in options.bit_length) defaults to 32, and this
means that the input numbers to the comparison protocols should be 32
bit at most.

The Toft05 protocol does

l = self.options.bit_length
m = l + self.options.security_parameter
t = m + 1

assert 2**(l+1) + 2**t < field.modulus, "2^(l+1) + 2^t < p must hold"

and so with l = 32 and m = 32 + 30 the field modulus must be at least
m bits. Nothing checks this at the moment...
Post by Sigurd Torkel Meldgaard
Anyway the precision parameter times y must be less than the number
of bits in the field (or half the number of bits) so I guess it is
only rarely useful to do the division without specifying the
precision. But maybe we can find an acceptable default.
Hmm, it does sounds tricky since y is secret as well.
Post by Sigurd Torkel Meldgaard
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+"""This program does a secret division between two secret shared
+values It is of course mostly meaningless for this example (you can
Missing full stop.
Post by Sigurd Torkel Meldgaard
+compute the inputs from your own value and the output)
Ditto :-)
You are really sharp, I should install a spell-and-grammar-checker
for my comments.
Hehe :-) It is just that Mikkel and I are currently following a course
in academic English, and the teacher has been very careful to stress
that all English sentences must a) begin with a capital letter, b) end
with a full stop, question mark or exclamation mark (except that we
don't want any !-marks in academic English) and c) contain a subject,
noun and verb. So there... :-)
Post by Sigurd Torkel Meldgaard
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+ b_r = bits[:]
+ b_r.reverse()
+ return sum([2**i * b for (i, b) in enumerate(b_r)])
Here I would just do

return sum([2**i * b for (i, b) in enumerate(reversed(bits))])
Post by Sigurd Torkel Meldgaard
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+ parser.add_option("-n", "--number", type="int",
+ help="number to compare")
This "option" is not an option at all, it is a required argument
Hmm, the players with id above 2 should not input a number. But I
guess it makes sense to make it a positional argument anyway.
It's just a matter of looking in args as defined below.
Post by Sigurd Torkel Meldgaard
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
+ parser.set_defaults(modulus=2**65, number=None)
+
+ Runtime.add_options(parser)
+
+ options, args = parser.parse_args()
+
+ parser.error("you must specify a config file")
Here you can check if len(args) == 1 or 2 for the appropriate players.
No need to fiddle with sys.argv. Using sys.argv wont work anyway if
people start the players like

./divide --no-ssl player-1.ini --modulus 2**120 7

Here args will be ['player-1.ini', '7'].
Post by Sigurd Torkel Meldgaard
Attached is a revised patch - I am sorry my email client (gmail)
does not allow me to specify the Mime-type...
Don't worry, mine does! :-) I press "t" and it suggests "text/x-patch"
for the type of your attachment. I press enter and the patch is
highlighted as such by Emacs. What a nice OS that editor has...!
--
Martin Geisler

VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/.
Tomas Toft
2008-10-30 05:42:14 UTC
Permalink
Hi Guys
Post by Martin Geisler
Post by Sigurd Torkel Meldgaard
That could be done, but unfortunately the limits are lower, it seems
it stops working at around 27-28-bits, you mentioned the other day
that comparisons can only be done in half of the bits, is that true?
Yes, the comparison protocols need some "head-room" in the field. The
bit_length parameter (in options.bit_length) defaults to 32, and this
means that the input numbers to the comparison protocols should be 32
bit at most.
Just a slight elaboration of the above: The implemented protocols
require some headroom. But if you really want no headroom then that
could be implemented as well. (I'd prefer 1-bit headroom, but that's
just because it's only a third the cost.)


Regards,
Tomas
Sigurd Torkel Meldgaard
2008-11-13 13:34:28 UTC
Permalink
One more try of the division patch
Just a slight elaboration of the above: The implemented protocols require
some headroom. But if you really want no headroom then that could be
implemented as well. (I'd prefer 1-bit headroom, but that's just because
it's only a third the cost.)
If we find something to use this for we might want to do that, until
now it is more like a proof of concept. But this division algorithm
will still have some preconditions on the relative sizes of the
operands
Martin Geisler
2008-11-13 16:55:29 UTC
Permalink
"Sigurd Torkel Meldgaard" <***@daimi.au.dk> writes:

Hi Sigurd
Post by Sigurd Torkel Meldgaard
One more try of the division patch
Thanks for revising the patch. I have pushed it along with some
cleanups...

Could you please add

[defaults]
qnew = -U

to your ~/.hgrc file. That will ensure that your MQ patches contain a
header with your username. This will allow me to commit your patches
directly, otherwise I have to use 'hg import -u "Sigurd..."'.
--
Martin Geisler
Loading...