@@ -107,3 +107,72 @@ def mod_inverse(self, number):
107107 if number < 0 :
108108 remainder *= - 1
109109 return (self .prime + remainder ) % self .prime
110+
111+
112+ def shares_to_x_y (self ,shares ):
113+ x = []
114+ y = []
115+ # must be: len(shares[0])//88 == len(shares[0])/88
116+ for i in range (len (shares [0 ])// 88 ):
117+ part_x = []
118+ part_y = []
119+ for share in shares :
120+ part_x .append (self .from_base64 (share [88 * i + 0 :88 * i + 44 ]))
121+ part_y .append (self .from_base64 (share [88 * i + 44 :88 * i + 88 ]))
122+ x .append (tuple (part_x ))
123+ y .append (tuple (part_y ))
124+ return x ,y
125+
126+ # extended_gcd, divmod, lagrange_interpolate are copied from https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
127+
128+ def extended_gcd (self , a , b ):
129+ """
130+ Division in integers modulus p means finding the inverse of the
131+ denominator modulo p and then multiplying the numerator by this
132+ inverse (Note: inverse of A is B such that A*B % p == 1) this can
133+ be computed via extended Euclidean algorithm
134+ http://en.wikipedia.org/wiki/Modular_multiplicative_inverse#Computation
135+ """
136+ x = 0
137+ last_x = 1
138+ y = 1
139+ last_y = 0
140+ while b != 0 :
141+ quot = a // b
142+ a , b = b , a % b
143+ x , last_x = last_x - quot * x , x
144+ y , last_y = last_y - quot * y , y
145+ return last_x , last_y
146+
147+ def divmod (self , num , den , p ):
148+ """Compute num / den modulo prime p
149+
150+ To explain what this means, the return value will be such that
151+ the following is true: den * divmod(num, den, p) % p == num
152+ """
153+ inv , _ = self .extended_gcd (den , p )
154+ return num * inv
155+
156+ def lagrange_interpolate (self , x , x_s , y_s , p ):
157+ """
158+ Find the y-value for the given x, given n (x, y) points;
159+ k points will define a polynomial of up to kth order.
160+ """
161+ k = len (x_s )
162+ assert k == len (set (x_s )), "points must be distinct"
163+ def PI (vals ): # upper-case PI -- product of inputs
164+ accum = 1
165+ for v in vals :
166+ accum *= v
167+ return accum
168+ nums = [] # avoid inexact division
169+ dens = []
170+ for i in range (k ):
171+ others = list (x_s )
172+ cur = others .pop (i )
173+ nums .append (PI (x - o for o in others ))
174+ dens .append (PI (cur - o for o in others ))
175+ den = PI (dens )
176+ num = sum ([self .divmod (nums [i ] * den * y_s [i ] % p , dens [i ], p )
177+ for i in range (k )])
178+ return (self .divmod (num , den , p ) + p ) % p
0 commit comments