Commit b9d01dbd by GUILLEVIC Aurore

### other families with k=8

parent 61c23ae3
 ... ... @@ -19,7 +19,7 @@ from PairingFriendlyCurve import print_parameters, print_parameters_for_RELIC class CocksPinch8(EllipticCurve_finite_field): """ A Cocks-Pinch curve of embedding degree k=8, D=8, rho=2 and optimal ate pairing available. A Cocks-Pinch curve of embedding degree k=8, D=4, rho=2 and optimal ate pairing available. """ def __init__(self, u, hy, ht, exp_tr=None, p=None, r=None, c=None, tr=None, y=None, a=None, beta=None, lamb=None): ... ...
FK8D4.py 0 → 100644
 """ Fotiadis-Konstantinou curve with k=8, rho=2 and D=4 From the papers https://eprint.iacr.org/2018/1017.pdf (for the curves) k = 8; D = 4; rho = 2; #quartic twists, V = [x, -1, 0, 0], x = 0 (mod 2) px = (x^8 + x^6 + 5*x^4 + x^2 + 4*x + 4)/4 rx = x^4 + 1 tx = x^4 + x + 2 yx = (x^3 - x^2)/2 #remove the /2 if you consider D=1 cx = (x^4+x^2)/4 beta = (x^6 - x^5 - 2*x^3 + 3*x^2 - 3*x - 2)/4 lamb = x^2 and https://eprint.iacr.org/2018/969.pdf https://eprint.iacr.org/2019/555.pdf (for pairing computation estimates) """ import sage from exceptions import ValueError from sage.functions.log import log from sage.functions.other import ceil from sage.functions.other import sqrt from sage.arith.misc import XGCD, xgcd from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import FiniteField 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 PairingFriendlyCurve from PairingFriendlyCurve import get_curve_parameter_a_j1728, get_curve_generator_order_r_j1728 from PairingFriendlyCurve import print_parameters, print_parameters_for_RELIC class FK8D4(EllipticCurve_finite_field): """ A Fotiadis-Konstantinou curve of embedding degree k=8, D=4, rho=2 https://eprint.iacr.org/2018/1017 """ def __init__(self, u, a=None): """ u is the seed s.t. p=P(u), r=R(u), t=T(u) :param u : seed :param a : curve parameter in E: y^2 = x^3 + a*x (optional) """ self._k = 8 # embedding degree self._D = 4 # curve discriminant self._b = 0 self._u = Integer(u) # see bottom of file for formulas self.polynomial_r = [1, 0, 0, 0, 1] # u^4 + 1 self.polynomial_r_denom = Integer(1) self.polynomial_tr= [2, 1, 0, 0, 1] self.polynomial_tr_denom = Integer(1) self.polynomial_p = [4, 4, 1, 0, 5, 0, 1, 0, 1] self.polynomial_p_denom = Integer(4) self.polynomial_y = [0, 0, -1, 1] self.polynomial_y_denom = Integer(2) self.polynomial_c = [0, 0, 1, 0, 1] self.polynomial_c_denom = Integer(4) self.polynomial_beta = [-2, -3, 3, -2, 0, -1, 1] self.polynomial_beta_denom = Integer(4) self.polynomial_lamb = [0,0,1] # x^2 mod r(x) = x^4+1 self.polynomial_lamb_denom = Integer(1) self._p = sum([Integer(self.polynomial_p[i])*self._u**i for i in range(len(self.polynomial_p))])//self.polynomial_p_denom self._pbits = self._p.nbits() self._r = sum([Integer(self.polynomial_r[i])*self._u**i for i in range(len(self.polynomial_r))])//self.polynomial_r_denom self._c = sum([Integer(self.polynomial_c[i])*self._u**i for i in range(len(self.polynomial_c))])//self.polynomial_c_denom self._tr= sum([Integer(self.polynomial_tr[i])*self._u**i for i in range(len(self.polynomial_tr))])//self.polynomial_tr_denom if not self._c * self._r == self._p + 1 - self._tr: raise ValueError("Error: r*c != p+1-tr\nr={}\nc={}\np+1-tr={}\n".format(self._r,self._c,self._p+1-self._tr)) self._y = sum([Integer(self.polynomial_y[i])*self._u**i for i in range(len(self.polynomial_y))])//self.polynomial_y_denom # GLV parameter for fast scalar multiplication thanks to automorphism # psi: (x,y) -> (-x,i*y) = [lambda mod r]*(x,y) if (x,y) is of order r # where beta is a root of x^2+1 mod p, beta = sqrt(-1) mod p # and lambda is a root of x^2+1 mod r, lamb = sqrt(-1) mod r # there are two choices: beta, -beta, and the same for lamb: lamb, -lamb # arbitrarily the positive ones are chosen # if u is odd, beta has integer coefficients, # but if u is even, then beta has denomiator 2: use / instead of // if (self._u % 2) == 0: self._beta = sum([Integer(self.polynomial_beta[i])*self._u**i for i in range(len(self.polynomial_beta))])/self.polynomial_beta_denom else: self._beta = sum([Integer(self.polynomial_beta[i])*self._u**i for i in range(len(self.polynomial_beta))])//self.polynomial_beta_denom # lamb is always an integer self._lamb = sum([Integer(self.polynomial_lamb[i])*self._u**i for i in range(len(self.polynomial_lamb))])//self.polynomial_lamb_denom try: self._Fp = FiniteField(self._p) except ValueError as err: print("ValueError creating Fp: {}".format(err)) raise except: print("Error creating Fp") raise if not self._r.is_prime(): raise ValueError("Error r is not prime") # if u is even, beta has denominator 2, reduces mod p: if (self._u %2) == 0: self._beta = Integer(self._Fp(self._beta)) if ((self._beta**2 + 1) % self._p) != 0: raise ValueError("Error beta^2 + 1 != 0 mod p") if ((self._lamb**2 + 1) % self._r) != 0: raise ValueError("Error lamb^2 + 1 != 0 mod r") self._Fpz = PolynomialRing(self._Fp, names=('z',)) (self._z,) = self._Fpz._first_ngens(1) self._bp = self._Fp(0) # second curve parameter is 0 because j=1728 if a != None: try: a = Integer(a) except: raise self._a = a self._ap = self._Fp(a) else: # check that beta = U/V, where U=t/2, V = y self._a, self._ap = get_curve_parameter_a_j1728(self._tr, self._y, self._beta, self._p, self._Fp) # Now self._a is such that E: y^2 = x^3 + a*x has order r try: # this init function of super inherits from class EllipticCurve_generic defined in ell_generic.py # __init__ method inherited from ell_generic EllipticCurve_finite_field.__init__(self, self._Fp, [0,0,0,self._ap,0]) except ValueError as err: print("ValueError at EllipticCurve_finite_field.__init__: {}".format(err)) raise except: print("An error occupred when initialising the elliptic curve") raise self.order_checked = super(FK8D4,self).order() if self.order_checked != (self._p+1-self._tr): print("Error, wrong order") raise ValueError("Wrong curve order: this one is a twist") # computes a generator self._G = get_curve_generator_order_r_j1728(self) self._Gx = self._G[0] self._Gy = self._G[1] # adjust beta and lamb according to the curve # do we have (-x,beta*y) = lamb*(x,y)? if self([-self._Gx, self._Gy*self._beta]) != self._lamb*self._G: print("adjusting beta, lambda") if self([-self._Gx, self._Gy*(-self._beta)]) == self._lamb*self._G: self._beta = self._p-self._beta print("beta -> -beta") elif self([-self._Gx, self._Gy*self._beta]) == (-self._lamb)*self._G: self._lamb = -self._lamb print("lamb -> -lamb") elif self([-self._Gx, self._Gy*(-self._beta)]) == (-self._lamb)*self._G: self._beta = self._p-self._beta self._lamb = -self._lamb print("lamb -> -lamb") print("beta -> -beta") else: raise ValueError("Error while adjusting beta, lamb: compatibility not found") def _repr_(self): return "FK8D4 p"+str(self._pbits)+" (Fotiadis-Konstantinou k=8) curve with seed "+str(self._u)+"\n"+super(FK8D4,self)._repr_() def u(self): return self._u def T(self): return self._u def p(self): return self._p def r(self): return self._r def c(self): return self._c def tr(self): return self._tr def y(self): return self._y def D(self): return self._D def a(self): return self._a # Integer def ap(self): return self._ap # in Fp (finite field element) def b(self): return self._b # 0 def bp(self): return self._bp # 0 def beta(self): return self._beta def lamb(self): return self._lamb def k(self): return self._k def Fp(self): return self._Fp def Fpz(self): return self._Fpz, self._z def G(self): return self._G def print_parameters(self): PairingFriendlyCurve.print_parameters(self) def print_parameters_for_RELIC(self): PairingFriendlyCurve.print_parameters_for_RELIC(self)
