def __init__(self, bits_modulo=2048, e=2**16 + 1): ''' genera una clau RSA (de 2048 bits i amb exponent públic 2**16+1 per defecte) ''' self.publicExponent = e correct_primes = False while not correct_primes: self.primeP = sympy.randprime(2**(bits_modulo // 2 - 1), 2**(bits_modulo // 2) - 1) self.primeQ = sympy.randprime(2**(bits_modulo // 2 - 1), 2**(bits_modulo // 2) - 1) phi_p = self.primeP - 1 if sympy.gcd(phi_p, self.publicExponent) != 1: continue phi_q = self.primeQ - 1 if sympy.gcd(phi_q, self.publicExponent) != 1: continue correct_primes = True phi_n = (self.primeP - 1) * (self.primeQ - 1) # lcm = phi_p * phi_q / math.gcd(phi_p,phi_q) lcm = sympy.lcm(phi_p, phi_q) self.privateExponent = sympy.invert(self.publicExponent, lcm) self.modulus = self.primeP * self.primeQ self.privateExponentModulusPhiP = self.privateExponent % phi_p self.privateExponentModulusPhiQ = self.privateExponent % phi_q self.inverseQModulusP = sympy.invert(self.primeQ, self.primeP)
def slope(point_a, point_b, a, p): if point_a.x != point_b.x: s = (point_b.y - point_a.y) * invert((point_b.x - point_a.x), p) elif point_a.y == point_b.y: s = (3 * point_a.x ** 2 + a) * invert((2 * point_a.y), p) else: return None return s % p
def slope(point_a, point_b, a, p): global tmp if point_a.x != point_b.x: tmp = point_b.x - point_a.x s = (point_b.y - point_a.y) * invert((point_b.x - point_a.x), p) elif point_a.y == point_b.y: tmp = 2 * point_a.y s = (3 * point_a.x ** 2 + a) * invert((2 * point_a.y), p) else: return None return s % p
def invert_poly(f_poly, R_poly, p): inv_poly = None if is_prime(p): inv_poly = invert(f_poly, R_poly, domain=GF(p)) elif is_2_power(p): inv_poly = invert(f_poly, R_poly, domain=GF(2)) e = int(math.log(p, 2)) for i in range(1, e): inv_poly = ((2 * inv_poly - f_poly * inv_poly**2) % R_poly).trunc(p) else: raise Exception("Cannot invert polynomial in Z_{}".format(p)) return inv_poly
def invert_poly(f_poly, N, p): R_poly = MOD inv_poly = None if is_prime(p): log.debug("Inverting as p={} is prime".format(p)) inv_poly = invert(f_poly, R_poly, domain=GF(p)) elif is_2_power(p): log.debug("Inverting as p={} is 2 power".format(p)) inv_poly = invert(f_poly, R_poly, domain=GF(2)) e = int(math.log(p, 2)) for i in range(1, e): log.debug("Inversion({}): {}".format(i, inv_poly)) inv_poly = ((2 * inv_poly - f_poly * inv_poly**2) % R_poly).trunc(p)
def _check_sign(filePath, signPath): print("Checking sign of the file...") file = open(filePath, 'rb') fileData = file.read() file.close() file = open(signPath, 'rb') signData = file.read() file.close() print("---> STEP #1: Getting r,s, Q_x, Q_y from asn.1 file...") x_q, y_q, r, s = asnGenerator.decodeSign(signData) print("r = ", r) print("s = ", s) print(" Checking if (0 < r < q) & (0 < s < q)...") if ((r > 0 and r < q) and (s > 0 and s < q)): print(" r and s are OK") print("---> STEP #2: Calculating hash of the file...") h = gost34112012256.new(fileData).digest() print(' hash = {0}'.format( gost34112012256.new(fileData).hexdigest())) print("---> STEP #3: Calculating alpha from hash...") alpha = int.from_bytes(h, byteorder="big") print(" Calculating e = alpha (mod q) ...") e = alpha % q if e == 0: print(" e = 0 ---> e = 1") e = 1 else: print(" e != 0") print("---> STEP #4: Calculating v = e^(-1) (mod q) ...") v = invert(e, q) print(" v = ", v) print("---> STEP #5: Calculating z1 = s*v (mod q) ...") print(" Calculating z2 = (-r*v) (mod q) ...") z_1 = (s * v) % q z_2 = (-r * v) % q print("---> STEP #6: Calculating C = z1*P + z2*Q ...") x1, y1 = _mul_points(p_x, p_y, z_1) x2, y2 = _mul_points(x_q, y_q, z_2) x_C, y_C = sum(x1, y1, x2, y2) print(" Calculating R = C_x (mod q) ...") R = x_C % q print(" R = ", R) print("---> STEP #7: Checking if R = r ...") if R == r: print(" ! R = r !") return True else: print(" ! R != r !") return False return False
def init_second_screen(): self.remove_widget(self.first_screen) p = self.p_choice q = self.q_choice self.n = p * q phi = (p - 1) * (q - 1) e = sy.prevprime(int(phi / 2)) while (sy.gcd(e, phi) != 1): e = sy.nextprime(e) if (e > phi): e = sy.nextprime(e % phi) d = sy.invert(e, phi) self.key_pub.text = "Public key (e, n) = (" + str(e) + "," + str( self.n) + ")" self.key_pri.text = "Private key (d, n) = (" + str(d) + "," + str( self.n) + ")" if (len(self.key_pub.text) > 100): self.key_pub.text = "Public key (e, n) = \n(" + str( e) + ",\n" + str(self.n) + ")" if (len(self.key_pri.text) > 100): self.key_pri.text = "Private key (d, n) = \n(" + str( d) + ",\n" + str(self.n) + ")" self.rsa_crack.bind(on_press=crack_rsa) self.add_widget(self.second_screen)
def main(): rsa_crypt = lib.RSACrypto(20, 7) print("params:") rsa_crypt.n = 790129 rsa_crypt.e = 7 rsa_crypt.d = 337579 print("n = ", str(rsa_crypt.n)) print("e = ", str(rsa_crypt.e)) print("d = ", str(rsa_crypt.d)) p = 0 q = 0 iter = 1 while (p * q) != rsa_crypt.n: print(iter) p = decomposition(rsa_crypt.n) q = rsa_crypt.n // rsa_crypt.p iter += 1 m = (p - 1) * (q - 1) d2 = int(sympy.invert(rsa_crypt.e, m)) print("Found p: " + str(p)) print("Found q: " + str(q)) print("Found d: " + str(d2))
def elgamal_ecc_verify(src_file, sign_file): with open(sign_file, mode='rb') as file: encoded_data = file.read() decoder = asn1.Decoder() decoder.start(encoded_data) parse_ans1(decoder) Qx = params[params_dict['Qx']] Qy = params[params_dict['Qy']] p = params[params_dict['p']] a = params[params_dict['a']] # b = params[params_dict['b']] Px = params[params_dict['Px']] Py = params[params_dict['Py']] q = params[params_dict['q']] r = params[params_dict['r']] s = params[params_dict['s']] # First step r = int(r) s = int(s) print('[+] a = ', hex(a)) print('[+] x = ', hex(Px)) print('[+] y = ', hex(Py)) print('[+] p = ', hex(p)) print('[+] r = ', hex(q)) print('[+] P.x = ', hex(Qx)) print('[+] P.y = ', hex(Qy)) if r <= 0 or r >= q or s <= 0 or s >= q: print('[-] Invalid signature! r <= 0 || r >= q || s <= 0 || s >= q ! ') with open(src_file, mode='rb') as file: data = file.read() # Second step # Used sha256, but standard use stribog dgst = sha256(data).digest() # Third step alfa = int.from_bytes(dgst, byteorder='big') e = alfa % q print('[+] e = ', hex(e)) if e == 0: e = 1 # Fourth step v = invert(e, q) # Fifth step z1 = s * v % q z2 = -r * v % q # Sixth step c1 = multiply(Point(Px, Py), z1, a, p) c2 = multiply(Point(Qx, Qy), z2, a, p) C = add(c1, c2, a, p) R = C.x % q # Seventh step if R == r: print('[+] Signature is valid!') else: print('[-] Invalid signature!')
def invert_poly(f_poly, R_poly, p): inv_poly = None if is_prime(p): log.debug("Inverting as p={} is prime".format(p)) inv_poly = invert(f_poly, R_poly, domain=GF(p)) elif is_2_power(p): log.debug("Inverting as p={} is 2 power".format(p)) inv_poly = invert(f_poly, R_poly, domain=GF(2)) e = int(math.log(p, 2)) for i in range(1, e): log.debug("Inversion({}): {}".format(i, inv_poly)) inv_poly = ((2 * inv_poly - f_poly * inv_poly**2) % R_poly).trunc(p) else: raise Exception("Cannot invert polynomial in Z_{}".format(p)) log.debug("Inversion: {}".format(inv_poly)) return inv_poly
def get_H(m_val, t_val, k_vec, g_vec): support = [] g_a = [] k_poly = sympy.Poly(k_vec, alpha, domain='FF(2)') # Store the support of the code into a list for i in range(pow(2, m_val)): if i == 0: # Calculate g(0) a_poly = sympy.reduced(sympy.Poly(sympy.Poly(g_vec, x, domain='FF(2)').eval(0), alpha, domain='FF(2)').args[0], [k_poly])[1].set_modulus(2) else: # Calculate g(a^(i-1)) a_poly = sympy.reduced(sympy.Poly(g_vec, alpha**(i-1), domain='FF(2)').args[0], [k_poly])[1].set_modulus(2) if not a_poly.is_zero: # Only store if it is not zero if i == 0: support.append(sympy.reduced(0, [k_poly])[1].set_modulus(2)) else: support.append(sympy.reduced(alpha**(i-1), [k_poly])[1].set_modulus(2)) g_a.append(a_poly) if args.vv: print('\nSupport:\n', support, '\n\ng(a_n):\n', g_a) col = [] # Store the inverses of g(a) for element in g_a: inverse = sympy.invert(element, k_poly) col.append(inverse) if args.vv: print('\nInverses:\n', col) # Form the Parity check matrix poly_H = [] for i in range(t_val): poly_H_row = [] for j in range(len(support)): top = sympy.Poly.pow(support[j], i) product = sympy.reduced(sympy.Poly.mul(top, col[j]), [k_poly])[1].set_modulus(2) poly_H_row.append(product) poly_H.append(poly_H_row) bin_H = sympy.zeros(t_val * m_val, len(support)) # Turn the parity check matrix into a binary matrix for i in range(t_val): for j in range(len(support)): current_poly = poly_H[i][j].all_coeffs() current_len = len(current_poly) for k in range(current_len): try: bin_H[(i*(m_val))+k,j] = current_poly[current_len-k-1] except: sympy.pprint(bin_H) print('i =', i, ', j =', j, ', k =', k) exit() bin_H, pivot = bin_H.rref(iszerofunc=lambda x: x % 2==0) bin_H = bin_H.applyfunc(lambda x: mod(x,2)) bin_H = fixup_H(bin_H, pivot) return(bin_H)
def _gen_params(self, dimension, fixed_e): if fixed_e is not None: if (fixed_e % 2) == 0: print("Error: e is even number") fixed_e = None if fixed_e < 3: fixed_e = None difference = 2**(dimension // 2 - 2) while True: p = q = 0 # Based on Pollard's p − 1 algorithm generate strong primes # https://en.wikipedia.org/wiki/Pollard%27s_p_%E2%88%92_1_algorithm # (p - 1 = prime * 2) => (p = prime * 2 + 1) while sympy.isprime(p) is False: p_1 = sympy.nextprime( random.getrandbits(dimension // 2 + 1)) * 2 p = p_1 + 1 while sympy.isprime(q) is False: q_1 = sympy.nextprime(random.getrandbits(dimension // 2)) * 2 q = q_1 + 1 # Anti Fermat's factorization method # https://en.wikipedia.org/wiki/Fermat%27s_factorization_method if abs(p - q) > difference: n = p * q if lib.bitcount(n) == dimension: phi = (p - 1) * (q - 1) while True: if fixed_e is None: e = random.randint(3, phi - 1) else: e = fixed_e if sympy.gcd(e, phi) == 1: d = sympy.invert(e, phi) # Anti Wiener's attack # https://en.wikipedia.org/wiki/Wiener%27s_attack if d > 1 / 3 * sympy.root(n, 4): break break self.p = p self.q = q self.n = n self.e = e self.d = int(d) return e, d, n
def init_second_screen(self): self.remove_widget(self.first_screen) p = self.p_choice q = self.q_choice n = p * q phi = (p - 1) * (q - 1) e = sy.nextprime(int(n / 2)) d = sy.invert(e, phi) self.key_pub.text = "Public key: (" + str(e) + ", " + str(n) + ")" self.key_pri.text = "Private key: (" + str(d) + ", " + str(n) + ")" self.add_widget(self.second_screen)
def sum(x_P, y_P, x_Q, y_Q): if (x_P == 0): return x_Q, y_Q if (x_Q == 0): return x_P, y_P if (x_P == x_Q and y_P == y_Q): m = ((3 * x_P * x_P + a) * invert(2 * y_P, p)) % p x_R = (m**2 - x_P - x_Q) % p x_R = int(x_R) y_R = (m * (x_P - x_R) - y_P) % p return x_R, y_R m = ((y_P - y_Q) * invert(x_P - x_Q, p)) % p x_R = (m**2 - x_P - x_Q) % p x_R = int(x_R) y_R = (m * (x_P - x_R) - y_P) % p return x_R, y_R return None
def decrypt(c): alphabet = "abcdefghijklmnopqrstuvwxyz" m = 3 p = "" m_inverse = int(sympy.invert(m, 26)) print m_inverse for i in c: if i in alphabet: index = alphabet.find(i) decrypted_char = alphabet[pow(m_inverse * index, 1, 26)] p += decrypted_char else: p += i return p
def apply(self, a, b, m, evaluation): 'PowerMod[a_Integer, b_Integer, m_Integer]' a_int = a m_int = m a, b, m = a.value, b.value, m.value if m == 0: evaluation.message('PowerMod', 'divz', m) return if b < 0: b = -b if a == 0: evaluation.message('PowerMod', 'ninv', a_int, m_int) return a = sympy.invert(a, m) return Integer(sympy.Mod(a ** b, m))
def inverse(self, matrix): """ compute inverse of a given matrix with mod(26) i.e => return inverse(matrix) mod(26) """ determinant = int(np.linalg.det(matrix)) determinant_inv = int(sympy.invert(determinant, 26)) matrix_adjascent = np.linalg.inv(matrix) * determinant matrix_inv = determinant_inv * matrix_adjascent % 26 matrix_inv = matrix_inv.astype(int) return matrix_inv
def apply(self, a, b, m, evaluation): "PowerMod[a_Integer, b_Integer, m_Integer]" a_int = a m_int = m a, b, m = a.value, b.value, m.value if m == 0: evaluation.message("PowerMod", "divz", m) return if b < 0: b = -b try: a = int(sympy.invert(a, m)) except sympy.polys.polyerrors.NotInvertible: evaluation.message("PowerMod", "ninv", a_int, m_int) return return Integer(pow(a, b, m))
def apply(self, a, b, m, evaluation): 'PowerMod[a_Integer, b_Integer, m_Integer]' a_int = a m_int = m a, b, m = a.value, b.value, m.value if m == 0: evaluation.message('PowerMod', 'divz', m) return if b < 0: b = -b try: a = int(sympy.invert(a, m)) except sympy.polys.polyerrors.NotInvertible: evaluation.message('PowerMod', 'ninv', a_int, m_int) return return Integer(pow(a, b, m))
conn.sendline(str(n)) conn.recvuntil("f_a(n + 0) = ") f0 = int(conn.recvuntil("\n").strip(b"\n").decode()) conn.recvuntil("f_a(n + 1) = ") f1 = int(conn.recvuntil("\n").strip(b"\n").decode()) conn.recvuntil("f_a(n + 4) = ") f4 = int(conn.recvuntil("\n").strip(b"\n").decode()) return f0, f1, f4 if __name__ == '__main__': proof() # n = (1 << 128) - 3 # conn.recvuntil("for n = ") # n = int(conn.recvuntil(",").strip(b",").decode()) conn.recvuntil("= (") p = int(conn.recvuntil(",").strip(b",").strip(b"0x").decode(), 16) # binary = bin(n)[2:].zfill(128) # p1 = new(int(binary[:32], 2) * 2 ** 96) # p2 = new(int(binary[32:], 2)) p0, p1, _ = new((1 << 128) - 6) _, _, p4 = new(int("10" * 64, 2) - 4) # new(n - 5) conn.recvuntil("[Q]uit") conn.sendline("G") conn.recvuntil(": ") conn.sendline(str(p4 * p1 * int(invert(p0, p)) % p)) conn.interactive()
a = 1 b = -(2**1024 + 31336) c = n d = int(root(b ** 2 - 4 * a * c, 2)) p = (-b + d) // (2 * a) q = n // p assert isPrime(p) and isPrime(q) assert p * q == n ''' for ei in range(4096): try: g = gcd(2 ** ei - 1, (p-1) * (q-1)) d = int(invert((2 ** ei - 1) // g, (p-1) * (q-1))) flag = long_to_bytes(pow(pow(ct, d, n), 1 / g)) if b"CCTF" in flag: print(ei) print(flag) break except: print(ei) ''' ei = 3729 g = gcd(2 ** ei - 1, (p-1) * (q-1)) d = int(invert((2 ** ei - 1) // g, (p-1) * (q-1))) flag = long_to_bytes(int(root(pow(ct, d, n), g))) print(flag.decode())
==> fermat(n1) ''' def fermat(n): a = gmpy2.isqrt(n) + 1 b = a ** 2 - n while not gmpy2.iroot(b, 2)[1]: a += 1 b = a ** 2 - n b = gmpy2.iroot(b, 2)[0] return (a + b, a - b) r1, r2 = fermat(n1) phi1 = (r1-1) * (r2-1) d1 = int(invert(e, phi1)) m1 = pow(enc1, d1, n1) flag1 = long_to_bytes(m1) k1, k2 = r1 - 1, r2 - 1 p1 = (r1 ** 5 - 1) // k1 p2 = (r2 ** 5 - 1) // k2 # print(n2 % p1) # print(n2 % p2) # <-- bingo p, q = p2, n2 // p2 phi2 = (p-1) * (q-1) d2 = int(invert(e, phi2)) m2 = pow(enc2, d2, n2) flag2 = long_to_bytes(m2)
G = E([Gx, Gy]) #r = random.randint(1,n) r = _sage_const_32903829104380230318795649424761085390545183133709242454697246715961201857515 print("Clau privada (r) = " + str(r)) public_key = r * G print("Clau publica (r*G) = " + str(public_key)) # b) # Firmar amb la nostra: m1 = b"Cryptography is easy" m2 = b"Fake news!" hash_m1 = hashlib.sha256(m1).hexdigest() hash_m2 = hashlib.sha256(m2).hexdigest() k = _sage_const_2019 kinv = sympy.invert(k, n) punt = k * public_key kinv = sympy.invert(k, n) f1_m1 = int(punt[_sage_const_0]) % n f2_m1 = kinv * (int(hash_m1, _sage_const_16) + f1_m1 * r) % n f1_m2 = int(punt[_sage_const_0]) % n f2_m2 = kinv * (int(hash_m2, _sage_const_16) + f1_m2 * r) % n print("sha256 m1 = " + hash_m1) print("firma m1 = " + str(f1_m1) + ", " + str(f2_m1)) print("sha256 m2 = " + hash_m2) print("firma m2 = " + str(f1_m2) + ", " + str(f2_m2)) # Descobrir la clau privada d'un company Qx, Qy = (
import sympy from pwn import * r = remote('csie.ctf.tw', 10119) n = 29483112906907846550407371381907804051925957834404110624325531950200215274674279351500117069061279396866776918114198748748643519779529947303729199772247349 e = 65537 c = "0x1c9d992fd1c6c9f26b24fb127e3e1ac343eadb0dad36c27747111ad07238bf9bc76d16737f8f7fc6752df563027fc6614a8c803de38bbe6aefca0e7f3ec739ba4" c = int(c, 16) inverse_of_2 = int(sympy.invert(2, n)) c_prime = pow(pow(2, e, n) * c, 1, n) r.send(str(c_prime) + '\n') c_prime_power_d = int(pow(int(r.recvline()[:-1]), 1, n)) m = int(pow(c_prime_power_d * inverse_of_2, 1, n)) stripped_message = str(hex(m))[2:].decode('hex') print stripped_message
# encrypted = a ** e % n = r # encrypted_2 = (a ** e) ** 2 % n = r ** 2 % n # Let m = k_1 * n + r # encrypted ** 2 - encrypted_2 = (r ** 2) - (r ** 2 % n) # Let r ** 2 = k_2 * n + r' (k_2 >= 0) # encrypted ** 2 - encrypted_2 = (k_2 * n + r') - r' = k_2 * n # ==> gcd(n, encrypted ** 2 - encrypted_2) = 0 or n encrypted_2 = oracle_enc(a**2) n = sympy.gcd(n, encrypted_2 - encrypted**2) encrypted, a = encrypted_2, a**2 print("n = {}".format(str(n))) plaintext = oracle_dec(ENC) encrypted_8 = oracle_enc(2**8) inverse = sympy.invert(n % 2**8, 2**8) # ENC = flag ** e % n # encrypted_8 = 2 ** 8 ** e % n # t_cipher = encrypted_8 ** t % n = 2 ** (8 * t) ** e % n # ENC * t_cipher % n = (flag * 2 ** (8 * t)) ** e % n # ==> decrypt(ENC * t_cipher % n) k = 0 t = 1 t_cipher = 1 for _ in xrange(128): t = t * 2**8 # record digest k = k * 2**8 # record flag t_cipher = t_cipher * encrypted_8 % n res = oracle_dec(int(ENC * t_cipher % n))
with open("raw/client_hello_random.bin","rb") as f: m = f.read() with open("raw/server_hello_random.bin","rb") as f: m += f.read() with open("raw/server_key_exchange_curve_type.bin","rb") as f: m += f.read() with open("raw/server_key_exchange_named_curve.bin","rb") as f: m += f.read() with open("raw/server_key_exchange_pubkey_length.bin","rb") as f: m += f.read() with open("raw/server_key_exchange_pubkey.bin","rb") as f: m += f.read() hashed = hashlib.sha512(m).hexdigest() hashed = hashed[:_sage_const_64 ] hashed = int(hashed,_sage_const_16 ) inv2 = sympy.invert(f2,n) w1 = int((hashed*inv2)%n) w2 = int((f1*inv2)%n) P = E([Gx,Gy]) Q = E([Px,Py]) P_ = w1*P + w2*Q print("e) Verificar la firma:") print(f1 == int(P_[_sage_const_0 ])%n)
t *= 2 n8 = 2**8 - res print("{} -> {}".format(Hex(res), Hex(n8))) assert n8 & 1 # 1. recover full n # by finding k = floor(2 ** 2048 / n) byte-by-byte # let t = n * k + r, r < n # then n = floor(t / k) - floor(r / k) # if k > r (i.e. is large enough) then n = floor(t / k) k = 0 t //= 2 # t < n inverse = sympy.invert(n8, 2**8) while t < 2**2048: t = t * 2**8 k = k * 2**8 res = oracle_dec(oracle_enc(t)) k += (t - k * n8 - res) * inverse % 2**8 n = t // k # floor n2 = n**2 print("n = {}".format(str(n))) # 2. decrypt flag # by using homomorphic operations def ctadd(c1, c2): return (c1 * c2) % n2
def get_pref_state(state): a_m = invert(25214903917, 2**48) return (int(a_m) * (int(state) - 11)) & 281474976710655
def inv(x, m): return sympy.invert(x, m)
from Crypto.Util.number import long_to_bytes from sympy import invert def egcd(a, b): #Extended Euclidean Algorithm if a == 0: return (b, 0, 1) else: g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y) n = 56891607317613445737750783421867972775249572399868790441120633009929442237956426430872259524747190957003843589191818005172449569095010326902570697779311445080658255239480648637639774011002922525938326812054289272761548189515649720401657615661945821118048442804640057370308200873641231270154569615397630035523 e1 = 15 e2 = 13 c1 = 56469309419621722745072264207838652962328435946767997622044814783708364014641727623574445134141501637979157915357991990349560025038641029733835390776874211827838349081746055988558104358822972488360758486671776227087938906728676579783033437913622465886682124098078049146249446462955542454130870990925587760172 c2 = 32329112615946008400629911894435459433005895247408214608443373037890224605212549196731172020927876324933946521979508705874232456594545880155126627698928055303619040189497194414548410456513691315796957680520443150673697523600966755935741384614826849213578224143275544065415119993769274896134376873260076292691 gcd, x, y = egcd(e1, e2) assert gcd == 1 assert invert(pow(c2, y, n), n) m = (pow(c1, x, n) * pow(c2, y, n)) % n print(long_to_bytes(m))
def invert_polynomial(f_polynomial, N, p): modulus_polynomial = MOD return invert(f_polynomial, modulus_polynomial, domain=GF(p))