Exemplo n.º 1
0
    def _verify_double(self, shares, rvec1, rvec2, T, field, d1, d2):
        """Verify shares.

        It is checked that they correspond to polynomial of the
        expected degrees and that they can be recombined to the
        same value.

        If the verification succeeds, the T double shares are
        returned, otherwise an exception is thrown.
        """
        si_1, si_2 = shares
        self._verify_single(si_1, rvec1, T, field, d1)
        self._verify_single(si_2, rvec2, T, field, d2)
        si_1 = map(lambda (i, s): (field(i + 1), s), enumerate(si_1))
        si_2 = map(lambda (i, s): (field(i + 1), s), enumerate(si_2))

        assert shamir.recombine(si_1[:d1 + 1]) == shamir.recombine(si_2[:d2 + 1]), \
            "Shares do not recombine to the same value"

        return (rvec1[:T], rvec2[:T])
Exemplo n.º 2
0
def convert_replicated_shamir(num_players, player_id, field, rep_shares):
    """Convert a set of replicated shares to a Shamir share.

    The conversion is done for player *j* (out of *n*) and will be
    done over *field*.
    """
    result = 0
    all = frozenset(range(1, num_players + 1))
    for subset, share in rep_shares:
        try:
            f_in_j = _f_in_j_cache[(field, num_players, player_id, subset)]
        except KeyError:
            points = [(field(x), 0) for x in all - subset]
            points.append((0, 1))
            f_in_j = shamir.recombine(points, player_id)
            _f_in_j_cache[(field, num_players, player_id, subset)] = f_in_j
        result += share * f_in_j
    return result
Exemplo n.º 3
0
def prss_zero(n, t, j, field, prfs, key, quantity):
    """Return *quantity* pseudo-random secret zero-sharings of degree 2t.

    >>> from viff.math.field import GF
    >>> from viff.shares.prf import PRF
    >>> Zp = GF(23)
    >>> prfs = {frozenset([1,2]): PRF("a", 7),
    ...         frozenset([1,3]): PRF("b", 7),
    ...         frozenset([2,3]): PRF("c", 7)}
    >>> prss_zero(3, 1, 1, Zp, prfs, "key", 1)
    [{16}]
    >>> prss_zero(3, 1, 2, Zp, prfs, "key", 1)
    [{13}]
    >>> prss_zero(3, 1, 3, Zp, prfs, "key", 1)
    [{14}]

    If we recombine 2t + 1 = 3 shares we can verify that this is
    indeed a zero-sharing:

    >>> from viff.shares.shamir import recombine
    >>> recombine([(Zp(1), Zp(4)), (Zp(2), Zp(0)), (Zp(3), Zp(11))])
    {0}
    """
    # We start by generating t random numbers for each subset. This is
    # very similar to calling random_replicated_sharing t times, but
    # by doing it like this we immediatedly get the nesting we want.
    rep_shares = [(s, [(i + 1, prf((key, i))) for i in range(t)])
                  for (s, prf) in prfs.iteritems() if j in s]

    # We then proceed with the zero-sharing. The first part is like in
    # a normal PRSS.
    result = [0] * quantity
    all = frozenset(range(1, n + 1))
    modulus = field.modulus

    # This is needed for correct exponentiation.
    j = field(j)

    for subset, shares in rep_shares:
        try:
            f_in_j = _f_in_j_cache[(field, n, j, subset)]
        except KeyError:
            points = [(field(x), 0) for x in all - subset]
            points.append((0, 1))
            f_in_j = shamir.recombine(points, j)
            _f_in_j_cache[(field, n, j, subset)] = f_in_j

        # Unlike a normal PRSS we have an inner sum where we use a
        # degree 2t polynomial g_i which we choose as
        #
        #   g_i(x) = f(x) * x**j
        #
        # since we already have the degree t polynomial f at hand. The
        # g_i are all linearly independent as required by the protocol
        # and can thus be used for the zero-sharing.
        for i, packed_share in shares:
            g_i_in_j = f_in_j * j ** i

            for k in range(quantity):
                result[k] += (packed_share % modulus) * g_i_in_j
                packed_share /= modulus

    return result
Exemplo n.º 4
0
# 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/>.

import sys

from viff.math.field import GF, GF256
from viff.shares import shamir

if sys.argv[1].find(":") == -1:
    F = GF(int(sys.argv.pop(1)))
else:
    F = GF256

print "Field: GF%d" % F.modulus

shares = [map(int, arg.split(":")) for arg in sys.argv[1:]]
shares = [(F(id), F(share)) for id, share in shares]

print "Shares:", shares
print "Result:", shamir.recombine(shares)
Exemplo n.º 5
0
    def prss_share(self, inputters, field, element=None):
        """Creates pseudo-random secret sharings.

        This protocol creates a secret sharing for each player in the
        subset of players specified in *inputters*. Each inputter
        provides an integer. The result is a list of shares, one for
        each inputter.

        The protocol uses the pseudo-random secret sharing technique
        described in the paper "Share Conversion, Pseudorandom
        Secret-Sharing and Applications to Secure Computation" by
        Ronald Cramer, Ivan Damgård, and Yuval Ishai in Proc. of TCC
        2005, LNCS 3378. `Download
        <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>`__

        Communication cost: Each inputter does one broadcast.
        """
        # Verifying parameters.
        if element is None:
            assert self.id not in inputters, "No element given."
        else:
            assert self.id in inputters, \
                "Element given, but we are not sharing?"

        n = self.num_players

        # Key used for PRSS.
        key = self.prss_key()

        # The shares for which we have all the keys.
        all_shares = []

        # Shares we calculate from doing PRSS with the other players.
        tmp_shares = {}

        prfs = self.players[self.id].dealer_prfs(field.modulus)

        # Compute and broadcast correction value.
        if self.id in inputters:
            for player in self.players:
                share = prss(n, player, field, prfs[self.id], key)
                all_shares.append((field(player), share))
            shared = shamir.recombine(all_shares[:self.threshold + 1])
            correction = element - shared
            # if this player is inputter then broadcast correction value
            # TODO: more efficient broadcast?
            pc = tuple(self.program_counter)
            for peer_id in self.players:
                if self.id != peer_id:
                    self.protocols[peer_id].sendShare(pc, correction)

        # Receive correction value from inputters and compute share.
        result = []
        for player in inputters:
            tmp_shares[player] = prss(n, self.id, field, prfs[player], key)
            if player == self.id:
                d = Share(self, field, correction)
            else:
                d = self._expect_share(player, field)
            d.addCallback(lambda c, s: s + c, tmp_shares[player])
            result.append(d)

        # Unpack a singleton list.
        if len(result) == 1:
            return result[0]
        else:
            return result
Exemplo n.º 6
0
 def test_shamir_recombine(self):
     shares = [(1, 1), None, None]
     self.assertEquals(shamir.recombine(shares), 1)