def l(j, x, k): """ Create a Lagrange basis polynomial Reference: https://wikimedia.org/api/rest_v1/media/math/render/svg/6e2c3a2ab16a8723c0446de6a30da839198fb04b """ polys = [ Poly([-1 * x[m], 1]) / Poly([x[j] - x[m]]) for m in range(k) if m != j ] return reduce(lambda acc, p: acc * p, polys, 1)
def __init__(self, secret, n, k, p): """ S: secret n: total number of shares k: recovery threshold p: prime, where p > S and p > n """ self.n = n self.k = k self.p = p mBytes = secret.encode("utf-8") Sval = int(mBytes.encode('hex'), 16) self.S = Sval production_coefs = [Sval] for coef in range(k - 1): production_coefs.append(randint(1, p - 1)) self.production_poly = Poly(production_coefs) poly = "" for i in reversed(range(len(self.production_poly))): if i != 0: poly += (str(self.production_poly.coef[i]) + "*x^" + str(i) + " + ") else: poly += str(self.production_poly.coef[i]) print "Secret Polynomial is: ", poly
def PolyInverseModOverZn(f: Poly, r: int, zn: int): #r=2, mod zn r = log2 if (r < 1) or (zn < 1): raise ValueError #f = modPoly(f, zn) f0 = f.coef[0] if (not (f0 == 1)): g = Poly(inverse(f0, zn)) else: g = Poly(f0) if (g.coef[0] == None or zn == 1): return None l = int(math.ceil(math.log2(r))) for k in range(1, l + 1): g = (2 * g - f * (g**2)) g = g.truncate(2**k) g = modPoly(g, zn) return g
def test_verify_degree(self): """ Check the degree of the polynomio """ minimum = randint(2, 70) e = self.generate_Encrypter("test_files/") p = self.get_poly(e, "test_files/", minimum) polynomial = Poly(p.generate_random_poly()) assert polynomial.degree() == minimum - 1
def PolyInverseModOverZn(f: Poly, mod_deg: int, mod_ring: int) -> Union[Poly, None]: if mod_deg < 1 or mod_ring < 1: raise ValueError('Модуль не может быть меньше 1') if f.coef[0] == 0 or mod_ring == 1: return None f = Poly(np.mod(f.coef, mod_ring)) c = InverseMod(f.coef[0], mod_ring) if c is None: return None g = Poly([c]) r = int(np.ceil(np.log2(mod_deg))) d = 2 for i in range(r): g = (2 * g - f * g ** 2).truncate(d) g = Poly(np.mod(g.coef, mod_ring)) d <<= 1 return g
def PolyInverseModOverQ(f: Poly, mod_deg: int) -> Union[Poly, None]: if mod_deg < 1: raise ValueError('Не допустимое значение модуля') if f.coef[0] == 0: return None g = Poly([1 / f.coef[0]]) r = int(np.ceil(np.log2(mod_deg))) d = 2 for i in range(r): g = (2 * g - f * g ** 2).truncate(d) d <<= 1 return g
def PolyInverseModOverQ(f: Poly, r: int): #r=2, предполагаем f0[0] = 1 f = f.trim() if (r < 1): raise ValueError #f = modPoly(f, zn) f0 = f.coef[0] if (f0 != Fraction(1, 1)): f0 = 1 / f0 if (f0 == Fraction(0, 1)): return None g = Poly(f0) l = int(math.ceil(math.log2(r))) for k in range(1, l + 1): g = (2 * g - f * (g**2)) g = g.truncate(2**k) return g
def PolyDivModOverQ(a, b: Poly): #−> (Poly , Poly ): while (a.degree() > 0 and a.coef[a.degree()] == Fraction(0, 1)): a = Poly(a.coef[:a.degree()]) while (b.degree() > 0 and b.coef[b.degree()] == Fraction(0, 1)): b = Poly(b.coef[:b.degree()]) if (a.degree() < b.degree()): return Poly([Fraction(0, 1)]), a m = a.degree() - b.degree() revb = Poly(b.coef[::-1]) rrevb = PolyInverseModOverQ(revb, m + 1) if (rrevb is None): raise ZeroDivisionError("ohohoh") q1 = Poly(a.coef[::-1]) * rrevb q1 = Poly(q1.coef[:(m + 1)]) q = Poly(q1.coef[::-1]) r = a - b * q while (r.degree() > 0 and r.coef[r.degree()] == Fraction(0, 1)): r = Poly(r.coef[:r.degree()]) return q, r
def __init__(self, S, n, k, p): """ S: secret n: total number of shares k: recovery threshold p: prime, where p > S and p > n """ self.S = S self.n = n self.k = k self.p = p # Used to generate random coefficients in a production environment # production_coefs = [self.S] + [randint(1, self.S) for i in range(1, k)] # self.D = self.construct_shares() # Making use of the coefficients from Wikipedia's example production_coefs = [1234, 166, 94] self.production_poly = Poly(production_coefs)
def PolyDivModOverQ(a: Poly, b: Poly) -> (Poly, Poly): if not b.coef.any(): raise ZeroDivisionError a = a.trim() b = b.trim() n, m = len(a.coef), len(b.coef) if n < m: return Poly([0]), a else: f = rev(b, m) g = PolyInverseModOverQ(f, n - m + 1) q = (rev(a, n) * g).truncate(n - m + 1) q = rev(q, n - m + 1) if len(q.coef) < n - m + 1: q.coef = np.concatenate([np.zeros(n - len(q)), q.coef]) r = a - b * q r = r.trim() q = r.trim() return q, r
def __init__(self, prime_number, k, n, key): """ Constructs Lagrange Polymial given a prime to use finite field arithmetic Args: prime_number (int): prime number to use finite field arithmetic k (int) : minimun number of shares to reconstruct the polynomial n (int) : number of shares to generate key (int) : secret to save """ self.field_p = Field(prime_number) """ (Field) : Object Field""" self.key = key """ key as the secret given""" self.partial_randomNumber = functools.partial( random.SystemRandom().randint, 0) """ Random Number""" self.k = k """ Polynomial Degree""" self.n = n """ Maximum of shares to be generated""" self.polynomial = Poly(self.generate_random_poly()) """ Polinomio generated"""
def PolyDivModOverZn(a: Poly, b: Poly, mod_r: int) -> (Poly, Poly): if mod_r < 1: raise ValueError if mod_r == 1: raise ZeroDivisionError a = Poly(np.mod(a.coef, mod_r)) b = Poly(np.mod(b.coef, mod_r)) a = a.trim() b = b.trim() n, m = len(a.coef), len(b.coef) if n < m: return Poly([0]), a else: f = rev(b, m) g = PolyInverseModOverZn(f, n - m + 1, mod_r) if g is None: raise ZeroDivisionError q = (rev(a, n) * g).truncate(n - m + 1) q = Poly(np.mod(q.coef, mod_r)) q = rev(q, n - m) if len(q.coef) < n - m + 1: q.coef = np.concatenate([np.zeros(n - m + 1 - len(q)), q.coef]) bq = Poly(np.mod((b * q).coef, mod_r)) r = a - bq r = Poly(np.mod(r.coef, mod_r)) q = Poly(np.mod(q.coef, mod_r)) r = r.trim() q = q.trim() return q, r
def PolyDivModOverZn(a, b: Poly, n: int): #−> (Poly , Poly ): a = a.trim() b = b.trim() if (n < 1): raise ValueError if (a.degree() < b.degree()): return Poly([0]), a m = a.degree() - b.degree() revb = Poly(b.coef[::-1]) rrevb = PolyInverseModOverZn(revb, m + 1, n) if (rrevb is None): raise ZeroDivisionError("") reva = Poly(a.coef[::-1]) q1 = reva * rrevb q1 = q1.truncate(m + 1) q = Poly(q1.coef[::-1]) q = modPoly(q, n) bq = b * q bq = modPoly(bq, n) r = modPoly(a - b * q, n) r = Poly(r.coef[::-1]) r.trim() r = Poly(r.coef[::-1]) return q, r
def rev(p: Poly, n: int) -> Poly: p = p.trim() result = p.coef[::-1] if len(p.coef) < n: result = np.concatenate([np.zeros(n - len(p.coef)), result]) return Poly(result)
def test_poly_div_quotient(f, g): res = poly_div(Poly(f), Poly(g))[0].coef res_np = list(polydiv(f, g)[0]) print(res) print(res_np) assert np.allclose(res, res_np)
def modPoly(f: Poly, n: int): coefs = f.coef for i in range(len(coefs)): coefs[i] = coefs[i] % n return Poly(coefs)