#!/usr/bin/env sage proof.all(False) # faster from sage.misc.banner import require_version if not require_version(10, 0, print_message=True): exit('') ################################################################ from parameters import p, f from torsion_basis import even_torsion_basis_E0 ################################################################ from sage.groups.generic import order_from_multiple pari.allocatemem(1 << 34) # 16G if p % 4 != 3: raise NotImplementedError('requires p ≡ 3 (mod 4)') assert (1 << f).divides(p + 1) Fp2. = GF((p,2), modulus=[1,0,1]) sqrtm1 = min(Fp2(-1).sqrt(all=True)) def compute(q, mat, idl, iso1q): print(f'\x1b[33m{q = }\x1b[0m') E0 = EllipticCurve(Fp2, [1,0]) E0.set_order((p+1)^2) if q == 1: E1 = E0 P1, Q1 = even_torsion_basis_E0(E1, f) print(f'E0 = {E1}') print(f'P0 = {P1}') print(f'Q0 = {Q1}') else: Quat. = QuaternionAlgebra(-1, -p) I = Quat.ideal(map(Quat, idl)) # print(f'{I = }') O0 = Quat.quaternion_order(list(map(Quat, orders[0][2]))) # print(f'{O0 = }') O1 = I.right_order() # print(f'{O1 = }') assert I.left_order() == O0 assert O0.is_maximal() and O1.is_maximal() assert I.norm() % 2 from deuring2d import Deuring2D ctx = Deuring2D(p) assert ctx.O0.order == O0 assert ctx.E0 == E0 ctx.sqrtm1 = sqrtm1 P0, Q0 = data[0][1] for deg in range(1,10): print(f'trying {deg = }...') ctx.e = E0.cardinality(extension_degree=2^deg).sqrt().valuation(2) - 1 first = True for suitable in ctx.SuitableIdeals(I, attempts=10**6, bound=10**3): if first: Fbig. = Fp2.extension(2^deg) ctx.E0 = E0.change_ring(Fbig) ctx.P = P0.change_ring(Fbig) ctx.Q = Q0.change_ring(Fbig) assert ctx.e == ctx.E0.order().sqrt().valuation(2) - 1 for _ in range(ctx.e - f): ctx.P = ctx.P.division_points(2)[0] ctx.Q = ctx.Q.division_points(2)[0] ctx.P.set_order(multiple=2^ctx.e) ctx.Q.set_order(multiple=2^ctx.e) first = False try: E1, P1, Q1 = ctx.IdealToIsogeny(I, suitable=suitable) break except Deuring2D.Failure: continue else: continue break else: raise NotImplementedError('Deuring2D failed') E1 = E1.change_ring(Fp2) j = GF(p)(E1.j_invariant()) X = polygen(GF(p)) for A,_ in sorted((256*(X^2-3)^3 - (X^2-4)*j).roots()): E1_ = EllipticCurve(Fp2, [0,A,0,1,0]) try: iso = min(E1.isomorphisms(E1_)) break except ValueError: pass E1 = iso.codomain() P1 = iso._eval(P1) Q1 = iso._eval(Q1) print(f'{E1 = }') P1 *= ctx.P.order() // P0.order() Q1 *= ctx.Q.order() // Q0.order() P1 = P1.change_ring(Fp2) Q1 = Q1.change_ring(Fp2) print(f'{P1 = }') print(f'{Q1 = }') P1.set_order(P0.order()) Q1.set_order(Q0.order()) assert P0.order() == Q0.order() == P1.order() == Q1.order() == 2^f assert P1.weil_pairing(Q1,2^f) == P0.weil_pairing(Q0,2^f)^I.norm() if q == 1: endo_i, = (a for a in E1.automorphisms() if a.scaling_factor() == sqrtm1) else: iso = E1.isomorphism(min(Fp2(-q).sqrt(all=True)), is_codomain=True) try: endo_i = iso * E1.isogeny(None, codomain=iso.domain(), degree=q) except ValueError: assert False # assert endo_i^2 == -q endo_1 = E1.scalar_multiplication(1) endo_j = E1.frobenius_isogeny() endo_k = endo_i * endo_j if __debug__: R = E1.random_point() assert (endo_i^2)(R) == -q*R assert (endo_j^2)(R) == -p*R assert (endo_j*endo_i)(R) == -(endo_i*endo_j)(R) denom = mat.denominator() coprime = denom.prime_to_m_part(lcm(P1.order(), Q1.order())) P1d, Q1d = (inverse_mod(coprime, T.order()) * T for T in (P1, Q1)) denom //= coprime extdeg = next(d for d in range(1,denom+1) if ((denom< = Fp2.extension(extdeg) P1d, Q1d = (T.change_ring(Fbig) for T in (P1d, Q1d)) P1d.set_order(multiple=denom<', file=hfile) print(f'#include ', file=hfile) print(f'#include ', file=hfile) print(f'#include ', file=cfile) print(f'#include ', file=cfile) print(f'#include ', file=cfile) print(''' /** Type for precomputed endomorphism rings applied to precomputed torsion bases. * * Precomputed by the precompute scripts. * * @typedef curve_with_endomorphism_ring_t * * @struct curve_with_endomorphism_ring **/ typedef struct curve_with_endomorphism_ring { ec_curve_t curve; ec_basis_t basis_even; ibz_mat_2x2_t action_i, action_j, action_k; ibz_mat_2x2_t action_gen2, action_gen3, action_gen4; } curve_with_endomorphism_ring_t; '''.strip(), file=hfile) print(f'#define CURVE_E0 (CURVES_WITH_ENDOMORPHISMS->curve)', file=hfile) print(f'#define BASIS_EVEN (CURVES_WITH_ENDOMORPHISMS->basis_even)', file=hfile) print(f'#define ACTION_I (CURVES_WITH_ENDOMORPHISMS->action_i)', file=hfile) print(f'#define ACTION_J (CURVES_WITH_ENDOMORPHISMS->action_j)', file=hfile) print(f'#define ACTION_K (CURVES_WITH_ENDOMORPHISMS->action_k)', file=hfile) print(f'#define ACTION_GEN2 (CURVES_WITH_ENDOMORPHISMS->action_gen2)', file=hfile) print(f'#define ACTION_GEN3 (CURVES_WITH_ENDOMORPHISMS->action_gen3)', file=hfile) print(f'#define ACTION_GEN4 (CURVES_WITH_ENDOMORPHISMS->action_gen4)', file=hfile) print(f'#define NUM_ALTERNATE_STARTING_CURVES {len(data)-1}', file=hfile) print(f'#define ALTERNATE_STARTING_CURVES (CURVES_WITH_ENDOMORPHISMS+1)', file=hfile) objs.header(file=hfile) objs.implementation(file=cfile) print(f'#endif', file=hfile)