The Example 1 to show its addictive property
import random
from math import ceil
from decimal import Decimal
FIELD_SIZE = 10**5
def reconstruct_secret(shares):
"""
Combines individual shares (points on graph)
using Lagranges interpolation.
`shares` is a list of points (x, y) belonging to a
polynomial with a constant of our key.
"""
sums = 0
prod_arr = []
for j, share_j in enumerate(shares):
xj, yj = share_j
prod = Decimal(1)
for i, share_i in enumerate(shares):
xi, _ = share_i
if i != j:
prod *= Decimal(Decimal(xi)/(xi-xj))
prod *= yj
sums += Decimal(prod)
return int(round(Decimal(sums), 0))
def polynom(x, coefficients):
"""
This generates a single point on the graph of given polynomial
in `x`. The polynomial is given by the list of `coefficients`.
"""
point = 0
# Loop through reversed list, so that indices from enumerate match the
# actual coefficient indices
for coefficient_index, coefficient_value in enumerate(coefficients[::-1]):
point += x ** coefficient_index * coefficient_value
return point
def coeff(t, secret):
"""
Randomly generate a list of coefficients for a polynomial with
degree of `t` - 1, whose constant is `secret`.
For example with a 3rd degree coefficient like this:
3x^3 + 4x^2 + 18x + 554
554 is the secret, and the polynomial degree + 1 is
how many points are needed to recover this secret.
(in this case it's 4 points).
"""
coeff = [random.randrange(0, FIELD_SIZE) for _ in range(t - 1)]
coeff.append(secret)
return coeff
def generate_shares(n, m, secret):
"""
Split given `secret` into `n` shares with minimum threshold
of `m` shares to recover this `secret`, using SSS algorithm.
"""
coefficients = coeff(m, secret)
shares = []
for i in range(1, n+1):
x = i
shares.append((x, polynom(x, coefficients)))
return shares
# Driver code
if __name__ == '__main__':
# (3,5) sharing scheme
t, n = 2, 5
secret_1 = 1234
secret_2 = 1233
print(f'Original Secret_1: {secret_1}')
print(f'Original Secret_2: {secret_2}')
# Phase I: Generation of shares
shares_1 = generate_shares(n, t, secret_1)
shares_2 = generate_shares(n, t, secret_2)
print(f'Shares_1: {", ".join(str(share) for share in shares_1)}')
print(f'Shares_2: {", ".join(str(share) for share in shares_2)}')
diff_shares = []
diff_shares.append((1, shares_1[0][1]+shares_2[0][1]))
diff_shares.append((2, shares_1[1][1]+shares_2[1][1]))
print(diff_shares)
print(f'Reconstructed secret: {reconstruct_secret(diff_shares)}')
The reults
Original Secret_1: 1234
Original Secret_2: 1233
Shares_1: (1, 3256), (2, 5278), (3, 7300), (4, 9322), (5, 11344)
Shares_2: (1, 95205), (2, 189177), (3, 283149), (4, 377121), (5, 471093)
[(1, 98461), (2, 194455)]
Reconstructed secret: 2467
The Example 2 to show its subtractive property
import random
from math import ceil
from decimal import Decimal
FIELD_SIZE = 10**5
def reconstruct_secret(shares):
"""
Combines individual shares (points on graph)
using Lagranges interpolation.
`shares` is a list of points (x, y) belonging to a
polynomial with a constant of our key.
"""
sums = 0
prod_arr = []
for j, share_j in enumerate(shares):
xj, yj = share_j
prod = Decimal(1)
for i, share_i in enumerate(shares):
xi, _ = share_i
if i != j:
prod *= Decimal(Decimal(xi)/(xi-xj))
prod *= yj
sums += Decimal(prod)
return int(round(Decimal(sums), 0))
def polynom(x, coefficients):
"""
This generates a single point on the graph of given polynomial
in `x`. The polynomial is given by the list of `coefficients`.
"""
point = 0
# Loop through reversed list, so that indices from enumerate match the
# actual coefficient indices
for coefficient_index, coefficient_value in enumerate(coefficients[::-1]):
point += x ** coefficient_index * coefficient_value
return point
def coeff(t, secret):
"""
Randomly generate a list of coefficients for a polynomial with
degree of `t` - 1, whose constant is `secret`.
For example with a 3rd degree coefficient like this:
3x^3 + 4x^2 + 18x + 554
554 is the secret, and the polynomial degree + 1 is
how many points are needed to recover this secret.
(in this case it's 4 points).
"""
coeff = [random.randrange(0, FIELD_SIZE) for _ in range(t - 1)]
coeff.append(secret)
return coeff
def generate_shares(n, m, secret):
"""
Split given `secret` into `n` shares with minimum threshold
of `m` shares to recover this `secret`, using SSS algorithm.
"""
coefficients = coeff(m, secret)
shares = []
for i in range(1, n+1):
x = i
shares.append((x, polynom(x, coefficients)))
return shares
# Driver code
if __name__ == '__main__':
# (3,5) sharing scheme
t, n = 2, 5
secret_1 = 1234
secret_2 = 1233
print(f'Original Secret_1: {secret_1}')
print(f'Original Secret_2: {secret_2}')
# Phase I: Generation of shares
shares_1 = generate_shares(n, t, secret_1)
shares_2 = generate_shares(n, t, secret_2)
print(f'Shares_1: {", ".join(str(share) for share in shares_1)}')
print(f'Shares_2: {", ".join(str(share) for share in shares_2)}')
diff_shares = []
diff_shares.append((1, -shares_1[0][1]+shares_2[0][1]))
diff_shares.append((2, -shares_1[1][1]+shares_2[1][1]))
print(diff_shares)
print(f'Reconstructed secret: {reconstruct_secret(diff_shares)}')
Corresponding Results
Original Secret_1: 1234
Original Secret_2: 1233
Shares_1: (1, 78719), (2, 156204), (3, 233689), (4, 311174), (5, 388659)
Shares_2: (1, 80726), (2, 160219), (3, 239712), (4, 319205), (5, 398698)
[(1, 2007), (2, 4015)]
Reconstructed secret: -1
The example to use larger number to substract the less number
import random
from math import ceil
from decimal import Decimal
FIELD_SIZE = 10**5
def reconstruct_secret(shares):
"""
Combines individual shares (points on graph)
using Lagranges interpolation.
`shares` is a list of points (x, y) belonging to a
polynomial with a constant of our key.
"""
sums = 0
prod_arr = []
for j, share_j in enumerate(shares):
xj, yj = share_j
prod = Decimal(1)
for i, share_i in enumerate(shares):
xi, _ = share_i
if i != j:
prod *= Decimal(Decimal(xi)/(xi-xj))
prod *= yj
sums += Decimal(prod)
return int(round(Decimal(sums), 0))
def polynom(x, coefficients):
"""
This generates a single point on the graph of given polynomial
in `x`. The polynomial is given by the list of `coefficients`.
"""
point = 0
# Loop through reversed list, so that indices from enumerate match the
# actual coefficient indices
for coefficient_index, coefficient_value in enumerate(coefficients[::-1]):
point += x ** coefficient_index * coefficient_value
return point
def coeff(t, secret):
"""
Randomly generate a list of coefficients for a polynomial with
degree of `t` - 1, whose constant is `secret`.
For example with a 3rd degree coefficient like this:
3x^3 + 4x^2 + 18x + 554
554 is the secret, and the polynomial degree + 1 is
how many points are needed to recover this secret.
(in this case it's 4 points).
"""
coeff = [random.randrange(0, FIELD_SIZE) for _ in range(t - 1)]
coeff.append(secret)
return coeff
def generate_shares(n, m, secret):
"""
Split given `secret` into `n` shares with minimum threshold
of `m` shares to recover this `secret`, using SSS algorithm.
"""
coefficients = coeff(m, secret)
shares = []
for i in range(1, n+1):
x = i
shares.append((x, polynom(x, coefficients)))
return shares
# Driver code
if __name__ == '__main__':
# (3,5) sharing scheme
t, n = 2, 5
secret_1 = 1234
secret_2 = 1233
print(f'Original Secret_1: {secret_1}')
print(f'Original Secret_2: {secret_2}')
# Phase I: Generation of shares
shares_1 = generate_shares(n, t, secret_1)
shares_2 = generate_shares(n, t, secret_2)
print(f'Shares_1: {", ".join(str(share) for share in shares_1)}')
print(f'Shares_2: {", ".join(str(share) for share in shares_2)}')
diff_shares = []
diff_shares.append((1, shares_1[0][1]-shares_2[0][1]))
diff_shares.append((2, shares_1[1][1]-shares_2[1][1]))
print(diff_shares)
print(f'Reconstructed secret: {reconstruct_secret(diff_shares)}')
Results
Original Secret_1: 1234
Original Secret_2: 1233
Shares_1: (1, 82486), (2, 163738), (3, 244990), (4, 326242), (5, 407494)
Shares_2: (1, 50272), (2, 99311), (3, 148350), (4, 197389), (5, 246428)
[(1, 32214), (2, 64427)]
Reconstructed secret: 1