blob: cc36a0fafa843eee7f8ea933b994d89cdc83b83d [file] [log] [blame]
#
# Elliptic Curve Points over Fp^2
# Projective Weierstrass coordinates
# M.Scott August 2013
#
import copy
from XXX import big
from XXX import curve
from XXX.fp2 import *
from XXX.ecp import *
class ECp2:
def __init__(self):
self.x = Fp2()
self.y = Fp2(Fp(1))
self.z = Fp2()
def copy(self):
return copy.deepcopy(self)
# convert to affine coordinates
def affine(self):
if self.isinf() or self.z.isone():
return self
iz = self.z.inverse()
self.x *= iz
self.y *= iz
self.z = Fp2(Fp(1))
return self
# check if point-at-infinity
def isinf(self):
if self.x.iszero() and self.z.iszero():
return True
return False
# set point to (x,y)
def set(self, x, y):
mx = x.copy()
my = y.copy()
if my * my != RHS(mx):
return False
self.x = mx
self.y = my
self.z = Fp2(Fp(1))
return True
def get(self): # return tuple Fp2 x and Fp2 y
W = self.copy()
if (W.isinf()):
return (Fp2(), Fp2())
W.affine()
return(W.x, W.y)
def getZ(self):
return self.z.copy()
def getxyz(self):
return (self.x.copy(), self.y.copy(), self.z.copy())
def getxy(self):
return (self.x.copy(), self.y.copy())
def __eq__(self, other):
zs = self.z
zo = other.z
if self.x * zo != other.x * zs:
return False
if self.y * zo != other.y * zs:
return False
return True
def __ne__(self, other):
return not(self == other)
def __neg__(self):
s = self.copy()
s.y = -s.y
return s
# use exeption free formulae
def dbl(self):
iy = self.y.copy()
if curve.SexticTwist == D_TYPE:
iy = iy.mulQNR()
t0 = self.y.copy()
t0.sqr()
if curve.SexticTwist == D_TYPE:
t0 = t0.mulQNR()
t1 = iy.copy()
t1 = t1 * self.z
t2 = self.z.copy()
t2.sqr()
self.z = t0 + t0
self.z += self.z
self.z += self.z
t2 = t2.muli(3 * curve.B)
if curve.SexticTwist == M_TYPE:
t2 = t2.mulQNR()
x3 = t2 * self.z
y3 = t0 + t2
self.z *= t1
t1 = t2 + t2
t2 += t1
t0 -= t2
y3 *= t0
y3 += x3
t1 = self.x * iy
self.x = t0
self.x *= t1
self.x += self.x
self.y = y3
return self
def add(self, other):
t0 = self.x.copy()
t0 *= other.x
t1 = self.y.copy()
t1 *= other.y
t2 = self.z.copy()
t2 = t2 * other.z
t3 = self.x.copy()
t3 += self.y
t4 = other.x + other.y
t3 *= t4
t4 = t0 + t1
t3 -= t4
if curve.SexticTwist == D_TYPE:
t3 = t3.mulQNR()
t4 = self.y + self.z
x3 = other.y + other.z
t4 *= x3
x3 = t1 + t2
t4 -= x3
if curve.SexticTwist == D_TYPE:
t4 = t4.mulQNR()
x3 = self.x + self.z
y3 = other.x + other.z
x3 *= y3
y3 = t0 + t2
y3 = x3 - y3
if curve.SexticTwist == D_TYPE:
t0 = t0.mulQNR()
t1 = t1.mulQNR()
x3 = t0 + t0
t0 += x3
t2 = t2.muli(3 * curve.B)
if curve.SexticTwist == M_TYPE:
t2 = t2.mulQNR()
z3 = t1 + t2
t1 -= t2
y3 = y3.muli(3 * curve.B)
if curve.SexticTwist == M_TYPE:
y3 = y3.mulQNR()
x3 = y3 * t4
t2 = t3 * t1
x3 = t2 - x3
y3 *= t0
t1 *= z3
y3 += t1
t0 *= t3
z3 *= t4
z3 += t0
self.x = x3
self.y = y3
self.z = z3
return self
def __rmul__(self, other): # use NAF
b = other
b3 = 3 * b
k = b3.bit_length()
#k = curve.r.bit_length()+2
# self.affine()
mself = -self
R = ECp2()
for i in range(k - 1, 0, -1):
R.dbl()
if big.bit(b3, i) == 1 and big.bit(b, i) == 0:
R.add(self)
if big.bit(b3, i) == 0 and big.bit(b, i) == 1:
R.add(mself)
return R
# calculate p.P(x,y) using frobenius
def frobenius(self):
X = Fp2(Fp(curve.Fra), Fp(curve.Frb))
if curve.SexticTwist == M_TYPE:
X = X.inverse()
X2 = X.copy()
X2.sqr()
# self.affine()
self.x = self.x.conj()
self.y = self.y.conj()
self.z = self.z.conj()
self.x *= X2
self.y *= X2
self.y *= X
return self
def __str__(self): # pretty print
W = self.copy()
if W.isinf():
return "infinity"
W.affine()
return "[%s,%s]" % (W.x, W.y)
# convert from and to an array of bytes
def fromBytes(self, W):
FS = curve.EFS
xa = big.from_bytes(W[0:FS])
xb = big.from_bytes(W[FS:2 * FS])
ya = big.from_bytes(W[2 * FS:3 * FS])
yb = big.from_bytes(W[3 * FS:4 * FS])
x = Fp2(Fp(xa), Fp(xb))
y = Fp2(Fp(ya), Fp(yb))
return self.set(x, y)
def toBytes(self):
FS = curve.EFS
PK = bytearray(4 * FS)
x, y = self.get()
xa, xb = x.get()
ya, yb = y.get()
W = big.to_bytes(xa)
for i in range(0, FS):
PK[i] = W[i]
W = big.to_bytes(xb)
for i in range(0, FS):
PK[FS + i] = W[i]
W = big.to_bytes(ya)
for i in range(0, FS):
PK[2 * FS + i] = W[i]
W = big.to_bytes(yb)
for i in range(0, FS):
PK[3 * FS + i] = W[i]
return PK
# calculate Right Hand Side of elliptic curve equation y^2=RHS(x)
def RHS(x):
if curve.SexticTwist == D_TYPE:
return x * x * x + Fp2(ECp.B).divQNR() # on the sextic twist
else:
return x * x * x + Fp2(ECp.B).mulQNR() # on the sextic twist
# get group generator point
def generator():
P = ECp2()
P.set(Fp2(Fp(curve.Pxa), Fp(curve.Pxb)), Fp2(Fp(curve.Pya), Fp(curve.Pyb)))
return P
# P=generator()
# print(curve.r*P)
# P.dbl()
# XX,YY,ZZ=P.getxyz()
#print("P= ",XX,YY,ZZ)
# XX,YY,ZZ=P.getxyz()
#print("P= ",XX,YY,ZZ)
# P.dbl()
# XX,YY,ZZ=P.getxyz()
#print("P= ",XX,YY,ZZ)
# print(P.frobenius())
#X=Fp2(Fp(curve.Fra), Fp(curve.Frb))
# X2=X*X
# X3=X*X*X
# print(X3)