TN8.py 0 → 100644
 """ Tanaka-Nakamula curves k=8 D=4 rho=1.5 Published at Pairing'2008 k = 8; D = 4; rho = 1.5; #quartic twists available rx = 2*x^4 + 4*x^3 + 6*x^2 + 4*x + 1 tx = 2*x^3 + 2*x^2 + 4*x + 2 yx = 3*x^3 + 5*x^2 + 7*x + 3 px = 10*x^6 + 32*x^5 + 72*x^4 + 94*x^3 + 85*x^2 + 46*x + 10 cx = 5*x^2 + 6*x + 9 twx= 10*x^6 + 32*x^5 + 72*x^4 + 96*x^3 + 87*x^2 + 50*x + 13 beta = 70*x^5 + 184*x^4 + 396*x^3 + 424*x^2 + 341*x + 117 lamb = 4*x^3 + 6*x^2 + 8*x + 3 """ import sage from exceptions import ValueError from sage.functions.log import log from sage.functions.other import ceil from sage.functions.other import sqrt from sage.arith.misc import XGCD, xgcd from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import FiniteField 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 PairingFriendlyCurve from PairingFriendlyCurve import get_curve_parameter_a_j1728, get_curve_generator_order_r_j1728 from PairingFriendlyCurve import print_parameters, print_parameters_for_RELIC class TN8(EllipticCurve_finite_field): """ A Tanaka-Nakamula curve of embedding degree k=8, D=4 rho=1.5 Pairing 2008 """ def __init__(self, u, a=None): """ u is the seed s.t. p=P(u), r=R(u), t=T(u) :param u : seed :param a : curve parameter in E: y^2 = x^3 + a*x (optional) """ self._k = 8 # embedding degree self._D = 4 # curve discriminant self._b = 0 self._u = Integer(u) # see bottom of file for formulas self.polynomial_r = [1, 4, 6, 4, 2] self.polynomial_tr= [2, 4, 2, 2] self.polynomial_y = [3, 7, 5, 3] self.polynomial_p = [10, 46, 85, 94, 72, 32, 10] self.polynomial_c = [9, 6, 5] self.polynomial_beta = [117, 341, 424, 396, 184, 70] self.polynomial_lamb = [3, 8, 6, 4] self.polynomial_r_denom = Integer(1) self.polynomial_tr_denom = Integer(1) self.polynomial_y_denom = Integer(1) self.polynomial_p_denom = Integer(1) self.polynomial_c_denom = Integer(1) self.polynomial_beta_denom = Integer(1) self.polynomial_lamb_denom = Integer(1) self._p = sum([Integer(self.polynomial_p[i])*self._u**i for i in range(len(self.polynomial_p))]) self._pbits = self._p.nbits() self._r = sum([Integer(self.polynomial_r[i])*self._u**i for i in range(len(self.polynomial_r))]) self._c = sum([Integer(self.polynomial_c[i])*self._u**i for i in range(len(self.polynomial_c))]) self._tr= sum([Integer(self.polynomial_tr[i])*self._u**i for i in range(len(self.polynomial_tr))]) if not self._c * self._r == self._p + 1 - self._tr: raise ValueError("Error: r*c != p+1-tr\nr={}\nc={}\np+1-tr={}\n".format(self._r,self._c,self._p+1-self._tr)) self._y = sum([Integer(self.polynomial_y[i])*self._u**i for i in range(len(self.polynomial_y))]) # GLV parameter for fast scalar multiplication thanks to automorphism # psi: (x,y) -> (-x,i*y) = [lambda mod r]*(x,y) if (x,y) is of order r # where beta is a root of x^2+1 mod p, beta = sqrt(-1) mod p # and lambda is a root of x^2+1 mod r, lamb = sqrt(-1) mod r # there are two choices: beta, -beta, and the same for lamb: lamb, -lamb # arbitrarily the positive ones are chosen self._beta = sum([Integer(self.polynomial_beta[i])*self._u**i for i in range(len(self.polynomial_beta))]) self._lamb = sum([Integer(self.polynomial_lamb[i])*self._u**i for i in range(len(self.polynomial_lamb))]) try: self._Fp = FiniteField(self._p) except ValueError as err: print("ValueError creating Fp: {}".format(err)) raise except: print("Error creating Fp") raise if not self._r.is_prime(): raise ValueError("Error r is not prime") if ((self._beta**2 + 1) % self._p) != 0: raise ValueError("Error beta^2 + 1 != 0 mod p") if ((self._lamb**2 + 1) % self._r) != 0: raise ValueError("Error lamb^2 + 1 != 0 mod r") self._Fpz = PolynomialRing(self._Fp, names=('z',)) (self._z,) = self._Fpz._first_ngens(1) self._bp = self._Fp(0) # second curve parameter is 0 because j=1728 if a != None: try: a = Integer(a) except: raise self._a = a self._ap = self._Fp(a) else: # check that beta = U/V, where U=t/2, V = y self._a, self._ap = get_curve_parameter_a_j1728(self._tr, self._y, self._beta, self._p, self._Fp) # Now self._a is such that E: y^2 = x^3 + a*x has order r try: # this init function of super inherits from class EllipticCurve_generic defined in ell_generic.py # __init__ method inherited from ell_generic EllipticCurve_finite_field.__init__(self, self._Fp, [0,0,0,self._ap,0]) except ValueError as err: print("ValueError at EllipticCurve_finite_field.__init__: {}".format(err)) raise except: print("An error occupred when initialising the elliptic curve") raise self.order_checked = super(TN8,self).order() if self.order_checked != (self._p+1-self._tr): print("Error, wrong order") raise ValueError("Wrong curve order: this one is a twist") # computes a generator self._G = get_curve_generator_order_r_j1728(self) self._Gx = self._G[0] self._Gy = self._G[1] # adjust beta and lamb according to the curve # do we have (-x,beta*y) = lamb*(x,y)? if self([-self._Gx, self._Gy*self._beta]) != self._lamb*self._G: print("adjusting beta, lambda") if self([-self._Gx, self._Gy*(-self._beta)]) == self._lamb*self._G: self._beta = self._p-self._beta print("beta -> -beta") elif self([-self._Gx, self._Gy*self._beta]) == (-self._lamb)*self._G: self._lamb = -self._lamb print("lamb -> -lamb") elif self([-self._Gx, self._Gy*(-self._beta)]) == (-self._lamb)*self._G: self._beta = self._p-self._beta self._lamb = -self._lamb print("lamb -> -lamb") print("beta -> -beta") else: raise ValueError("Error while adjusting beta, lamb: compatibility not found") def _repr_(self): return "TN8 p"+str(self._pbits)+" (Tanaka-Nakamula k=8) curve with seed "+str(self._u)+"\n"+super(TN8,self)._repr_() def u(self): return self._u def T(self): return self._u def p(self): return self._p def r(self): return self._r def c(self): return self._c def tr(self): return self._tr def y(self): return self._y def D(self): return self._D def a(self): return self._a # Integer def ap(self): return self._ap # in Fp (finite field element) def b(self): return self._b # 0 def bp(self): return self._bp # 0 def beta(self): return self._beta def lamb(self): return self._lamb def k(self): return self._k def Fp(self): return self._Fp def Fpz(self): return self._Fpz, self._z def G(self): return self._G def print_parameters(self): PairingFriendlyCurve.print_parameters(self) def print_parameters_for_RELIC(self): PairingFriendlyCurve.print_parameters_for_RELIC(self) """ ZZx. = ZZ[] k=8 ux = 2*x^3 + 4*x^2 + 6*x + 3 Phi8 = cyclotomic_polynomial(k) Phi8(ux).factor() rx = (2*x^4 + 4*x^3 + 6*x^2 + 4*x + 1) tx = (ux^3+1) % rx # yx = (tx-2)/sqrt(-D) sqrt_D = ux^2 % rx #g, u, v = xgcd(sqrt_D, rx) #g == u*sqrt_D + v*rx #inv_sqrt_D = u/ZZ(g) inv_sqrt_D = sqrt_D # 1/sqrt(-1) = -sqrt(-1) assert ((inv_sqrt_D^2 + 1) % rx) == 0 yx = ((tx-2)*inv_sqrt_D/2) % rx px = (tx^2 + 4*yx^2)/4 assert tx^2 - 4*px == -4*yx^2 assert (px+1-tx) % rx == 0 cx = (px+1-tx)//rx assert Phi8(px) % rx == 0 twx = px+1+tx lamb = sqrt_D # sqrt(-1) mod px <-> tx/yx -> invert yx mod px g,u,v = xgcd(yx,px) g == u*yx + v*px inv_yx = u/ZZ(g) beta = tx*inv_yx/2 % px assert ((beta^2 +1) % rx) == 0 assert ((lamb^2 +1) % px) == 0 print("rx = {}".format(rx)) print("tx = {}".format(tx)) print("yx = {}".format(yx)) print("px = {}".format(px)) print("cx = {}".format(cx)) print("twx= {}".format(twx)) print("beta = {}".format(beta)) print("lamb = {}".format(lamb)) print("R = {}".format(rx.list())) print("T = {}".format(tx.list())) print("Y = {}".format(yx.list())) print("P = {}".format(px.list())) print("C = {}".format(cx.list())) print("TW= {}".format(twx.list())) print("BETA = {}".format(beta.list())) print("LAMB = {}".format(lamb.list())) """
 ... ... @@ -224,6 +224,83 @@ class TestPairingFriendlyCurve(): # outside the class def generate_parameters_high(pnbits, poly_p, poly_r, polys_cofact_twist=[], u_mod_m=0, m=1,verbose=False): """ Generate parameters: find u s.t. p=poly_p(u), r=poly_r(u), tw=poly_r_twist(u) are prime, and p is pnbits long.""" lc = poly_p.leading_coefficient() deg_p = poly_p.degree() u_min = floor((2**(pnbits-1)/lc)**(1/deg_p)) u_min = (u_min-(u_min % m) + u_mod_m) while (ceil(poly_p(u_min))).nbits() < pnbits: u_min+=m while (ceil(poly_p(u_min))).nbits() > pnbits: u_min-=m u_max = floor((2**pnbits/lc)**(1/deg_p)) u_max = (u_max-(u_max % m) + u_mod_m) while (ceil(poly_p(u_max))).nbits() > pnbits: u_max-=m while (ceil(poly_p(u_max))).nbits() < pnbits: u_max+=m u = u_max p = ZZ(poly_p(u)) r = ZZ(poly_r(u)) tw= [ZZ(c_i(u)) for c_i in polys_cofact_twist] if pnbits < 1024: prod_primes = prod(prime_range(10**5)) else: prod_primes = prod(prime_range(10**7)) i = 0 # save the gcd of parameters to detect possible systematic cofactor gcd_p = 0 gcd_r = 0 gcd_ci = [0 for j in range(len(tw))] gcd_pi = gcd(prod_primes, p) gcd_ri = gcd(prod_primes, r) cond = gcd_pi > 1 or gcd_ri > 1 j = 0 for ci in tw: gcd_cii = gcd(prod_primes, ci) gcd_ci[j] = gcd_cii cond = cond or gcd_ci[j] > 1 j += 1 cond = cond or not p.is_pseudoprime() or not r.is_pseudoprime() for ci in tw: cond = cond or not ci.is_pseudoprime() while u >= u_min and cond: u -=m p = ZZ(poly_p(u)) r = ZZ(poly_r(u)) tw= [ZZ(c_i(u)) for c_i in polys_cofact_twist] gcd_pi = gcd(prod_primes, p) gcd_ri = gcd(prod_primes, r) gcd_p = gcd(gcd_p, gcd_pi) gcd_r = gcd(gcd_r, gcd_ri) cond = gcd_pi > 1 or gcd_ri > 1 j = 0 for ci in tw: gcd_cii = gcd(prod_primes, ci) gcd_ci[j] = gcd(gcd_ci[j], gcd_cii) cond = cond or gcd_cii > 1 j += 1 cond = cond or not p.is_pseudoprime() or not r.is_pseudoprime() for ci in tw: cond = cond or not ci.is_pseudoprime() i +=1 if verbose and (i % 10**5) == 0: print i print("gcd all p: {} gcd all r: {} gcd all ci: {}".format(gcd_p, gcd_r, gcd_ci)) # reset gcd_p = 0 gcd_r = 0 gcd_ci = [0 for j in range(len(tw))] if u >= u_min: print("u={}, i = {}".format(u,i)) return u, p, r, tw, u_min, u_max, i # else return None from CocksPinch6 import CocksPinch6 from CocksPinch8 import CocksPinch8 from CocksPinch_k import CocksPinch_k ... ...
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!