def id_dirichlet(fun, N, n): N = Integer(N) if N == 1: return (1, 1) p2 = valuation(N, 2) N2 = 2**p2 Nodd = N // N2 Nfact = list(factor(Nodd)) #print "n = "+str(n) #for j in range(20): # print "chi(%d) = e(%d/%d)"%(j+2, fun(j+2,n), n) plist = [z[0] for z in Nfact] ppows = [z[0]**z[1] for z in Nfact] ppows2 = list(ppows) idems = [1 for z in Nfact] proots = [primitive_root(z) for z in ppows] # Get CRT idempotents if p2 > 0: ppows2.append(N2) for j in range(len(plist)): exps = [1 for z in idems] if p2 > 0: exps.append(1) exps[j] = proots[j] idems[j] = crt(exps, ppows2) idemvals = [fun(z, n) for z in idems] # now normalize to right root of unity base idemvals = [ idemvals[j] * euler_phi(ppows[j]) / n for j in range(len(idemvals)) ] ans = [ Integer(mod(proots[j], ppows[j])**idemvals[j]) for j in range(len(proots)) ] ans = crt(ans, ppows) # There are cases depending on 2-part of N if p2 == 0: return (N, ans) if p2 == 1: return (N, crt([1, ans], [2, Nodd])) if p2 == 2: my3 = crt([3, 1], [N2, Nodd]) if fun(my3, n) == 0: return (N, crt([1, ans], [4, Nodd])) else: return (N, crt([3, ans], [4, Nodd])) # Final case 2^3 | N my5 = crt([5, 1], [N2, Nodd]) test1 = fun(my5, n) * N2 / 4 / n test1 = Integer(mod(5, N2)**test1) minusone = crt([-1, 1], [N2, Nodd]) test2 = (fun(minusone, n) * N2 / 4 / n) % (N2 / 4) if test2 > 0: test1 = Integer(mod(-test1, N2)) return (N, crt([test1, ans], [N2, Nodd]))
def id_dirichlet(fun, N, n): N = Integer(N) if N == 1: return (1, 1) p2 = valuation(N, 2) N2 = 2 ** p2 Nodd = N / N2 Nfact = list(factor(Nodd)) # print "n = "+str(n) # for j in range(20): # print "chi(%d) = e(%d/%d)"%(j+2, fun(j+2,n), n) plist = [z[0] for z in Nfact] ppows = [z[0] ** z[1] for z in Nfact] ppows2 = list(ppows) idems = [1 for z in Nfact] proots = [primitive_root(z) for z in ppows] # Get CRT idempotents if p2 > 0: ppows2.append(N2) for j in range(len(plist)): exps = [1 for z in idems] if p2 > 0: exps.append(1) exps[j] = proots[j] idems[j] = crt(exps, ppows2) idemvals = [fun(z, n) for z in idems] # now normalize to right root of unity base idemvals = [idemvals[j] * euler_phi(ppows[j]) / n for j in range(len(idemvals))] ans = [Integer(mod(proots[j], ppows[j]) ** idemvals[j]) for j in range(len(proots))] ans = crt(ans, ppows) # There are cases depending on 2-part of N if p2 == 0: return (N, ans) if p2 == 1: return (N, crt([1, ans], [2, Nodd])) if p2 == 2: my3 = crt([3, 1], [N2, Nodd]) if fun(my3, n) == 0: return (N, crt([1, ans], [4, Nodd])) else: return (N, crt([3, ans], [4, Nodd])) # Final case 2^3 | N my5 = crt([5, 1], [N2, Nodd]) test1 = fun(my5, n) * N2 / 4 / n test1 = Integer(mod(5, N2) ** test1) minusone = crt([-1, 1], [N2, Nodd]) test2 = (fun(minusone, n) * N2 / 4 / n) % (N2 / 4) if test2 > 0: test1 = Integer(mod(-test1, N2)) return (N, crt([test1, ans], [N2, Nodd]))
def make_curve(q, t, r, k, D, debug=False): """ Description: Finds the curve equation for the elliptic curve (q,t,r,k,D) using the Complex Multiplication method Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: E - elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ assert is_valid_curve(q, t, r, k, D), 'Invalid input. No curve exists.' # check inputs if debug: print('Tested input') poly = hilbert_class_polynomial(D) # compute hilbert class polynomial if debug: print('Computed Hilbert class polynomial') check = False j_inv = poly.any_root(GF(q)) # find j-invariant orig_curve = EllipticCurve(GF(q), j=j_inv) # make a curve E = orig_curve check = test_curve(q, t, r, k, D, E) # see if this is the right curve twist = False if not check: # not the right curve, use quadratic twist E = E.quadratic_twist() check = test_curve(q, t, r, k, D, E) if check: twist = True else: # twist didnt work => j = 0 or 1728 if j_inv == 0: # for j = 0, use sextic twists prim = primitive_root(q) i = 1 while t != E.trace_of_frobenius() and i < 6: E = orig_curve.sextic_twist(power_mod(prim, i, q)) i += 1 elif j_inv == 1728: # for j = 1728, use quartic twists prim = primitive_root(q) i = 1 while t != E.trace_of_frobenius() and i < 4: E = orig_curve.quartic_twist(power_mod(prim, i, q)) i += 1 else: # twist didnt work and j != 0, 1728. this should never happen, so write input to a file for debugging print( 'Error. Quadratic twist failed to find the correct curve with j != 0, 1728. Logging output to debug.txt' ) # this line should never be reached' f = open('debug.txt', 'w') f.write('Twist: ' + str(twist) + '\n') f.write('q: ' + str(q) + '\n') f.write('t: ' + str(t) + '\n') f.write('r: ' + str(r) + '\n') f.write('k: ' + str(k) + '\n') f.write('D: ' + str(D) + '\n') f.write('E: ' + str(E) + '\n') f.write('orig_curve: ' + str(orig_curve)) f.close() return False check = test_curve(q, t, r, k, D, E) twist = True if not check: # didnt find a curve. this should never happen, so write input to a file for debugging print('Error. Failed to find curve. Logging output to debug.txt') f = open('debug.txt', 'w') f.write('Twist: ' + str(twist) + '\n') f.write('q: ' + str(q) + '\n') f.write('t: ' + str(t) + '\n') f.write('r: ' + str(r) + '\n') f.write('k: ' + str(k) + '\n') f.write('D: ' + str(D) + '\n') f.write('E: ' + str(E) + '\n') f.write('orig_curve: ' + str(orig_curve)) f.close() return False return E
def make_curve(q,t,r,k,D,debug=False): """ Description: Finds the curve equation for the elliptic curve (q,t,r,k,D) using the Complex Multiplication method Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: E - elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ assert is_valid_curve(q,t,r,k,D), 'Invalid input. No curve exists.' # check inputs if debug: print('Tested input') poly = hilbert_class_polynomial(D) # compute hilbert class polynomial if debug: print('Computed Hilbert class polynomial') check = False j_inv = poly.any_root(GF(q)) # find j-invariant orig_curve = EllipticCurve(GF(q), j=j_inv) # make a curve E = orig_curve check = test_curve(q,t,r,k,D,E) # see if this is the right curve twist = False if not check: # not the right curve, use quadratic twist E = E.quadratic_twist() check = test_curve(q,t,r,k,D,E) if check: twist = True else: # twist didnt work => j = 0 or 1728 if j_inv == 0: # for j = 0, use sextic twists prim = primitive_root(q) i = 1 while t != E.trace_of_frobenius() and i < 6: E = orig_curve.sextic_twist(power_mod(prim,i,q)) i+=1 elif j_inv == 1728: # for j = 1728, use quartic twists prim = primitive_root(q) i = 1 while t != E.trace_of_frobenius() and i < 4: E = orig_curve.quartic_twist(power_mod(prim,i,q)) i+=1 else: # twist didnt work and j != 0, 1728. this should never happen, so write input to a file for debugging print('Error. Quadratic twist failed to find the correct curve with j != 0, 1728. Logging output to debug.txt') # this line should never be reached' f = open('debug.txt', 'w') f.write('Twist: ' + str(twist) + '\n') f.write('q: ' + str(q) + '\n') f.write('t: ' + str(t) + '\n') f.write('r: ' + str(r) + '\n') f.write('k: ' + str(k) + '\n') f.write('D: ' + str(D) + '\n') f.write('E: ' + str(E) + '\n') f.write('orig_curve: ' + str(orig_curve)) f.close() return False check = test_curve(q,t,r,k,D,E) twist = True if not check: # didnt find a curve. this should never happen, so write input to a file for debugging print('Error. Failed to find curve. Logging output to debug.txt') f = open('debug.txt', 'w') f.write('Twist: ' + str(twist) + '\n') f.write('q: ' + str(q) + '\n') f.write('t: ' + str(t) + '\n') f.write('r: ' + str(r) + '\n') f.write('k: ' + str(k) + '\n') f.write('D: ' + str(D) + '\n') f.write('E: ' + str(E) + '\n') f.write('orig_curve: ' + str(orig_curve)) f.close() return False return E