def reduce_p(f, p, output=True): f = process(f) if any(type(c) != int for c in f.coef) or f.coef[-1] % p == 0: return "cannot apply" F = Zn(p) g = polynom(f.coef, True, F) print(g) if f.deg() == 2 or f.deg() == 3: for i in range(0, p): if output: print("g(%s) = %s" %(F(i), g(F(i)))) if g(F(i)) == 0: return "inconclusive" return "irreducible" else: for i in range(0, p): if output: print("g(%s) = %s" %(F(i), g(F(i)))) if g(F(i)) == 0: return "inconclusive" for i in range(2, math.ceil((len(g.coef))/2)): for fn in itertools.product(*[[F(i) for i in range(0, p)] for q in range(0, i+1)]): if fn == tuple([F(0) for i in range(0, i+1)]) or fn[-1] == F(0): continue h = polynom(list(fn), True, F) temp = divmod(g, h) if output: print("%s = (%s)(%s) + (%s)" %(g, h, temp[0], temp[1])) if not temp[1]: return "inconclusive" return "irreducible"
def generate_test_functions(): from random import randint m = randint(10, 30) n = randint(2, m) f = polynom([randint(1, 10)] + [randint(-30, 30) for i in range(0, m)]) g = polynom([randint(1, 10)] + [randint(-30, 30) for i in range(0, n)]) return (f, g)
def karatsuba(a, b): if type(a) == int and type(b) == int: n = max(int_len(a), int_len(b)) m = int(n/2) base = 10 basem = base**m a1 = int(a/basem) a0 = a%basem b1 = int(b/basem) b0 = b%basem z2 = a1*b1 z0 = a0*b0 z1 = (a1 + a0)*(b1 + b0) - z2 - z0 return z2*(base**(2*m)) + z1*basem + z0 if type(a) == polynom and type(b) == polynom: if not len(a) or not len(b): return polynom(0) n = max(len(a), len(b)) m = int(n/2) a1 = a >> m a0 = polynom(a.coef[0:m], True, a.ring) b1 = b >> m b0 = polynom(b.coef[0:m], True, b.ring) z2 = a1*b1 z0 = a0*b0 z1 = (a1 + a0)*(b1 + b0) - z2 - z0 return (z2 << 2*m) + (z1 << m) + z0
def ExpandKey(self): result = self.keys[0] temp = result[-1] for i in range(4): if i % 4 == 0: temp = self.ShiftRows(['', temp])[1] temp = self.SubBytes([temp])[0] if self.Rcon == False: self.Rcon = polynom('1') else: self.Rcon *= polynom('10') if self.Rcon()[1] >= 0x80: self.Rcon += polynom(bin(0x11b)[2:]) tmp = int(self.Rcon()[2], 16) ^ int(temp[0], 16) temp = [hex(tmp)[2:]] + temp[1:] tmp1 = [] for j in range(4): tmp2 = hex(int(temp[j], 16) ^ int(result[i][j], 16))[2:] tmp1 += ["0" * ((2 - len(tmp2)) % 2) + tmp2] result += [tmp1] temp = tmp1 keys = [] for i in range(len(result) // 4): keys += [result[4 * i:4 * (i + 1)]] return keys
def AddRoundKey(self, mat): result = mat[:] key = self.TransposeMat(self.keys[0]) for i in range(len(mat)): for j in range(len(mat[i])): tmp = (polynom(bin(int(result[i][j], 16))[2:]) + polynom(bin(int(key[i][j], 16))[2:]))()[2] result[i][j] = "0" * ((2 - len(tmp)) % 2) + tmp self.keys = self.ExpandKey() self.keys = self.keys[1:] return mat
def mix(self, line): if len(line) != 4: return False result = [] mat = [['02', '03', '01', '01'], ['01', '02', '03', '01'], ['01', '01', '02', '03'], ['03', '01', '01', '02']] for i in range(4): tmp = polynom('0') for j in range(4): tmp += polynom(bin(int(mat[i][j]))[2:]) * polynom( bin(int(line[j], 16))[2:]) result += ["0" * ((2 - len(tmp()[2])) % 2) + tmp()[2]] return result
def divp(a, b): if a.deg() < b.deg(): raise Exception("a has to have degree greater than or equal to b's.") if a.ring != b.ring: raise Exception("a and b have to be polynomials over the same ring.") print("$a(x) =", a, "$") print("$b(x) =", b, "$") l_num = max([abs(coef) for coef in a.coef + b.coef]) l = floor(log(abs(l_num))) + 1 #print("$l$ is the number of digits in $", l_num, "$, which is ", l) q = [] ap = a c = b.coef[-1] m = ap.deg() n = b.deg() powers = [1, c] for i in range(2, m-n+1): powers.append(powers[-1]*c) loop_num = 1 while m >= n: ap_norm = max([abs(coef) for coef in ap.coef]) l_ap = floor(log(abs(ap_norm))) + 1 #print("At the beginning of the %sth iteration through the loop, $\\norm[\\infty]{a^\\prime} =" %(loop_num), ap_norm, "$, with number of digits $", l_ap, "$ and it is", l_ap <= loop_num*l, "that $L(\\norm[\\infty]{a^\\prime})$ is $\O(il)$") #print("Also, $a^\\prime =", ap, "$") #print("And so far, $q =", polynom(q, ring=a.ring), "$") d = ap.coef[-1]*powers[m-n] #print("So $d =", d, "$") q.append(d) ap = c*ap - ap.coef[-1]*(b << m-n) # This is b * x^{m-n}, I implemented multiplying by x^n as polynom << n. for i in range(1, min(m - ap.deg() - 1, m - n) + 1): q.append(0) ap = c*ap m = ap.deg() loop_num += 1 q = polynom(q, ring=a.ring) r = ap #print("Finally, we are left with $q =", q, "$ and $r =", r, "$") return (q, r)
def mod_gcd2(a, b): if a.ring != int or b.ring != int: return "Nope" print("Step (1)") cont_a = gcd(*a.coef) cont_b = gcd(*b.coef) a = a / cont_a b = b / cont_b cont_gcd = gcd(cont_a, cont_b) print(cont_gcd) d = gcd(a.coef[-1], b.coef[-1]) M = LandauMignotte(a, b) print("d =", d) print("M =", M) primes = sieve_eratosthenes(int(M+1)) prime_index = 0 while True: print("Step (2)") while (a.coef[-1] % primes[prime_index] == 0 and b.coef[-1] % primes[prime_index] == 0): prime_index += 1 p = primes[prime_index] prime_index += 1 c_p = gcd(a.change_ring(Zn(p)), b.change_ring(Zn(p))) c_p = c_p*~c_p.coef[-1] g_p = (d % p)*c_p print("with p =", p, "g_p =", g_p) while True: print("Step (3)") if g_p.deg() == 0: return polynom([1]) P = p g = g_p print("P =", P, "and g =", g) print("Step (4)") while P <= M: print("P =", P) while (a.coef[-1] % primes[prime_index] == 0 or b.coef[-1] % primes[prime_index] == 0): prime_index += 1 p = primes[prime_index] prime_index += 1 c_p = gcd(a.change_ring(Zn(p)), b.change_ring(Zn(p))) c_p = c_p*~c_p.coef[-1] g_p = (d % p)*c_p print("with p =", p, "g_p =", g_p) if g_p.deg() < g.deg(): print("New g_p has lower degree than the previous one.") break if g_p.deg() == g.deg(): print("Degrees match when p =", p) g = polynom([CRA2(g.coef[i], g_p.coef[i], P, p) for i in range(0, len(g.coef))], True) P *= p print("g =", g) else: print("P =", P, "> M =", M, "so time to test for completion with g =", g) if any(coef > M for coef in g.coef): print("Positive coefficients are too large - we must have negative coefficients.") coefs = [] for coef in g.coef: if coef > M: coefs.append(coef - P) else: coefs.append(coef) alt_g = polynom(coefs, True) if gcd(*alt_g.coef) != 1: alt_g = alt_g/gcd(*alt_g.coef) print("Primitive part =", alt_g) if not a % alt_g and not b % alt_g: return cont_gcd*alt_g else: if gcd(*g.coef) != 1: g = g/gcd(*g.coef) print("Primitive part =", g) if not a % g and not b % g: return cont_gcd*g break