示例#1
0
def LagrangeInterpolation(x: int, shares: Shares, p: int) -> int:
    """
    Given t shares calculate the interpolation of the polynomial of degree
    t-1 at point x.
    Input: 
        x: the point where we want to calculate f(x)
        shares: a set of values (xi, yi) randomly sampled from the polynomial
    Returns:
        the value f(x) for the polynomial with degree len(points)-1 (fully determined)
    """
    if not isPrime(p, 40):
        raise ValueError(
            f"{p} is not a prime, please enter the prime with which you have generated the random points"
        )

    #Check all points are distinct
    distinct_xi = set([x for x, y in shares])
    if len(shares) != len(distinct_xi):
        raise ValueError(
            "Points at which we evaluate the polynomial must be all different")

    summands = []
    for i, (xi, yi) in enumerate(shares):
        val = 1
        for j, (xj, yj) in enumerate(shares):
            if i != j:
                val *= (x - xj) * InverseFermat(xi - xj, p) % p

        val *= yi % p
        summands.append(val)

    # cast it to integer (has to be since x and y are all integers and f is polynomial)
    # same time to avoid numerical errors we round the number
    return int(round(sum(summands))) % p
示例#2
0
def reconstruct_bin(shares: List[List[int]], field: int) -> str:
    """
    From the shares reconstruct the binary number
    Input:
        x: integer (smaller than 2**l)
        l: number of bits to encode
        field: The field of the additive sharing
        parties: number of parties for secret sharing
    Output:
        A list of a list of integers with max range field. Each list is
        the share for each party.
    """

    assert isPrime(field, 100), f"{field} is not prime"

    x = []
    l = len(shares[0])

    bit = 0
    while bit < l:
        s = 0
        for share in shares:
            s += share[bit]

        x.append(s % field)
        bit += 1

    return '0b' + ''.join(map(str, x))
示例#3
0
def share_bin(x: int, l: int, field: int, parties: int = 2) -> List[List[int]]:
    """
    Given an integer x, calculate the shares for n parties in the field.
    Input:
        x: integer (smaller than 2**l)
        l: number of bits to encode
        field: The field of the additive sharing
        parties: number of parties for secret sharing
    Output:
        A list of a list of integers with max range field. Each list is
        the share for each party.
    """

    assert isPrime(field, 100), f"{field} is not prime"

    x_bin = to_binl(x, l)
    shares = [[] for _ in range(parties)]

    for bit in x_bin[2:]:
        rdm = []
        for i in range(parties - 1):
            rdm.append(randrange(field))
            shares[i].append(rdm[-1])

        shares[parties - 1].append((int(bit) - sum(rdm)) % field)

    return shares
示例#4
0
    def __init__(self, n: int, p: int):

        self._p = p
        self._n = n

        if not isPrime(p, 100):
            raise ValueError(
                f"{p} is not a prime, please enter the prime to define the field"
            )
示例#5
0
def ShamirRandomPolynomial(s: int, n: int, p: int) -> List[int]:
    """
    Calculates the coeficients living on a field Zp for a polynomial of degree n
    Input:
        s: secret, independent term of the polynomial
        n: degree of the polynomial, we need t=n+1 to reconstruct
        p: prime number to generate the coeffients
    Output:
        A list of integers with the coefficients [a0, a1, a2,...,an]
    """
    # s is the secret (independent term), n the degree of polynomial and p the prime number for the field
    if not isPrime(p, 40):
        raise ValueError(f"p={p} is not prime, please feed a prime")

    coef = [s]
    while len(coef) < n + 1:
        coef.append(randrange(1, p))
    return coef
示例#6
0
def DrawPolynomialPoints(shares: int,
                         coef: List[int],
                         p: int,
                         rng: Tuple[int, int] = (0, 20)) -> Shares:
    """
    Draw distinct points from a coefficient of certain degree and coefficients in a list
    Inputs:
        shares: number of points to be drawn randomly
        coef: the list of coefficients of the polynomial. Degree is len(coef)-1
        p: the prime over which the ring is generated
        rng: range of x to be selected randomly.

    returns:
        A list of tuples [(x0, f(x0)), (x1, f(x1)),...,(x_npoints-1, f(x_npoints-1))]
        those are random points (not repeated) sampled from the polynomial with x in the range
        of the parameter rng

    """
    if not isPrime(p, 40):
        raise ValueError(
            f"{p} is not a prime, please enter the prime that generates the coefficients"
        )
    if len(rng) != 2:
        raise ValueError(
            f"rng value is incorrect, must be a tuple (min, max) in the range of x to draw"
        )

    degree = len(coef) - 1
    x = []
    while len(x) < shares:
        i = randrange(rng[0], rng[1])

        # avoid sharing the secret (i=0) and repeat shares
        if i not in x and i != 0:
            x.append(i)

    # apply modulo operation to the evaluation, otherwise we evaluate regular polynomial
    y = [PolyEvaluateModulo(coef, point, p) for point in x]

    return list(zip(x, y))
示例#7
0
def PolyEvaluateModulo(coef: List[int], x: int, p: int) -> int:
    """
    Horner's method to evaluate polynomial
    coef is a list of the coefficients [a0, a1,..., an], note this is 
    modulo p evaluation. Not real valued polynomials

    Input:
        coef: list of coefficients of the polynomial
        x: input where we want to evaluate the polynomial (x<p)
        p: the prime number over which the ring of polynomials is defined
    Returns:
        f(x), the evaluation of the polynomial at x in modulo 
    """
    if not isPrime(p, 40):
        raise ValueError(f"{p} should be a prime number")
    n = len(coef)
    #apply modulo just in case we lie out of the range of the field
    x = x % p
    coef = coef[::-1]
    r = coef[0]
    for i in range(1, n):
        r = (r * x + coef[i]) % p
    return r