def __init__(self, k, r, gen: list = None): super().__init__(k, r, name='ADR') if gen is None: self.F = ffield.FField(r) else: if not isinstance(gen, list) or len( gen) != r + 1 or gen.count(0) + gen.count(1) != len(gen): raise Exception('generator polynom error') gen = binlist2int(gen) self.F = ffield.FField(r, gen, useLUT=0) # create GF(2^r)
def __init__(self, k: int, r: int, gen: list = None): super().__init__(k=k, r=r, name='TS') s = (k / r - 1) / 2.0 if int(s) != s: raise Exception('TS parameters error: k != (2*s+1)*r') self.s = int(s) # convert double to int. if gen is None: self.F = ffield.FField(r) else: if not isinstance(gen, list) or len( gen) != r + 1 or gen.count(0) + gen.count(1) != len(gen): raise Exception('generator polynom error') gen = binlist2int(gen) self.F = ffield.FField(r, gen, useLUT=0) # create GF(2^r)
def reconstruct_secret_cheating(shares_f, shares_g, degree, field_base=8): ''' :param shares: shares. eg. shares = ['52-4cb1787cc758426bc82aebb44050', 'e1-31770e32acb4091ca4e43c000316', 'e2-078f51a8d8e4f2f2b2b00529de62'] :param degree: the degree of the polynomial :param field_base: usually 8 :return: return the original secret in string or give a cheating notification ''' F = ffield.FField(field_base) if len(shares_f) <= degree or len(shares_g) <= degree: raise ValueError("The number of shares must be ") if len(shares_f) != len(shares_g): raise ValueError("Please enter equal number of shares from f and g") xy_value_f = get_points(shares_f) x_values_f = xy_value_f[0] xy_value_g = get_points(shares_g) x_values_g = xy_value_g[0] secret = '' for i in range(1, len(xy_value_f)): y_values_f = xy_value_f[i] y_values_g = xy_value_g[i] s_f, a1_f = lagrange_interpolation_getcoefficients([x_values_f, y_values_f], field_base) s_g, a1_g = lagrange_interpolation_getcoefficients([x_values_g, y_values_g], field_base) secret += chr(s_f) for r in range (2**field_base): test1 = F.Add(s_g, F.Multiply(s_f, r)) test2 = F.Add(a1_g, F.Multiply(a1_f, r)) if test1 == 0 and test2 == 0: print("No cheating detected!") return secret print ("Cheating detected!") return 0
def __init__(self, n, p): self.coeff_table = list() self.dig_table = list() self.cyclomatic_classes = list() self.m = int(math.log(n, 2)) + 1 self.size = 2 ** self.m - 1 self.p = p #self.entropy = (-1) * p * math.log2(p) + (-1) * (1 - p) * math.log2(1 - p) self.entropy = (-1) * p * math.log(p, 2) + (-1) * (1.0 - p) * math.log(1.0 - p, 2) self.r = int(self.size * self.entropy) + 1 self.k = self.size - self.r self.d = self.calculate_dist() self.t = (self.d - 1) // 2 self.F = ffield.FField(self.m) one = 1 self.dig_table.append(one) self.coeff_table.append(list(self.F.ShowCoefficients(one))) alpha = 2 self.coeff_table.append(list(self.F.ShowCoefficients(alpha))) self.dig_table.append(alpha) beta = alpha for i in range(2, self.size + 1): beta = self.F.Multiply(alpha, beta) self.dig_table.append(beta) self.coeff_table.append(list(self.F.ShowCoefficients(beta))) self.create_cyclomatic_classes() self.gen_poly = self.create_generate_poly(self.t) self.verify_poly = self.create_verify_poly() return
def lagrange_interpolation_getcoefficients(points, field_base=8): ''' :param points: a list of two lists. the first list element is the list of x values, the second list element is the list of y values :param field_base: base of the field. usually 8 :return: a0, a1, a0 is the constant term of polynomial g(x), while a1 is the coefficient of x in polynomial g(x) ''' x_values, y_values = points F = ffield.FField(field_base) a1 = 0 a0 = 0 for i in range(len(x_values)): a1_numerator, denominator = 0, 1 a0_numerator= 1 for j in range(len(x_values)): if i == j: continue a1_numerator = F.Add(a0_numerator, F.Multiply(a1_numerator, F.Subtract(0, x_values[j]))) a0_numerator = F.Multiply(a0_numerator, F.Subtract(0, x_values[j])) denominator = F.Multiply(denominator, F.Subtract(x_values[i], x_values[j])) lagrange_polynomial_a0 = F.Multiply(a0_numerator, F.Inverse(denominator)) lagrange_polynomial_a1 = F.Multiply(a1_numerator, F.Inverse(denominator)) a0 = F.Add(a0, F.Multiply(y_values[i], lagrange_polynomial_a0)) a1 = F.Add(a1, F.Multiply(y_values[i], lagrange_polynomial_a1)) return a0, a1
def __init__(self, n=3, u=1, alphabet=alphabet1): self.n = 3 self.Field = ffield.FField(n) #Galois Field GF(2^n) self.array = [[ alphabet[self.Field.Add(self.Field.Multiply(u, i), 2**n - 1 - j)] for j in range(2**n) ] for i in range(2**n)]
def asyl(A, B, m, c, x1=0, y1=0): "tries to find an invertible solution to the equation AX = YB" "m is field size, c is subgroup " F = ffield.FField(m) n = A.shape[0] a, null = asylmat(A, B, m, c, x1, y1) if a == 0: return "no solution" f = lambda i: null[i][:n**2] g = lambda i: null[i][n**2:] for cnt in range(50): ran1 = np.zeros((n, n), dtype=int) ran2 = np.zeros((n, n), dtype=int) for j in range(a): c = np.random.randint(0, 2**m) for i in range(n): for k in range(n): ran1[i][k] = F.Add(ran1[i][k], F.Multiply(c, f(j)[i * n + k])) ran2[i][k] = F.Add(ran2[i][k], F.Multiply(c, g(j)[i * n + k])) if invble(ran1, m) and invble(ran2, m): return ran1, ran2 return "no invertible solution"
def smul(x, A, m): "scalar matrix multiplication" F = ffield.FField(m) n, m = A.shape B = np.zeros((n, m), dtype=int) for i in range(n): for j in range(m): B[i][j] = F.Multiply(A[i][j], x) return B
def testEvaluations(n: int, l: int, mode: str, R=None, omit_zero=True): """ n: The number of vertices in the complete graph in question l: F_2^l is the field we're working with Returns and prints the fraction of assignments over F_2^l to the edges of the complete graph K_n that yield a nonzero output. """ m = n**2 #edges q = 2**l #field size K = q**m F = ffield.FField(l) zero_count = 0 """ K is an ml bit number. We want to split it up into l bit parts To do this, we pick a K, get just the last l bits by taking the AND with q-1 (which is l 1's) and then rightshifting to get the next l bits. """ #Idea - precompute all the possible relevant monomial values and store them. #Idea - do changes to the unvisited set using sortedcontainers if mode == "random": assert (R is not None) for X in randomAssignments(n, l, R, omit_zero): evaluation = 0 for perm in permutations(list(range(1, n))): monomial = X[0, perm[0]] vtx = 0 for i in range(n - 1): monomial = F.Multiply(monomial, X[vtx, perm[i]]) vtx = perm[i] monomial = F.Multiply(monomial, X[perm[n - 2], 0]) evaluation = F.Add(monomial, evaluation) if evaluation == 0: zero_count += 1 print("When n = ", n, "and l = ", l, "the fraction of nonzeros was: ", 1 - float(zero_count) / R) else: for X in bruteForceAssignments(n, l): evaluation = 0 for perm in permutations(list(range(1, n))): monomial = X[0, perm[0]] vtx = 0 for i in range(n - 1): monomial = F.Multiply(monomial, X[vtx, perm[i]]) vtx = perm[i] monomial = F.Multiply(monomial, X[perm[n - 2], 0]) evaluation = F.Add(monomial, evaluation) if evaluation == 0: zero_count += 1 print("When n = ", n, "and l = ", l, "the fraction of nonzeros was: ", 1 - float(zero_count) / K)
def __init__(self, plainTxt, key, printMode=OFF): self.plainTxt = plainTxt self.key = key self.state = FField(plainTxt) self.printMode = printMode self.currentRound = 10 self.f = ffield.FField(8, gen=0x11B, useLUT=0) print("***********************************************\n" + f"Decrypting: {plainTxt}\n" + f"Using Key : {key}\n" + "***********************************************") self.go()
def calculate_g_shares(x_value, g_coefficients, field_base): ''' This function aims to generate the y value corresponding to the x value in polynomial g(x) ''' #print ("g_coefficients[0]:", g_coefficients[0]) F = ffield.FField(field_base) result = 0 for i in reversed(range(1, len(g_coefficients) - 1)): result = F.Add(F.Multiply(result, x_value), g_coefficients[i]) result = F.Add(F.Multiply(result, x_value), g_coefficients[0]) return result
def multiply_galois_64(a: int, b: int): """ Multiplies a and b in a Galois Field of 2^64 :param a: :param b: :return: """ galois_128 = ffield.FField( 64, 2**64 + 2**63 + 2**62 + 2**60 + 2**59 + 2**57 + 2**54 + 2**53 + 2**52 + 2**51 + 2**46 + 2**44 + 2**43 + 2**42 + 2**41 + 2**40 + 2**39 + 2**38 + 2**34 + 2**31 + 2**0) return galois_128.Multiply(a, b)
def __init__(self, key, legacy=False): """Met en place un moyen de chiffrement.""" # Le polynôme "x^5 + x^2 + 1" est celui par défaut self._f = ffield.FField(5) assert (key.get_size() == 64) self._key = key self._iterations = 6 self.encrypt_one_block = self.encrypt_one_block_legacy if legacy else encrypt_one_block_native
def __init__(self, k: int, r: int, pv: bitarray = None, gen: list = None): """ pv: Punching vector. len(P)=k, w(P)=r gen: generating polynomial in binary vector form. """ super().__init__(k=k, r=r, name='PC') if pv is None: pv = bitarray([0 for _ in range(k - r)] + [1 for _ in range(r)]) if pv.count(1) != r or pv.count(0) != k - r: raise Exception( '{pv} can not be used as punching vector (k={k}, r={r})'. format(pv=pv, k=k, r=r)) self.PV = pv if gen is None: self.F = ffield.FField(k) else: if not isinstance(gen, list) or len( gen) != k + 1 or gen.count(0) + gen.count(1) != len(gen): raise Exception('generator polynom error') gen = binlist2int(gen) self.F = ffield.FField(k, gen, useLUT=0) # create GF(2^k)
def __init__(self): self.field = ffield.FField(163) self.a = ffield.FElement(self.field, 1) self.b = ffield.FElement( self.field, 0x000000020A601907B8C953CA1481EB10512F78744A3205FD) self.n = 0x000000040000000000000000000292FE77E70C12A4234C33 self.h = 2 self.curve_points = self.n * self.h self.g = Point(self, False, 0x3f0eba16286a2d57ea0991168d4994637e8343e36, 0x0d51fbc6c71a0094fa2cdd545b11c5c0c797324f1)
def experiment_4_3(n, m): F = ffield.FField(m) M1 = ran(n, m, "G") M2 = ran(n, m, "G") M3 = ran(n, m, "G") M4 = ran(n, m, "G") M5 = ran(n, m, "G") M6 = ran(n, m, "G") a0 = conj(ran(n, m, "D"), M1, m) a1 = conj(ran(n, m, "D"), M2, m) a2 = conj(ran(n, m, "D"), M3, m) b1 = conj(ran(n, m, "D"), M4, m) b2 = conj(ran(n, m, "D"), M5, m) b3 = conj(ran(n, m, "D"), M6, m) x0 = ran(n, m, "G") x1 = conj(ran(n, m, "D"), M4, m) x2 = conj(ran(n, m, "D"), M5, m) x3 = conj(ran(n, m, "D"), M6, m) y0 = conj(ran(n, m, "D"), M1, m) y1 = conj(ran(n, m, "D"), M2, m) y2 = conj(ran(n, m, "D"), M3, m) y3 = ran(n, m, "G") p = longmul([inv(y0, m), b1, y1], m) cnt = 0 for n1 in range(1, 2**m): for n2 in range(1, 2**m): C = np.zeros((n**2, n**2), dtype=int) for i in range(n): for j in range(n): for k in range(n): C[i * n + j][k] = F.Multiply( mul(M1, inv(M4, m), m)[i][k], mul(M4, inv(M2, m), m)[k][j]) for j in range(n): C[0 * n + j][n + j] = F.Multiply( n1, longmul([M1, p, inv(M2, m)], m)[i][j]) C[1 * n + j][n + j] = F.Multiply( n2, longmul([M1, p, inv(M2, m)], m)[i][j]) for i in range(2, n): for j in range(n): C[i * n + j][i * n + j] = longmul( [M1, p, inv(M2, m)], m)[i][j] d = ns(C, m).shape[0] if d > 1: return False cnt += d return cnt
def mul(A, B, m): "finite-field multiplication" F = ffield.FField(m) n1, m1 = A.shape n2, m2 = B.shape if m1 != n2: return "incompatible dimensions" C = np.zeros((n1, m2), dtype=int) for i in range(n1): for j in range(m2): cnt = 0 for k in range(m1): cnt = F.Add(cnt, F.Multiply(A[i][k], B[k][j])) C[i][j] = cnt return C
def create_finite_field(self): self.coeff_table = list() self.dig_table = list() self.F = ffield.FField(self.m) one = 1 self.dig_table.append(one) self.coeff_table.append(list(self.F.ShowCoefficients(one))) alpha = 2 self.coeff_table.append(list(self.F.ShowCoefficients(alpha))) self.dig_table.append(alpha) beta = alpha for i in range(2, self.size + 1): beta = self.F.Multiply(alpha, beta) self.dig_table.append(beta) self.coeff_table.append(list(self.F.ShowCoefficients(beta))) return
def reshape_as_matrix(input_state): # define GF(2^8) (i.e., GF(256)) field F = ffield.FField(8) # define a matrix in GF(256) output_matrix = genericmatrix.GenericMatrix(size=(4, 4), add=F.Add, sub=F.Subtract, mul=F.Multiply, div=F.Divide) # add the corresponding elements from the input_state to the matrix for i in range(4): output_matrix.SetRow(i, input_state[i * 4:(i * 4) + 4]) return output_matrix
def calculate_shares(x_value, coefficients, secret, field_base=8): """ :param x_value: the x value :param coefficients: coefficients of the polynomial, coefficient[i] is the coefficient of x^(i+1) :param field_base: field base :param secret: the character secret :return: return the y value correspond to the x value """ F = ffield.FField(field_base) s0 = ord(secret) result = 0 for i in reversed(range(len(coefficients))): result = F.Add(F.Multiply(result, x_value), coefficients[i]) result = F.Add(F.Multiply(result, x_value), s0) return result
def __init__(self, bit_length: int = 16, fn_poly: str = 'polynomial.txt'): self.irr_polys_8 = [ 2**8 + 2**4 + 2**3 + 2**2 + 2**0, 2**8 + 2**5 + 2**3 + 2**1 + 2**0, 2**8 + 2**6 + 2**4 + 2**3 + 2**2 + 2**1 + 2**0, 2**8 + 2**6 + 2**5 + 2**1 + 2**0, 2**8 + 2**6 + 2**5 + 2**2 + 2**0, 2**8 + 2**6 + 2**5 + 2**3 + 2**0, 2**8 + 2**7 + 2**6 + 2**1 + 2**0, 2**8 + 2**7 + 2**6 + 2**5 + 2**2 + 2**1 + 2**0 ] self.irr_polys_16 = [ 2**16 + 2**9 + 2**8 + 2**7 + 2**6 + 2**4 + 2**3 + 2**2 + 2**0, 2**16 + 2**12 + 2**3 + 2**1 + 2**0, 2**16 + 2**12 + 2**7 + 2**2 + 2**0, 2**16 + 2**13 + 2**12 + 2**10 + 2**9 + 2**7 + 2**6 + 2**1 + 2**0, 2**16 + 2**13 + 2**12 + 2**11 + 2**7 + 2**6 + 2**3 + 2**1 + 2**0, 2**16 + 2**13 + 2**12 + 2**11 + 2**10 + 2**6 + 2**2 + 2**1 + 2**0, 2**16 + 2**14 + 2**10 + 2**8 + 2**3 + 2**1 + 2**0, 2**16 + 2**14 + 2**13 + 2**12 + 2**6 + 2**5 + 2**3 + 2**2 + 2**0, 2**16 + 2**14 + 2**13 + 2**12 + 2**10 + 2**7 + 2**0, 2**16 + 2**15 + 2**10 + 2**6 + 2**5 + 2**3 + 2**2 + 2**1 + 2**0, 2**16 + 2**15 + 2**11 + 2**9 + 2**8 + 2**7 + 2**5 + 2**4 + 2**2 + 2**1 + 2**0, 2**16 + 2**15 + 2**11 + 2**10 + 2**7 + 2**6 + 2**5 + 2**3 + 2**2 + 2**1 + 2**0, 2**16 + 2**15 + 2**11 + 2**10 + 2**9 + 2**6 + 2**2 + 2**1 + 2**0, 2**16 + 2**15 + 2**11 + 2**10 + 2**9 + 2**8 + 2**6 + 2**4 + 2**2 + 2**1 + 2**0 ] self.polynomial = 0 self.generator = 0 self.bit_length = bit_length self.path_poly = path.join( path.join(path.abspath(path.dirname(__file__)), '../../data/'), fn_poly) self.galois_field = None if path.exists(self.path_poly): # Open previously written polynomial setting with open(self.path_poly, 'r') as file_poly: line_elems = file_poly.readline().split(' ') if int(line_elems[0]) == self.bit_length: self.polynomial = int(line_elems[1]) self.generator = int(line_elems[2]) self.galois_field = ffield.FField(self.bit_length, self.polynomial) if self.polynomial == 0: self.__generate_polynomial()
def __generate_polynomial(self): """ Generates a generator element in the polynomial """ power = 0 res = 1 # Select a random generator possibility # primes_field, _ = _prime_factorize(2 ** self.bit_length - 1) # possibilities = _products(primes_field) possibilities = [i for i in range(2, 2**self.bit_length - 1)] # Select a random irreducible polynomial according to the degree if self.bit_length == 16: self.polynomial = self.irr_polys_16[random.randint( 0, len(self.irr_polys_16) - 1)] elif self.bit_length == 8: self.polynomial = self.irr_polys_8[random.randint( 0, len(self.irr_polys_8) - 1)] else: # TODO select an irreducible polynomial for degrees other than 16 (not required for now) print('Oups') self.galois_field = ffield.FField(self.bit_length, self.polynomial) while True: # Select one random polynomial to check if it is a generator elem = possibilities[random.randint(0, len(possibilities) - 1)] possibilities.remove( elem) # Remove it from remaining possibilities for power in range(2**self.bit_length): res = self.galois_field.Multiply(res, elem) if res == 1: break if power == (2**self.bit_length) - 2: # Generator !!! break self.generator = elem with open(self.path_poly, 'w+') as file_poly: file_poly.write( str(self.bit_length) + ' ' + str(self.polynomial) + ' ' + str(self.generator))
def ffunction(x): x4 = [] for i in range(4): x4.append((x >> (4 * (3 - i))) & 0xffff) F = ffield.FField(16) x4d = [] for i in range(4): for k in range(4): sum = 0 sum += F.Multiply(M[i][k], x4[k]) x4d.append(sum) new_x = 0 for i in range(4): new_x = new_x | (x4d[i] << (4 * (3 - i))) return new_x
def old_init(self, size, m): self.coeff_table = list() self.dig_table = list() self.cyclomatic_classes = list() self.size = size self.m = m self.F = ffield.FField(self.m) one = 1 self.dig_table.append(one) self.coeff_table.append(list(self.F.ShowCoefficients(one))) alpha = 2 self.coeff_table.append(list(self.F.ShowCoefficients(alpha))) self.dig_table.append(alpha) beta = alpha for i in range(2, self.size + 1): beta = self.F.Multiply(alpha, beta) self.dig_table.append(beta) self.coeff_table.append(list(self.F.ShowCoefficients(beta))) self.create_cyclomatic_classes() return
def inv(Y, m): "finds inverse of a square matrix A over the finite field F(2^m)" A = copy.copy(Y) if ns(A, m).shape[0] != 0: # nontrivial nullspace - not invertible! return "not invertible" F = ffield.FField(m) n = A.shape[0] X = np.zeros((n, n), dtype=int) for i in range(n): X[i][i] = 1 for j in range(n): zeros = True for i in range(j, n): if zeros == True and A[i][j] != 0: B = copy.copy(A[i]) B1 = copy.copy(X[i]) C = copy.copy(A[j]) C1 = copy.copy(X[j]) A[i] = C A[j] = B X[i] = C1 X[j] = B1 zeros = False if A[j][j] != 0: B = copy.copy(A[j]) B1 = copy.copy(X[j]) for i in range(n): B[i] = F.Multiply(A[j][i], F.Inverse(A[j][j])) B1[i] = F.Multiply(X[j][i], F.Inverse(A[j][j])) A[j] = B X[j] = B1 for i in range(n): if i != j: B = copy.copy(A[i]) B1 = copy.copy(X[i]) for l in range(n): B[l] = F.Add(A[i][l], F.Multiply(A[j][l], A[i][j])) B1[l] = F.Add(X[i][l], F.Multiply(X[j][l], A[i][j])) A[i] = B X[i] = B1 return X
def syl(A, B, m, c, x1=0, y1=0): "tries to find an invertible solution to the sylvester equation AX = XB" "m is field size, c is subgroup" F = ffield.FField(m) n = A.shape[0] a, null = sylmat(A, B, m, c, x1, y1) if a == 0: return "no solution" f = lambda i: null[i].reshape((n, n)) for cnt in range(20): ran = np.zeros((n, n), dtype=int) for j in range(a): c = np.random.randint(0, 2**m) for i1 in range(n): for i2 in range(n): ran[i1][i2] = F.Add(ran[i1][i2], F.Multiply(c, f(j)[i1][i2])) if invble(ran, m): return ran return "no invertible solution"
def invert_matrix(): field = ffield.FField(7, gen=0x83) matrix = genericmatrix.GenericMatrix(size=(8, 8), zeroElement=0, identityElement=1, add=field.Add, mul=field.Multiply, sub=field.Subtract, div=field.Divide) matrix.SetRow(0, [get_int_from_BV(i) for i in A_matrix[0]]) matrix.SetRow(1, [get_int_from_BV(i) for i in A_matrix[1]]) matrix.SetRow(2, [get_int_from_BV(i) for i in A_matrix[2]]) matrix.SetRow(3, [get_int_from_BV(i) for i in A_matrix[3]]) matrix.SetRow(4, [get_int_from_BV(i) for i in A_matrix[4]]) matrix.SetRow(5, [get_int_from_BV(i) for i in A_matrix[5]]) matrix.SetRow(6, [get_int_from_BV(i) for i in A_matrix[6]]) matrix.SetRow(7, [get_int_from_BV(i) for i in A_matrix[7]]) inverse = matrix.Inverse() for rownum in range(8): row = [bv(i) for i in inverse.GetRow(rownum)] A_Inverse.append(row)
def mix_column(input_state, mode): # define GF(2^8) (i.e., GF(256)) field F = ffield.FField(8) # depending on the mode of operation get the right mix_column matrix if mode == 'E': column_matrix = genericmatrix.GenericMatrix(size=(4, 4), add=F.Add, sub=F.Subtract, mul=F.Multiply, div=F.Divide) row = [2, 3, 1, 1] for i in range(4): column_matrix.SetRow(i, row) row = rotate(row, -1) elif mode == 'D': column_matrix = genericmatrix.GenericMatrix(size=(4, 4), add=F.Add, sub=F.Subtract, mul=F.Multiply, div=F.Divide) row = [14, 11, 13, 9] for i in range(4): column_matrix.SetRow(i, row) row = rotate(row, -1) else: raise ValueError('invalid mode of operation, mode = {0}'.format(mode)) # convert input_state to input_matrix input_matrix = reshape_as_matrix(input_state) # perform matrix multiplication using * operator output_matrix = input_matrix * column_matrix # convert output_matrix to output_state output_state = reshape_as_state(output_matrix) return output_state
def lagrange_interpolation(points, field_base=8, x0=0): ''' :param points: a list of two lists. the first list element is the list of x values, the second list element is the list of y values :param field_base: base of the field. usually 8 :param x0: f(x0) is the secret. We set x0 to be 0 :return: s0, which is also the constant term of the polynomial ''' x_values, y_values = points F = ffield.FField(field_base) f_x = 0 for i in range(len(x_values)): numerator, denominator = 1, 1 for j in range(len(x_values)): if i == j: continue numerator = F.Multiply(numerator, F.Subtract(x0, x_values[j])) denominator = F.Multiply(denominator, F.Subtract(x_values[i], x_values[j])) lagrange_polynomial = F.Multiply(numerator, F.Inverse(denominator)) f_x = F.Add(f_x, F.Multiply(y_values[i], lagrange_polynomial)) print(f_x) return chr(f_x)
def generate_g_polynomial(degree, field_base, f_coefficients, secret): ''' To detect cheating, we generate another polynomial g(x) = a0 + a1x + ... + ak-1x^(k-1), which satisfies a0 + s0*r = 0, a1 + s1*r = 0, r belongs to GF(2^8). Here we denote f(x) = s0 + s1x + ... + sk-1*x^(k-1) This function returns [a0, a1, ... , ak-1] ''' F = ffield.FField(field_base) if degree < 0: raise ValueError("Degree cannot be a negative number.") g_coefficients = [] upper_bound = 2**field_base - 1 random_r = randint(0, upper_bound) s0 = ord(secret) a0 = F.Subtract(0, F.Multiply(random_r, s0)) g_coefficients.append(a0) a1 = F.Subtract(0, F.Multiply(random_r, f_coefficients[0])) g_coefficients.append(a1) for i in range(1, degree): random_coeff = randint(0, upper_bound) g_coefficients.append(random_coeff) return g_coefficients