import numpy as np
from numpy.polynomial import polynomial as P
from prompt_inputs import accept_scheme_parameters, prompt_pooled_parties
# prime quantity to outline the finite area the place coefficients will likely be sampled from
# in observe, FIELD_SIZE > max(n, okay)
FIELD_SIZE = 65521
def generate_polynomial(d, okay):
“””
Parameters:
d: diploma of polynomial to be generated
okay: secret to outline polynomial y-intercept
Returns:
poly: vector of polynomial coefficients & intercept
ordered from intercept time period to largest diploma time period i.e. [k, a_{1}, a_{2},…, a_{t-1}]
“””
# generate random coeffcients from {0,…,p-1}
poly = [random.randint(0, FIELD_SIZE-1) for _ in range(d)]
# coefficient of largest diploma time period should be non-zero
poly[-1] = random.randint(1, FIELD_SIZE-1)
# place secret at y-intercept i.e. p(0) = okay
poly.insert(0, okay)
return poly
def compute_shares(poly, n):
“””
Parameters:
coeff: polynomial coefficients ordered from intercept time period to largest diploma time period i.e. [k, a_{1}, a_{2},…, a_{t-1}]
n: variety of events to distribute secret shares to
Returns:
shares: vector of computed shares
ordered by ascending order of social gathering index i.e. [s_{1}, s_{2},…, s_{n}]
“””
# consider polynomial at x in {1, 2,…, n}
x = np.arange(1, n + 1, 1)
# Generate the Vandermonde matrix
vandermonde = P.polyvander(x=x, deg=len(poly)-1)
# shares = vandermonde * poly
shares = vandermonde @ poly
return shares
def reconstruct_secret(shares, indices):
“””
Parameters:
shares: pooled share values
indices: events akin to pooled share values
Returns:
secret & vector containing polynomial coefficients and secret
“””
# Vandermonde matrix for pooled events
vandermonde = P.polyvander(x=indices, deg=len(indices)-1)
# coeff = inv(Vandermonde) * shares
poly = np.linalg.inv(vandermonde) @ np.array(shares)
# rounding to deal w/ floating pt. precision errors: wrapping integer lists into numpy arrays could promote integers into floats
# polynomial coefficients are integers in {0,…,p-1}
poly = [float(poly[0])] + [round(x) for x in poly[1:]]
print(f”Reconstructed Secret: {poly[0]}”)
print(f”Reconstructed Polynomial: {poly}”)
def display_scheme_info(okay, poly, shares):
“””
Show secret (okay), polynomial, and shares for the collaborating events within the (t, n) secret sharing scheme.
“””
print(f”Secret: {okay}”)
print(f”Polynomial: {poly}”)
print(“Shares:”)
for i, share in enumerate(shares):
print(f” Celebration {i+1}: {share}”)
def most important():
# outline scheme & compute/distribute shares
t, n, okay = accept_scheme_parameters()
poly = generate_polynomial(t-1, okay)
shares = compute_shares(poly, n)
display_scheme_info(okay, poly, shares)
# immediate for shares to pool
pooled_parties = prompt_pooled_parties(t, n)
pooled_shares = [shares[i-1] for i in pooled_parties]
# reconstruct secret from pooled shares
reconstruct_secret(pooled_shares, pooled_parties)