def siegel_series_dim2(q, p): det_4 = q.Gram_det() * ZZ(4) c = q.content_order() fd = fundamental_discriminant(-det_4) f = (valuation(det_4, p) - valuation(fd, p)) / ZZ(2) return (_siegel_series_dim2(p, c, f + 1) - kronecker_symbol(fd, p) * p * X * _siegel_series_dim2(p, c, f))
def make_curve(k,D): """ Description: Find all MNT curves with embedding degree k and fundamental discriminant D Input: k - embedding degree D - (negative) fundamental discriminant Output: curves - list of the aforementioned elliptic curves; each curve is represented as a tuple (q,t,r,k,D) """ assert k == 3 or k== 4 or k == 6, 'Invalid embedding degree' assert fundamental_discriminant(D) == D, 'Invalid discriminant' if k == 3: curves = _mnt_subcall(k,D, 24,lambda x: ((x % 24 == 19) and kronecker(6,x) == 1), 6, 3, -3, lambda x: (x -3 )//6, lambda x: (x+3)//6, lambda l: 6*l - 1, lambda l: -6*l - 1, lambda l: 12*l*l - 1) if k == 4: curves = _mnt_subcall(k,D,-8, lambda x: ( (x % 8 == 3) and kronecker(-2, x) ==1) or (x == 2) or (x == 8), 3, 2, 1, lambda x: (x-2)//3, lambda x: (x-1)//3, lambda l: -l, lambda l: l+1, lambda l: l*l + l + 1) if k == 6: curves = _mnt_subcall(k,D,-8, lambda x: (x % 8 == 3) and kronecker(-2, x) == 1, 6, 5, 1, lambda x: (x+1)//6, lambda x: (x-1)//6, lambda l: 2*l + 1, lambda l: -2*l + 1, lambda l: 4*l*l + 1) for c in curves: assert is_valid_curve(c[0],c[1],c[2],c[3],c[4]), 'Invalid output' assert k == c[3], 'Bug in code' assert D == c[4], 'Bug in code' return curves
def gen_params_from_r(r,k): """ Description: Finds a fundamental discriminant D to use as input to the Cocks-Pinch method Input: r - prime such that r % k == 1 k - embedding degree Output: r - prime such that r % k == 1 k - embedding degree D - (negative) fundamental discriminant where D is a square mod r """ D = -Integer(Mod(int(random()*(1000)),r)) i = 0 while not kronecker(D,r) == 1: # expected number of iterations of the while loop is 2 D = -Integer(Mod(int(random()*(1000)),r)) i+=1 D = fundamental_discriminant(D) if not (kronecker(D,r) == 1): return r, k, 0 return r,k,D
def method(num_bits,k,D,y,max_trials=10000): """ Description: Runs the Dupont-Enge-Morain method Input: num_bits - number of bits for the prime order r k - embedding degree D - (negative) fundamental discriminant y - coefficient of D in the CM equation num_times - number of iterations of the while loop when searching for q Output: (q,t,r,k,D) - elliptic curve; returns (0,0,0,k,D) if no r was found, and (0,0,r,k,D) if no q was found """ assert fundamental_discriminant(D) == D, 'Invalid discriminant' assert k >= 1, 'Invalid embedding degree' t,r = _method_pt1(num_bits,k,D,y) if r == 0: return 0,0,0,k,D return _method_pt2(t,r,k,D,y,max_trials)
def gen_params_from_r(r, k): """ Description: Finds a fundamental discriminant D to use as input to the Cocks-Pinch method Input: r - prime such that r % k == 1 k - embedding degree Output: r - prime such that r % k == 1 k - embedding degree D - (negative) fundamental discriminant where D is a square mod r """ D = -Integer(Mod(int(random() * (1000)), r)) i = 0 while not kronecker( D, r) == 1: # expected number of iterations of the while loop is 2 D = -Integer(Mod(int(random() * (1000)), r)) i += 1 D = fundamental_discriminant(D) if not (kronecker(D, r) == 1): return r, k, 0 return r, k, D
def method(num_bits, k, D, y, max_trials=10000): """ Description: Runs the Dupont-Enge-Morain method Input: num_bits - number of bits for the prime order r k - embedding degree D - (negative) fundamental discriminant y - coefficient of D in the CM equation num_times - number of iterations of the while loop when searching for q Output: (q,t,r,k,D) - elliptic curve; returns (0,0,0,k,D) if no r was found, and (0,0,r,k,D) if no q was found """ assert fundamental_discriminant(D) == D, 'Invalid discriminant' assert k >= 1, 'Invalid embedding degree' t, r = _method_pt1(num_bits, k, D, y) if r == 0: return 0, 0, 0, k, D return _method_pt2(t, r, k, D, y, max_trials)
def _fc__unramfactor(self, content, det_4): chi = kronecker_character(-det_4) pfacs = prime_factors(det_4) fd = fundamental_discriminant(-det_4) l = [(p, valuation(content, p), (valuation(det_4, p) - valuation(fd, p)) / 2) for p in pfacs] return reduce(operator.mul, [self._fc__unramfactor_at_p(p, ci, fi, chi) for (p, ci, fi) in l])
def make_curve(k, D): """ Description: Find all MNT curves with embedding degree k and fundamental discriminant D Input: k - embedding degree D - (negative) fundamental discriminant Output: curves - list of the aforementioned elliptic curves; each curve is represented as a tuple (q,t,r,k,D) """ assert k == 3 or k == 4 or k == 6, 'Invalid embedding degree' assert fundamental_discriminant(D) == D, 'Invalid discriminant' if k == 3: curves = _mnt_subcall( k, D, 24, lambda x: ( (x % 24 == 19) and kronecker(6, x) == 1), 6, 3, -3, lambda x: (x - 3) // 6, lambda x: (x + 3) // 6, lambda l: 6 * l - 1, lambda l: -6 * l - 1, lambda l: 12 * l * l - 1) if k == 4: curves = _mnt_subcall( k, D, -8, lambda x: ((x % 8 == 3) and kronecker(-2, x) == 1) or (x == 2) or (x == 8), 3, 2, 1, lambda x: (x - 2) // 3, lambda x: (x - 1) // 3, lambda l: -l, lambda l: l + 1, lambda l: l * l + l + 1) if k == 6: curves = _mnt_subcall(k, D, -8, lambda x: (x % 8 == 3) and kronecker(-2, x) == 1, 6, 5, 1, lambda x: (x + 1) // 6, lambda x: (x - 1) // 6, lambda l: 2 * l + 1, lambda l: -2 * l + 1, lambda l: 4 * l * l + 1) for c in curves: assert is_valid_curve(c[0], c[1], c[2], c[3], c[4]), 'Invalid output' assert k == c[3], 'Bug in code' assert D == c[4], 'Bug in code' return curves
def test_promise(r,k,D): """ Description: Tests that r,k,D is a valid input to the Cocks-Pinch method Input: r - prime k - embedding degree D - (negative) funadmental discriminant Output: bool - true iff (r,k,D) is a valid input to the Cocks-Pinch method """ bool = (kronecker(D,r) == 1) # D is a square mod r bool = bool and ( (r-1) % k ==0) # k | r-1 bool = bool and (D == fundamental_discriminant(D)) # check that D is a fundamental discriminant return bool
def test_promise(r, k, D): """ Description: Tests that r,k,D is a valid input to the Cocks-Pinch method Input: r - prime k - embedding degree D - (negative) funadmental discriminant Output: bool - true iff (r,k,D) is a valid input to the Cocks-Pinch method """ bool = (kronecker(D, r) == 1) # D is a square mod r bool = bool and ((r - 1) % k == 0) # k | r-1 bool = bool and (D == fundamental_discriminant(D) ) # check that D is a fundamental discriminant return bool
def is_valid_curve(q,t,r,k,D): """ Description: Tests that (q,t,r,k,D) is a valid elliptic curve Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: bool - true iff there exists an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ if q == 0 or t == 0 or r == 0 or k == 0 or D == 0: return False if not is_prime(q): return False if not is_prime(r): return False if not fundamental_discriminant(D) == D: return False if D % 4 == 0: #check CM equation if not is_square(4*(t*t - 4*q)//D): return False if D % 4 == 1: if not is_square((t*t - 4*q)//D): return False if not (q+1-t) % r == 0: #check r | #E(F_q) return False if not power_mod(q,k,r) == 1: #check embedding degree is k return False return True
def run(num_bits, k): """ Description: Runs the Dupont-Enge-Morain method multiple times until a valid curve is found Input: num_bits - number of bits k - an embedding degree Output: (q,t,r,k,D) - an elliptic curve; if no curve is found, the algorithm returns (0,0,0,k,0) """ j, r, q, t = 0, 0, 0, 0 num_generates = 512 h = num_bits / (euler_phi(k)) tried = [(0, 0)] # keep track of random values tried for efficiency for i in range(0, num_generates): D = 0 y = 0 while (D, y) in tried: # find a pair that we have not tried D = -randint(1, 1024) # pick a small D so that the CM method is fast D = fundamental_discriminant(D) m = 0.5 * (h - log(-D).n() / (2 * log(2)).n()) if m < 1: m = 1 y = randint(floor(2**(m - 1)), floor(2**m)) tried.append((D, y)) q, t, r, k, D = method(num_bits, k, D, y) # run DEM if q != 0 and t != 0 and r != 0 and k != 0 and D != 0: # found an answer, so output it assert is_valid_curve(q, t, r, k, D), 'Invalid output' return q, t, r, k, D return 0, 0, 0, k, 0 # found nothing
def is_valid_curve(q, t, r, k, D): """ Description: Tests that (q,t,r,k,D) is a valid elliptic curve Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: bool - true iff there exists an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ if q == 0 or t == 0 or r == 0 or k == 0 or D == 0: return False if not is_prime(q): return False if not is_prime(r): return False if not fundamental_discriminant(D) == D: return False if D % 4 == 0: #check CM equation if not is_square(4 * (t * t - 4 * q) // D): return False if D % 4 == 1: if not is_square((t * t - 4 * q) // D): return False if not (q + 1 - t) % r == 0: #check r | #E(F_q) return False if not power_mod(q, k, r) == 1: #check embedding degree is k return False return True
def run(num_bits,k): """ Description: Runs the Dupont-Enge-Morain method multiple times until a valid curve is found Input: num_bits - number of bits k - an embedding degree Output: (q,t,r,k,D) - an elliptic curve; if no curve is found, the algorithm returns (0,0,0,k,0) """ j,r,q,t = 0,0,0,0 num_generates = 512 h = num_bits/(euler_phi(k)) tried = [(0,0)] # keep track of random values tried for efficiency for i in range(0,num_generates): D = 0 y = 0 while (D,y) in tried: # find a pair that we have not tried D = -randint(1, 1024) # pick a small D so that the CM method is fast D = fundamental_discriminant(D) m = 0.5*(h - log(-D).n()/(2*log(2)).n()) if m < 1: m = 1 y = randint(floor(2**(m-1)), floor(2**m)) tried.append((D,y)) q,t,r,k,D = method(num_bits,k,D,y) # run DEM if q != 0 and t != 0 and r != 0 and k != 0 and D != 0: # found an answer, so output it assert is_valid_curve(q,t,r,k,D), 'Invalid output' return q,t,r,k,D return 0,0,0,k,0 # found nothing
def __init__(self, num_zeros, min_D, **kwds): self.min_D = min_D params = fundamental_discriminant(min_D, -1) super(QuadraticImaginary, self).__init__(num_zeros, params, **kwds)