Sage code for Shamir's Secret Sharing Algorithm and Reconstruction using Lagrange Interpolation. Go to cocalc to run the code. You can also install sage on your local machine.


reset()
        
# Random number generation in Zp
def rand_gen(p) :
    Zp = Integers(p)
    return Zp.list()[randint(0,p-1)]
        
# Return a  random polynomial in Zp[X] of degree <= (t-1)
# And through the point (0,s)
def rand_poly_share(s,t,p) :
    Zp = Integers(p)
    R.<X> = Zp[]
    coeffs = []
    for i in [0,..,t-1] :
        if (i==0) :
            coeffs.append(Zp.list()[s])
        else :
            coeffs.append(rand_gen(p))
    #print coeffs
    PX = coeffs[0]
    for i in [1,..,t-1] :
        PX = PX + coeffs[i]*(X^i)
    return PX
            
# Secret share s
# into n-parties
# t-parties can reconstruct
# over Zp
# shares[0] has the secret for sanity check purposes
def shamir_share(s,n,t,p) :
    if (s<0 or s>p-1) :
        return -1
    if (n<1 or n>p-1) :
        return -1
    # Generate a random polynomial consistent with the secret
    PX = rand_poly_share(s,t,p)
    print "...[Internal State] Secret Sharing Polynomial used:", PX
    # Evaluate the polynomial to obtain the shares
    shares = []
    for i in [0..n] :
        shares.append(PX(X=i))
    return shares
                    
                    
# Lagrange Interpolate the list of coordinates using Zp[X] polynomial
def lagrange_interpolation(coords,p) :
    t = len(coords)
    Zp = Integers(p)
    R.<X> = Zp[]
    x_tup, y_tup = zip(*coords)
    x_list = list(x_tup)
    y_list = list(y_tup)
    polys = []
    for i in [0,..,t-1] :
        polys.append(1)
        for j in [0,..,t-1] :
            if (j == i) :
                polys[i] = polys[i]* y_tup[i]
            else :
                polys[i] = polys[i]* (X-x_tup[j]) / (x_tup[i] - x_tup[j])
    print "...[Internal State] List of P_i(X) polynomials:", polys
    PprimeX = 0
    for i in [0,..,t-1] :
        PprimeX = PprimeX + polys[i]
    print "...[Internal State] Reconstructed Polynomial:", PprimeX
    return PprimeX
                        
                        
# Reconstruction algorithm
def reconstruct_secret(coords,p) :
    PprimeX = lagrange_interpolation(coords,p)
    return PprimeX(X=0)
                        
                        
                        
s = 10 ### Input by User ###
n = 16 ### Input by User ###
t = 5  ### Input by User ###
p = 17 ### Input by User ###
                        
print "Secret to be shared:", s
print "Number of parties:", n
print "Number of parties that can reconstruct the secret:", t
print "The prime used as the field size:", p
                        
secret_shares = shamir_share(s,n,t,p)
print "\nThe Secret Shares of Parties:", secret_shares
                        
# Indices of t parties who want to reconstruct the secret
ind = [1,3,4,6,15] ### Input by User ###
print "\nList of parties who want to reconstruct the secret", ind
                        
vals = []
for i in ind :
    vals.append(secret_shares[i])
# Coordinates of reconstruction parties and their respective secret shares
coords = zip(ind,vals)
print "\nCoordinates to Interpolate:" , coords
sprime = reconstruct_secret(coords,p)
print "Reconstructed Secret:", sprime
                        
print "\nIs the reconstructed secret identical to the original secret?", s==sprime