Path: blob/master/Public Key/Factoring/utils.py
336 views
# Sage does not implement xgcd or modular multiplicative inverses for polynomials over composite rings, so1# We just roll our own implementation here (which is really adapted pseudocode from Wikipedia)2import random3from sage.all import *45def polynomial_egcd(f, g):6"""7Calculates the polynomial inverse of f with respect to g.8:param f: a univariate polynomial.9:param g: a univariate polynomial.10:return: a polynomial h such that f*h = 1 (mod g)11"""12old_r, r = f, g13old_s, s = 1, 014old_t, t = 0, 11516while r != 0:17try:18q = old_r // r19old_r, r = r, old_r - q * r20old_s, s = s, old_s - q * s21old_t, t = t, old_t - q * t22except:23raise ValueError("No inverse for r in Q.", r)2425return old_r, old_s, old_t2627def polynomial_inv_mod(f, g):28"""29Calculates the polynomial inverse of f with respect to g.30:param f: a univariate polynomial.31:param g: a univariate polynomial.32:return: a polynomial h such that f*h = 1 (mod g)33"""34g, s, _ = polynomial_egcd(f, g)3536if g.degree() > 1:37raise ValueError("No polynomial inverse exists.")3839return s * g.lc()**-14041def generate_cm_prime(D, n=512):42"""43Generates an approximately 2n-bit prime p such that 4p - 1 = D * s^244:param D: a squarefree integer.45:param n: bit-length of s.46:return: prime p47"""48assert D.is_squarefree(), "D must be squarefree."4950while True:51s = randint(2**n, 2**(n + 1) - 1)52t = D * s**2 + 153p = t // 45455if is_prime(p) and t % 4 == 0:56return p5758