Commit 0c5398bb authored by Emmanuel Thomé's avatar Emmanuel Thomé

moved some more files, used by cost_pairing.sage

parent c000b56c
import sage
from exceptions import ValueError
from sage.functions.log import log
from sage.functions.other import ceil
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_b_j0, get_curve_generator_order_r_j0
class BLS12(EllipticCurve_finite_field):
"""
A Barreto-Lynn-Scott curve of embedding degree 12
"""
def __init__(self, u, b=None):
"""
u is the seed such that p=P_BLS12(u), and b is the curve coefficient, s.t. y^2 = x^3 + b has a subgroup of order r=R_BLS12(u)
(there are two possible choices for b: b, 1/b (a twist) but only one has order r)
"""
self._k = 12 # embedding degree
self._a = 0 # first curve parameter is 0 because j=0
self._D = 3
# polynomials (will be needed later for polynomial selection)
# P_BLS12 = (u-1)^2*(u^4 - u^2 + 1)/3 + u #= (s^6 - 2*s^5 + 2*s^3 + s + 1)/3
# R_BLS12 = u^4 - u^2 + 1
# C_BLS12 = (1/3) * (u - 1)^2 # cofactor such that p+1-tr == c*r
# T_BLS12 = u + 1
# Y_BLS12 = (u-1)*(2*u^2 - 1)/3 # = (2*s^3 - 2*s^2 - s + 1)/3
# Y such that T^2 - 4*P = -3*Y^2
# BETA_BLS12 = u^5 - 3*u^4 + 3*u^3 - u + 1
# LAMB_BLS12 = u^2 -1
# do not divides by 3 so that it has integer coeffs.
# pb type with 1/3 (as an int, it is 0) -> uses Integer(1)/Integer(3)
self.polynomial_p = [1, 1, 0, 2, 0, -2, 1]
self.polynomial_p_denom = 3
self.polynomial_r = [1, 0, -1, 0, 1]
self.polynomial_r_denom = 1
self.polynomial_c = [1, -2, 1]
self.polynomial_c_denom = 3
self.polynomial_tr = [1, 1]
self.polynomial_tr_denom = 1
self.polynomial_y = [1, -1, -2, 2]
self.polynomial_y_denom = 3
self.polynomial_beta = [1, -1, 0, 3, -3, 1]
self.polynomial_beta_denom = 1
self.polynomial_lamb = [-1, 0, 1]
self.polynomial_lamb_denom = 1
self._u = Integer(u)
self._p = (self._u-1)**2*(self._u**4 - self._u**2 + 1)//3 + self._u
self._pbits = self._p.nbits()
self._tr = self._u + 1
self._r = self._u**4 - self._u**2 + 1
self._c = (self._u-1)**2//3 # cofactor
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 = ((self._u - 1) * (2*self._u**2 - 1))//3
# GLV parameter for fast scalar multiplication thanks to automorphism
# psi: (x,y) -> (beta*x,y) = [lambda mod r]*(x,y) if (x,y) is of order r
# where beta is a root of x^2+x+1 mod p, beta = (-1 + sqrt(Fp(-3)))/2
# and lambda is a root of x^2+x+1 mod r, lamb = (-1 + sqrt(Fr(-3)))/2
# there are two choices: beta, -beta-1, and the same for lamb: lamb, -lamb-1
# arbitrarily the positive ones are chosen
self._beta = self._u**5 - 3*self._u**4 + 3*self._u**3 - self._u + 1
self._lamb = self._u**2 - 1
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 + self._beta + 1) % self._p) != 0:
raise ValueError("Error beta^2 + beta + 1 != 0 mod p")
if ((self._lamb**2 + self._lamb + 1) % self._r) != 0:
raise ValueError("Error lamb^2 + lamb + 1 != 0 mod r")
self._Fpz = PolynomialRing(self._Fp, names=('z',))
(self._z,) = self._Fpz._first_ngens(1)
if b != None:
try:
b = Integer(b)
except:
raise
self._b = b
self._bp = self._Fp(b)
else:
# check that beta = 2*U/(-3*V-U) before, where U=t/2, V = y/2 and 2V = 2 mod 3
self._b, self._bp = get_curve_parameter_b_j0(self._tr, self._y, self._beta, self._p, self._Fp)
self._ap = self._Fp(0) # first curve parameter is 0 because j=0
# Now self._b is such that E: y^2 = x^3 + b 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,0,self._bp])
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(BLS12,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_j0(self)
self._Gx = self._G[0]
self._Gy = self._G[1]
# adjust beta and lamb according to the curve
# do we have (beta*x,y) = lamb*(x,y)?
if self([self._Gx*self._beta, self._Gy]) != self._lamb*self._G:
print("adjusting beta, lambda")
if self([self._Gx*(-self._beta-1), self._Gy]) == self._lamb*self._G:
self._beta = -self._beta-1
print("beta -> -beta-1")
elif self([self._Gx*self._beta, self._Gy]) == (-self._lamb-1)*self._G:
self._lamb = -self._lamb-1
print("lamb -> -lamb-1")
elif self([self._Gx*(-self._beta-1), self._Gy]) == (-self._lamb-1)*self._G:
self._beta = -self._beta-1
self._lamb = -self._lamb-1
print("lamb -> -lamb-1")
print("beta -> -beta-1")
else:
raise ValueError("Error while adjusting beta, lamb: compatibility not found")
def _repr_(self):
return "BLS12 p"+str(self._pbits)+" (Barreto-Lynn-Scott k=12) curve with seed "+str(self._u)+"\n"+super(BLS12,self)._repr_()
def u(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 a(self):
return self._a # 0
def ap(self):
return self._ap # 0
def b(self):
return self._b # Integer
def bp(self):
return self._bp # in Fp (finite field element)
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)
# http://doc.sagemath.org/html/en/thematic_tutorials/tutorial-objects-and-classes.html
# http://doc.sagemath.org/html/en/thematic_tutorials/coercion_and_categories.html
# http://doc.sagemath.org/html/en/thematic_tutorials/tutorial-implementing-algebraic-structures.html
# https://docs.python.org/3/library/functions.html#super
# https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
import sage
from exceptions import ValueError
from sage.functions.log import log
from sage.functions.other import ceil
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_generic import EllipticCurve_generic
#from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field
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_b_j0, get_curve_generator_order_r_j0
class BN(EllipticCurve_finite_field):
"""
A Barreto-Naehrig curve
"""
def __init__(self, u, b=None):
"""
u is the seed such that p=P_BN(u), and b is the curve coefficient, s.t. y^2 = x^3 + b has exactly order r=R_BN(u)
(there are two possible choices for b: b, 1/b (a twist) but only one has order r)
"""
self._k = 12 # embedding degree
self._a = 0 # first curve parameter is 0 because j=0
self._D = 3
# polynomials (will be needed later for polynomial selection)
# P_BN = 36*u^4 + 36*u^3 + 24*u^2 + 6*u + 1
# R_BN = 36*u^4 + 36*u^3 + 18*u^2 + 6*u + 1
# C_BN = 1 # cofactor such that p+1-tr == c*r
# T_BN = 6*u^2 + 1
# Y_BN = 6*u^2 + 4*u + 1 # such that T_BN^2 - 4*P_BN = -3*Y_BN^2
# BETA_BN = 18*u^3 + 18*u^2 + 9*u + 1
# LAMB_BN = 36*u^3 + 18*u^2 + 6*u + 1
self.polynomial_p = [1,6,24,36,36]
self.polynomial_r = [1,6,18,36,36]
self.polynomial_c = [1]
self.polynomial_tr= [1,0,6]
self.polynomial_y = [1,4,6]
self.polynomial_beta = [1,9,18,18]
self.polynomial_lamb = [1,6,18,36]
self._u = Integer(u)
self._p = 36*self._u**4 + 36*self._u**3 + 24*self._u**2 + 6*self._u + 1
self._pbits = self._p.nbits()
self._tr = 6*self._u**2 + 1
self._r = 36*self._u**4 + 36*self._u**3 + 18*self._u**2 + 6*self._u + 1
self._c = Integer(1)
self._y = 6*self._u**2 + 4*self._u + 1 # such that T^2 - 4*P = -3*Y^2
# GLV parameter for fast scalar multiplication thanks to automorphism
# psi: (x,y) -> (beta*x,y) = [lambda mod r]*(x,y) if (x,y) is of order r
# where beta is a root of x^2+x+1 mod p, beta = (-1 +/- sqrt(Fp(-3)))/2
# beta = 18*u^3 + 18*u^2 + 9*u + 1 (other one is -beta-1)
# and lambda is a root of x^2+x+1 mod r, lamb = (-1 +/- sqrt(Fr(-3)))/2
# lamb = 36*u^3 + 18*u^2 + 6*u + 1 (other one is -lamb-1)
# there are two choices: beta, -beta-1, and the same for lamb: lamb, -lamb-1
# arbitrarily the positive ones are chosen
self._beta = 18*self._u**3 + 18*self._u**2 + 9*self._u + 1
self._lamb = 36*self._u**3 + 18*self._u**2 + 6*self._u + 1
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 + self._beta + 1) % self._p) != 0:
raise ValueError("Error beta^2 + beta + 1 != 0 mod p")
if ((self._lamb**2 + self._lamb + 1) % self._r) != 0:
raise ValueError("Error lamb^2 + lamb + 1 != 0 mod r")
self._Fpz = PolynomialRing(self._Fp, names=('z',))
(self._z,) = self._Fpz._first_ngens(1)
if b != None:
try:
b = Integer(b)
except:
raise
self._b = b
self._bp = self._Fp(b)
else:
# BN curves:
# Pereira et al solution: b = c^4 + d^6 or b = c^6 + 4*d^4 for c, d in Fp*
# https://eprint.iacr.org/2010/429
self._b, self._bp = get_curve_parameter_b_j0(self._tr, self._y, self._beta, self._p, self._Fp)
self._ap = self._Fp(0) # first curve parameter is 0 because j=0
# Now self._b is such that E: y^2 = x^3 + b 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,0,self._bp])
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(BN,self).order()
if self.order_checked != self._r:
print("Error, wrong order")
raise ValueError("Wrong curve order: this one is a twist")
# computes a generator
self._G = get_curve_generator_order_r_j0(self)
self._Gx = self._G[0]
self._Gy = self._G[1]
# note that there is no cofactor for BN curves because r=p+1-tr
# adjust beta and lamb according to the curve
# do we have (beta*x,y) = lamb*(x,y)?
if self([self._Gx*self._beta, self._Gy]) != self._lamb*self._G:
print("adjusting beta, lambda")
if self([self._Gx*(-self._beta-1), self._Gy]) == self._lamb*self._G:
self._beta = -self._beta-1
print("beta -> -beta-1")
elif self([self._Gx*self._beta, self._Gy]) == (-self._lamb-1)*self._G:
self._lamb = -self._lamb-1
print("lamb -> -lamb-1")
elif self([self._Gx*(-self._beta-1), self._Gy]) == (-self._lamb-1)*self._G:
self._beta = -self._beta-1
self._lamb = -self._lamb-1
print("lamb -> -lamb-1")
print("beta -> -beta-1")
else:
raise ValueError("Error while adjusting beta, lamb: compatibility not found")
def _repr_(self):
return "BN p"+str(self._pbits)+" (Barreto-Naehrig) curve with seed "+str(self._u)+"\n"+super(BN,self)._repr_()
def u(self):
return self._u
def p(self):
return self._p
def r(self):
return self._r
def c(self):
return self._c # cofactor is Integer(1) because r=p+1-tr and r is prime
def tr(self):
return self._tr
def y(self):
return self._y
def a(self):
return self._a # 0
def ap(self):
return self._ap # 0
def b(self):
return self._b # Integer
def bp(self):
return self._bp # in Fp (finite field element)
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)
import sage
from exceptions import ValueError
from sage.functions.log import log
from sage.functions.other import ceil
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
class KSS16(EllipticCurve_finite_field):
"""
A Kachisa-Schaefer-Scott curve of embedding degree 16
"""
def __init__(self, u, a=None):
"""
u is the seed such that p=P_KSS16(u), and a is the curve coefficient, s.t. y^2 = x^3 + a*x has a subgroup of order r=R_KSS16(u)
(there are two possible choices for a: a, 1/a (a twist) but only one has order r)
"""
self._k = 16 # embedding degree
self._b = 0 # second curve parameter is 0 because j=1728
self._D = 4 # 4, not 1, be careful with that
# polynomials (will be needed later for polynomial selection)
# P_KSS16 = (s^10 + 2*s^9 + 5*s^8 + 48*s^6 + 152*s^5 + 240*s^4 + 625*s^2 + 2398*s + 3125)/980
# R_KSS16 = (s^8 + 48*s^4 + 625)/61250 # 625 = 5^4, 61250 = 2*5^4*7^2
# T_KSS16 = (2*s^5 + 41*s + 35)/35
# C_KSS16 = (125/2) * (s^2 + 2*s + 5) # C such that P+1-T = C*R
# Y_KSS16 = (1/70) * (s^5 + 5*s^4 + 38*s + 120) # Y such that T^2 - 4*P = -3*Y^2
# assert (P_KSS16+1-T_KSS16) == C_KSS16*R_KSS16
# assert (T_KSS16^2 + D_KSS16*Y_KSS16^2)/4 == P_KSS16
# sqrt(-1) mod P
# BETA_KSS16 = (s^9-11*s^8-16*s^7-120*s^6-32*s^5-498*s^4-748*s^3-2740*s^2-3115*s-5651)/4018
# LAMB_KSS16 = (1/7)*(s^4 + 24) # sqrt(-1) mod R
self.polynomial_p = [3125, 2398, 625, 0, 240, 152, 48, 0, 5, 2, 1]
self.polynomial_p_denom = 980
self.polynomial_r = [625, 0, 0, 0, 48, 0, 0, 0, 1]
self.polynomial_r_denom = 61250
# when u = 25, 45 mod 70, then P(u), T(u), (P+1-T)(u) are all integers, and 61250 | R(u)
self.polynomial_c = [625, 250, 125]
self.polynomial_c_denom = 2
self.polynomial_tr= [35, 41, 0, 0, 0, 2]
self.polynomial_tr_denom= 35 # we need u = 25,45 mod 70 for T to be integer
self.polynomial_y = [120, 38, 0, 0, 5, 1]
self.polynomial_y_denom = 70
self.polynomial_beta = [-5651, -3115, -2740, -748, -498, -32, -120, -16, -11, 1]
self.polynomial_beta_denom = 4018 # 2 * 7^2 * 41
self.polynomial_lamb = [24, 0, 0, 0, 1]
self.polynomial_lamb_denom = 7
self._u = Integer(u)
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
# unfortunately beta has always denominator 41, computes modulo p: / instead of //
self._beta = sum([Integer(self.polynomial_beta[i])*self._u**i for i in range(len(self.polynomial_beta))])/Integer(self.polynomial_beta_denom)
# LAMB is an integer when u=25,45 mod 70, which should be the case for P, T, R to be integers.
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")
# beta has denominator 41, reduces mod p:
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(KSS16,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 "KSS16 p"+str(self._pbits)+" (Kachisa-Schaefer-Scott k=16) curve with seed "+str(self._u)+"\n"+super(KSS16,self)._repr_()
def u(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 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)
# MNT curves with k=6
# This time, j != 0.
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_generator_order_r
class MNT6(EllipticCurve_finite_field):
"""
A Miyaji-Nakabayashi-Takano curve of embedding degree 6
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.20.8113&rep=rep1&type=pdf
"""
def __init__(self, u, a, b, D=None, c=None):
"""
u is the seed such that p=P_MNT6(u), and a,b are the curve coefficients,
s.t. y^2 = x^3 + a*x + b has exactly order r=R_MNT6(u)
(there are two possible choices for b: b, 1/b (a twist) but only one has order r)
"""
self._k = 6 # embedding degree
self._a = Integer(a)
self._b = Integer(b)
if D != None:
self._D = Integer(D)
# polynomials (will be needed later for polynomial selection)
#P_MNT6 = 4*x^2+1
#R_MNT6 = 4*x^2 - 2*x + 1
#C_MNT6 = 1
#T_MNT6 = 2*x + 1
#DY2_MNT6 = 12*x^2 - 4*x + 3
# no beta, lambda
self.polynomial_p = [1, 0, 4]
self.polynomial_p_denom = 1
self.polynomial_r = [1, -2, 4]
self.polynomial_r_denom = 1
self.polynomial_c = [1]
self.polynomial_c_denom = 1
self.polynomial_tr = [1, 2]
self.polynomial_tr_denom = 1
self._u = Integer(u)
self._p = Integer(4)*(self._u)**2 + Integer(1)
self._pbits = self._p.nbits()
self._tr = Integer(2)*self._u + 1
self._r = Integer(4)*self._u**2 - Integer(2)*self._u + 1
if c != None and c != 1 and (self._r % Integer(c)) == 0:
self._c = Integer(c)
self._r = self._r // self._c
else:
self._c = Integer(1)
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))
#print("computing y")
self._y = Integer(((4*self._p - self._tr**2)//self._D).sqrt())
#print("y done")
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")
self._Fpz = PolynomialRing(self._Fp, names=('z',))
(self._z,) = self._Fpz._first_ngens(1)
if a != None:
try:
a = Integer(a)
except:
raise
self._a = a
self._ap = self._Fp(a)
if b != None:
try:
b = Integer(b)
except:
raise
self._b = b
self._bp = self._Fp(b)
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,self._bp])
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
#print("check order")
#self.order_checked = super(MNT6,self).order()
#if self.order_checked != (self._p+1-self._tr):
# raise ValueError("Wrong curve order: this one is a twist")
print("check order (randomized)")
self.curve_order = self._p + Integer(1) - self._tr
self.twist_order = self._p + Integer(1) + self._tr
for i in range(10):
P = self.random_element()
if self.curve_order*P != self(0):
if self.twist_order*P == self(0):
raise ValueError("Wrong curve order: this one is a twist: (p+1+tr)*P = 0\ntr={}\nr={}\np+1+tr={}\n".format(self._tr,self.curve_order,self.twist_order))
else:
self.order_checked = super(MNT6,self).order()
raise ValueError("Wrong curve order:\np+1-tr = {}\np+1+tr = {}\nchecked order = {}\np = {}".format(self.curve_order,self.twist_order,self.order_checked,self._p))
print("ok")
# computes a generator
self._G = get_curve_generator_order_r(self)
self._Gx = self._G[0]
self._Gy = self._G[1]
def _repr_(self):
return "MNT6 p"+str(self._pbits)+" (Miyaji-Nakabayashi-Takano curve k=6) curve with seed "+str(self._u)+"\n"+super(MNT6,self)._repr_()
def u(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 a(self):
return self._a # 0
def ap(self):
return self._ap # 0
def b(self):
return self._b # Integer
def bp(self):
return self._bp # in Fp (finite field element)
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