From 307e5e1eee90390373a274e25ce2fd2e9cb8dafd Mon Sep 17 00:00:00 2001 From: Aurore Guillevic <aurore.guillevic@inria.fr> Date: Thu, 13 Jul 2023 22:10:11 +0200 Subject: [PATCH] another file for Brezing-Weng curves with rx cyclotomic --- sage/tnfs/curve/cyclotomic.py | 161 ++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 sage/tnfs/curve/cyclotomic.py diff --git a/sage/tnfs/curve/cyclotomic.py b/sage/tnfs/curve/cyclotomic.py new file mode 100644 index 0000000..efd6e48 --- /dev/null +++ b/sage/tnfs/curve/cyclotomic.py @@ -0,0 +1,161 @@ +import sage + +from sys import version_info +if version_info[0] < 3: + from exceptions import ValueError +from sage.functions.log import log +from sage.functions.other import ceil, sqrt +from sage.arith.misc import XGCD, xgcd, gcd +from sage.arith.functions import lcm +from sage.misc.functional import cyclotomic_polynomial +from sage.rings.integer import Integer +from sage.rings.integer_ring import Z, ZZ +from sage.rings.rational_field import Q, QQ +from sage.rings.number_field.number_field import CyclotomicField +from sage.rings.number_field.number_field import NumberField +from sage.rings.finite_rings.finite_field_constructor import FiniteField, GF +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.schemes.elliptic_curves.ell_finite_field import EllipticCurve_finite_field +from sage.schemes.elliptic_curves.constructor import EllipticCurve + +import tnfs +import tnfs.curve.pairing_friendly_curve +from tnfs.curve.pairing_friendly_curve import get_curve_parameter_b_j0, get_curve_generator_order_r_j0 +from tnfs.curve.pairing_friendly_curve import get_curve_parameter_a_j1728, get_curve_generator_order_r_j1728 +from tnfs.curve.pairing_friendly_curve import compute_beta_lambda +from tnfs.curve.pairing_friendly_curve import BrezingWeng + +#possible embedding degrees +allowed_k = [20, 22] + +def polynomial_params(k: int, D: int, l: int, exp_tr: int): + """ + Returns the polynomial parameters px, rx, cx, tx, yx, betapx, lambrx, and D + for the Brezing-Weng construction of pairing-friendly curves. + eprint 2003/143 DCC vol 37 (1) pp. 133--141, 2005 10.1007/s10623-004-3808-4 + Choose r(x) = Phi_k(x) or Phi_{k*l}(x) so that -D is a square mod r(x), + define t(x) = x^{e*l}+1 where e is co-prime to k, + get y(x) = (t(x)-2)/sqrt(-D), then + p(x) = (t^2(x) + D*y^2(x))/4 + + this function lists precomputed values for k, l, exp_tr, such that p(x) and r(x) generate primes. + + INPUT + k: embedding degree + D: discriminant (abs) + l: small integer (1, 2, 3) so that -D is a square modulo Phi_{k*l}(x) + multiplier of the degree of the cyclotomic polynomial + e.g. for D=3, l = 3/gcd(3,k) + for D=1, l = 4/gcd(4,l) + exp_tr: choice of exponent of the trace t(x) = (x^l)^exp_tr + 1 mod r(x) + """ + QQx = QQ['x']; (x,) = QQx._first_ngens(1) + Phi_k = QQx(cyclotomic_polynomial(k)) + automorphisms = [] # automorphisms other than identity + m = 1 + u_m = [0] + cofactor_r = [1] + if k==20 and D==1 and l==1 and exp_tr==1: # actually this is FST 64 k=20 + k = 20 + D = 1 + l = 1 + exp_tr = 1 + rho = 3/2 + tx = x + 1 + rx = x**8 - x**6 + x**4 - x**2 + 1 + px = (x**12 - 2*x**11 + x**10 + x**2 + 2*x + 1)/4 + yx = x**6 - x**5 + cx = (x - 1)**2 * (x**2 + 1)/4 + betapx = (x**11 - 3*x**10 + 4*x**9 - 4*x**8 + 4*x**7 - 4*x**6 + 2*x**5 + x + 1)/2 + lambrx = x**5 + m = 2 + u_mod_m = [1] + if k==22 and D==1 and l==2 and exp_tr==1: # this is FST 6.3 + k = 22 + D = 1 + l = 2 + exp_tr = 1 + rho = 13/10 # 1.3 + tx = x**2 + 1 + rx = x**20 - x**18 + x**16 - x**14 + x**12 - x**10 + x**8 - x**6 + x**4 - x**2 + 1 + px = (x**26 - 2*x**24 + x**22 + x**4 + 2*x**2 + 1)/4 + yx = x**13 - x**11 + cx = (x**4 - 1) * (x**2 - 1)/4 + lambrx = x**11 + betapx = (x**25 - 3*x**23 + 4*x**21 - 4*x**19 + 4*x**17 - 4*x**15 + 4*x**13 - 2*x**11 + x**3 + x)/2 # (t-2)/y mod px + m = 2 + u_mod_m = [1] + elif k==22 and D==3 and l==3 and exp_tr==1: # this is FST 6.6 + k = 22 + D = 3 + l = 3 + exp_tr = 1 + rho = 7/5 # 1.4 + tx = x**3 + 1 + rx = x**20 + x**19 - x**17 - x**16 + x**14 + x**13 - x**11 - x**10 - x**9 + x**7 + x**6 - x**4 - x**3 + x + 1 + px = (x**28 - 2*x**25 + x**22 - x**17 + 2*x**14 - x**11 + x**6 + x**3 + 1)/3 + yx = (2*x**14 - 2*x**11 - x**3 + 1)/3 + cx = (x**3 - 1)**2 * (x**2 - x + 1)/3 + lambrx = -x**11 + betapx = (2*x**27 + 4*x**26 - x**25 - 6*x**24 - 12*x**23 + 3*x**22 + 8*x**21 + 16*x**20 - 4*x**19 - 8*x**18 - 16*x**17 + 2*x**16 + 4*x**15 + 17*x**14 + 2*x**13 + 4*x**12 - 10*x**11 - 4*x**10 - 8*x**9 + 2*x**8 + 4*x**7 + 8*x**6 - 9*x**3 + 2*x**2 + 4*x - 1)/9 + m = 3 + u_mod_m = [1] + else: + raise ValueError("no configured set of parameters for Cyclotomic k={} D={} l={} exp_t={}".format(k, D, l, exp_tr)) + + assert (Phi_k(tx-1) % rx) == 0, "Error k={},D={},l={},exp_tr={}, Phi_k(tx-1)%rx != 0, = {}, tx=x^({}*{})+1 mod rx = {}, rx={}".format(k, D, l, exp_tr, Phi_k(tx-1) % rx, l, exp_tr, tx, rx) + px_denom = lcm([pi.denom() for pi in px.list()]) + assert ((px+1-tx) % rx) == 0, "Error (px+1-tx)%rx != 0, px={}*({}), tx={}, rx={}, (px+1-tx)={}".format(px_denom, px_denom*px, tx,rx, (px+1-tx).factor()) + assert cx == (px+1-tx) // rx + assert (Phi_k(px) % rx) == 0, "Error k={}, Phi_k(px)%rx != 0, = {}".format(k, Phi_k(px) % rx) + assert px.is_irreducible(), "Error px is not irreducible, px= {}".format(px.factor()) + assert rx.is_irreducible(), "Error rx is not irreducible, rx= {}".format(rx.factor()) + assert 4*px == (tx**2 + D*yx**2), "Error 4*px != tx^2+D*yx^2, {}*px = {}, tx={}, D={}, yx={}, tx^2+Dyx^2 = {}".format(px_denom, px_denom*px, tx, D, yx, tx**2+D*yx**2) + + return px, rx, tx, cx, yx, betapx, lambrx, D, l, exp_tr, m, u_m + +def coeffs_params(k: int, D: int, l: int, exp_tr: int): + px, rx, tx, cx, yx, betapx, lambrx, D, l, exp_tr, m, u_m = polynomial_params(k, D, l, exp_tr) + Px_denom = Integer(lcm([ci.denom() for ci in px.list()])) + Px = [Integer(ci) for ci in (Px_denom*px).list()] + Rx_denom = Integer(lcm([ci.denom() for ci in rx.list()])) + Rx = [Integer(ci) for ci in (Rx_denom*rx).list()] + Tx_denom = Integer(lcm([ci.denom() for ci in tx.list()])) + Tx = [Integer(ci) for ci in (Tx_denom*tx).list()] + Cx_denom = Integer(lcm([ci.denom() for ci in cx.list()])) + Cx = [Integer(ci) for ci in (Cx_denom*cx).list()] + Yx_denom = Integer(lcm([ci.denom() for ci in yx.list()])) + Yx = [Integer(ci) for ci in (Yx_denom*yx).list()] + if betapx != 0 and lambrx != 0: + BETAPx_denom = Integer(lcm([ci.denom() for ci in betapx.list()])) + BETAPx = [Integer(ci) for ci in (BETAPx_denom*betapx).list()] + LAMBRx_denom = Integer(lcm([ci.denom() for ci in lambrx.list()])) + LAMBRx = [Integer(ci) for ci in (LAMBRx_denom*lambrx).list()] + else: + BETAPx_denom=0; BETAPx=0; LAMBRx_denom=0; LAMBRx=0 + return Px, Px_denom, Rx, Rx_denom, Tx, Tx_denom, Cx, Cx_denom, Yx, Yx_denom, BETAPx, BETAPx_denom, LAMBRx, LAMBRx_denom, D, l, exp_tr + +def poly_cofactor_gt(k: int, D: int, l: int, exp_tr: int): + """ + Computes the co-factors for GT: Phi_k(p(x))/r(x) + Same inputs as for polynomial_params + """ + QQx = QQ['x']; (x,) = QQx._first_ngens(1) + px, rx, tx, cx, yx, betapx, lambrx, D, l, exp_tr, m, u_m = polynomial_params(k, D, l, exp_tr) + ex = cyclotomic_polynomial(k)(px) + assert (ex % rx) == 0 + ex = ex // rx + return ex + +class Cyclotomic(BrezingWeng): + """A cyclotomic pairing-friendly curve of embedding degree k + """ + # re-use the init function of class BrezingWeng + def __init__(self, k, u, D, l, e0, a=None, b=None, cofactor_r=1, verbose_init=False): + px, px_denom, rx, rx_denom, tx, tx_denom, cx, cx_denom, yx, yx_denom, betapx, betapx_denom, lambrx, lambrx_denom, D, l, exp_tr = coeffs_params(k, D, l, e0) + super().__init__(k, D, u, px, px_denom, rx, rx_denom, tx, tx_denom, cx, cx_denom, yx, yx_denom, betapx, betapx_denom, lambrx, lambrx_denom, a, b, cofactor_r, verbose_init) + self._l = l + self._exp_tr = exp_tr + + def _repr_(self): + return "Cyclotomic_k"+str(self._k)+"_D"+str(self._D)+"_l"+str(self._l)+"_e0"+str(self._exp_tr)+" p"+str(self._pbits)+" (pairing-friendly curve k="+str(self._k)+") with seed "+str(self._u)+"\n"+super(BrezingWeng, self)._repr_() -- GitLab