def mod_get_powers(a: int, n: int, p: int) -> List[nmod]: """ returns a list 1, a, a^2, a^{n-1} mod p example: mod_get_powers(3, 4, 7) = [1, 3, 9, 27] (mod 7) = [1, 3, 2, 6] """ if n < 1: raise FuzzyError("upper power n is not positive") if p < 2 or not isprime(p): raise FuzzyError("prime is not prime") if a == 0: ans = [nmod(1, p)] ans.extend([nmod(0, p)] * (n-1)) return ans def my_gen(): """ This is a generator that yields 1, a, a^2, ..., a^(n-1) (mod p) """ x = nmod(a, p) y = nmod(1, p) for _ in range(n): yield y y *= x return list(my_gen())
def test_nmod_poly(): P = flint.nmod_poly Z = flint.fmpz_poly assert P([], 17) == P([0], 17) assert P([1, 2, 3], 17) == P([1, 2, 3], 17) assert P([1, 2, 3], 17) != P([1, 2, 3], 15) assert P([1, 2, 3], 17) != P([1, 2, 4], 15) assert P(Z([1, 2, 3]), 17) == P([1, 2, 3], 17) assert P([1, 2, flint.nmod(3, 17)], 17) == P([1, 2, 3], 17) assert raises(lambda: P([1, 2, flint.nmod(3, 15)], 17), ValueError) assert P([1, 2, 3], 17).degree() == 2 assert P([1, 2, 3], 17).length() == 3 assert P([1, 2, 3], 17) + 2 == P([3, 2, 3], 17) assert 2 + P([1, 2, 3], 17) == P([3, 2, 3], 17) assert P([1, 2, 3], 17) + P([3, 4, 5], 17) == P([4, 6, 8], 17) assert P([1, 2, 3], 17) + P([3, 4, 5], 17) == P([4, 6, 8], 17) assert P([1, 2, 3], 17) - 2 == P([16, 2, 3], 17) assert 2 - P([1, 2, 3], 17) == -P([16, 2, 3], 17) assert P([1, 2, 3], 17) - P([3, 4, 6], 17) == P([15, 15, 14], 17) assert P([1, 2, 3], 17) * 2 == P([2, 4, 6], 17) assert 2 * P([1, 2, 3], 17) == P([2, 4, 6], 17) assert P([1, 2, 3], 17) * P([1, 2, 3], 17) == P([1, 4, 10, 12, 9], 17) assert P([1, 2, 3], 17) * Z([1, 2, 3]) == P([1, 4, 10, 12, 9], 17) assert Z([1, 2, 3]) * P([1, 2, 3], 17) == P([1, 4, 10, 12, 9], 17) assert P([1, 2, 3, 4, 5], 17) % P([2, 3, 4], 17) == P([12, 12], 17) assert P([1, 2, 3, 4, 5], 17) // P([2, 3, 4], 17) == P([3, 16, 14], 17) assert P([1, 2, 3, 4, 5], 17)**2 == P([1, 2, 3, 4, 5], 17) * P([1, 2, 3, 4, 5], 17) assert P([1, 2, 3], 17) * flint.nmod(3, 17) == P([3, 6, 9], 17) assert str(P([1, 2, 3], 17)) == "3*x^2 + 2*x + 1" p = P([3, 4, 5], 17) assert p(14) == flint.nmod(2, 17) assert p(P([1, 2, 3], 17)) == P([12, 11, 11, 9, 11], 17)
def test_nmod_poly(): P = flint.nmod_poly Z = flint.fmpz_poly assert P([],17) == P([0],17) assert P([1,2,3],17) == P([1,2,3],17) assert P([1,2,3],17) != P([1,2,3],15) assert P([1,2,3],17) != P([1,2,4],15) assert P(Z([1,2,3]),17) == P([1,2,3],17) assert P([1,2,flint.nmod(3,17)],17) == P([1,2,3],17) assert raises(lambda: P([1,2,flint.nmod(3,15)],17), ValueError) assert P([1,2,3],17).degree() == 2 assert P([1,2,3],17).length() == 3 assert P([1,2,3],17) + 2 == P([3,2,3],17) assert 2 + P([1,2,3],17) == P([3,2,3],17) assert P([1,2,3],17) + P([3,4,5],17) == P([4,6,8],17) assert P([1,2,3],17) + P([3,4,5],17) == P([4,6,8],17) assert P([1,2,3],17) - 2 == P([16,2,3],17) assert 2 - P([1,2,3],17) == -P([16,2,3],17) assert P([1,2,3],17) - P([3,4,6],17) == P([15,15,14],17) assert P([1,2,3],17) * 2 == P([2,4,6],17) assert 2 * P([1,2,3],17) == P([2,4,6],17) assert P([1,2,3],17) * P([1,2,3],17) == P([1,4,10,12,9], 17) assert P([1,2,3],17) * Z([1,2,3]) == P([1,4,10,12,9], 17) assert Z([1,2,3]) * P([1,2,3],17) == P([1,4,10,12,9], 17) assert P([1,2,3,4,5],17) % P([2,3,4],17) == P([12,12],17) assert P([1,2,3,4,5],17) // P([2,3,4],17) == P([3,16,14],17) assert P([1,2,3,4,5],17) ** 2 == P([1,2,3,4,5],17) * P([1,2,3,4,5],17) assert P([1,2,3],17) * flint.nmod(3,17) == P([3,6,9],17) assert str(P([1,2,3],17)) == "3*x^2+2*x+1" p = P([3,4,5],17) assert p(14) == flint.nmod(2,17) assert p(P([1,2,3],17)) == P([12,11,11,9,11],17)
def bit_pow_mod_n(b, m, n): acc = nmod(1, n) z = nmod(b, n) while m: if m & 1: # check the least significant bit acc *= z z *= z m >>= 1 # the bit shift return fmpz(acc)
def my_gen(): """ This is a generator that yields 1, a, a^2, ..., a^(n-1) (mod p) """ x = nmod(a, p) y = nmod(1, p) for _ in range(n): yield y y *= x
def row_echelon(A: nmod_mat) -> None: """ Convert A in place to row echelon (upper triangular) form with ones along the diagonal (if possible) """ nrows: int = A.nrows() ncols: int = A.ncols() h: int = 0 # pivot row k: int = 0 # pivot column while h < nrows and k < ncols: try: swap_rows_to_get_nonzero_pivot_point(A, h, k) assert A[h, k] != nmod(0, A.modulus()) scale: nmod = 1 / A[h, k] for i in range(k, ncols): A[h, i] *= scale for i in range(h + 1, nrows): f: nmod = A[i, k] A[i, k] = 0 for j in range(k + 1, ncols): A[i, j] -= A[h, j] * f h += 1 k += 1 except GetRowIndexError: k += 1
def get_ek(self, words: List[int]) -> bytes: """ Returns the bytes constant used in the RecoverSecret loop It is passed into key_derivation returns (s_1 * a_1) * (s_2 * a_2) * ... * (s_n * a_n) (mod p) """ sList = self.extractor aList = words aList.sort() e: nmod = nmod(1, self.prime) for i in range(self.setSize): e *= sList[i] * aList[i] return scrypt.hash("key:" + str(e), self.salt)
def Berlekamp_Welch( aList: List[int], # inputs bList: List[int], # received codeword k: int, t: int, p: int # prime ) -> nmod_poly: """ Berlekamp-Welsch-Decoder This function throws an exception if no solution exists see https://en.wikipedia.org/wiki/Berlekamp%E2%80%93Welch_algorithm """ if len(aList) < 1: raise FuzzyError("aList is empty") if len(aList) != len(bList): raise FuzzyError("bList is empty") if k < 1 or t < 1: raise FuzzyError("k={0} and t={1} are not consistent".format(k, t)) if p < 2 or not isprime(p): raise FuzzyError("p is not prime") n = len(aList) # Create the Berlekamp-Welch system of equations # and store them as an n x n matrix 'm' and a # constant source vector 'y' of length n m_entries: List[nmod] = [] y_entries: List[nmod] = [] for i in range(n): a: int = aList[i] b: int = bList[i] apowers: List[nmod] = mod_get_powers(a, k + t, p) for j in range(k+t): m_entries.append(apowers[j]) for j in range(t): m_entries.append(-b * apowers[j]) y_entries.append(b * apowers[t]) m: nmod_mat = nmod_mat(n, n, m_entries, p) y: nmod_mat = nmod_mat(n, 1, y_entries, p) # solve the linear system of equations m * x = y for x try: x = gauss.solve(m, y).entries() except gauss.NoSolutionError: raise FuzzyError("No solution exists") # create the polynomials Q and E Qs: List[nmod] = x[:k+t] Es: List[nmod] = x[k+t:] Es.append(nmod(1, p)) Q: nmod_poly = nmod_poly(Qs, p) E: nmod_poly = nmod_poly(Es, p) Answer: nmod_poly = Q // E Remainder: nmod_poly = Q - Answer * E if len(Remainder.coeffs()) > 0: raise FuzzyError("Remainder is not zero") return Answer