/* this+=this */ public int dbl() { if (INF) { return(-1); } if (y.iszilch()) { inf(); return(-1); } FP2 w1 = new FP2(x); FP2 w2 = new FP2(0); FP2 w3 = new FP2(x); FP2 w8 = new FP2(x); w1.sqr(); w8.copy(w1); w8.imul(3); w2.copy(y); w2.sqr(); w3.copy(x); w3.mul(w2); w3.imul(4); w1.copy(w3); w1.neg(); // w1.norm(); x.copy(w8); x.sqr(); x.add(w1); x.add(w1); x.norm(); z.mul(y); z.add(z); w2.add(w2); w2.sqr(); w2.add(w2); w3.sub(x); y.copy(w8); y.mul(w3); // w2.norm(); y.sub(w2); y.norm(); z.norm(); return(1); }
/* Calculate RHS of twisted curve equation x^3+B/i */ public static FP2 RHS(FP2 x) { x.norm(); FP2 r = new FP2(x); r.sqr(); FP2 b = new FP2(new BIG(ROM.CURVE_B)); b.div_ip(); r.mul(x); r.add(b); r.reduce(); return(r); }
/* this=this^p using Frobenius */ public void frob(FP2 f) { FP2 f2 = new FP2(f); FP2 f3 = new FP2(f); f2.sqr(); f3.mul(f2); a.frob(f3); b.frob(f3); c.frob(f3); b.pmul(f); c.pmul(f2); }
/* this=1/this */ public void inverse() { norm(); FP2 t1 = new FP2(a); FP2 t2 = new FP2(b); t1.sqr(); t2.sqr(); t2.mul_ip(); t1.sub(t2); t1.inverse(); a.mul(t1); t1.neg(); b.mul(t1); }
/* normalises m-array of ECP2 points. Requires work vector of m FP2s */ public static void multiaffine(int m, ECP2[] P) { int i; FP2 t1 = new FP2(0); FP2 t2 = new FP2(0); FP2[] work = new FP2[m]; work[0] = new FP2(1); work[1] = new FP2(P[0].z); for (i = 2; i < m; i++) { work[i] = new FP2(work[i - 1]); work[i].mul(P[i - 1].z); } t1.copy(work[m - 1]); t1.mul(P[m - 1].z); t1.inverse(); t2.copy(P[m - 1].z); work[m - 1].mul(t1); for (i = m - 2;; i--) { if (i == 0) { work[0].copy(t1); work[0].mul(t2); break; } work[i].mul(t2); work[i].mul(t1); t2.mul(P[i].z); } /* now work[] contains inverses of all Z coordinates */ for (i = 0; i < m; i++) { P[i].z.one(); t1.copy(work[i]); t1.sqr(); P[i].x.mul(t1); t1.mul(work[i]); P[i].y.mul(t1); } }
/* set this*=q, where q is Modulus, using Frobenius */ public void frob(FP2 X) { if (INF) { return; } FP2 X2 = new FP2(X); X2.sqr(); x.conj(); y.conj(); z.conj(); z.reduce(); x.mul(X2); y.mul(X2); y.mul(X); }
/* construct this from (x,y) - but set to O if not on curve */ public ECP2(FP2 ix, FP2 iy) { x = new FP2(ix); y = new FP2(iy); z = new FP2(1); FP2 rhs = RHS(x); FP2 y2 = new FP2(y); y2.sqr(); if (y2.Equals(rhs)) { INF = false; } else { x.zero(); INF = true; } }
/* Test if P == Q */ public bool Equals(ECP2 Q) { if (is_infinity() && Q.is_infinity()) { return(true); } if (is_infinity() || Q.is_infinity()) { return(false); } FP2 zs2 = new FP2(z); zs2.sqr(); FP2 zo2 = new FP2(Q.z); zo2.sqr(); FP2 zs3 = new FP2(zs2); zs3.mul(z); FP2 zo3 = new FP2(zo2); zo3.mul(Q.z); zs2.mul(Q.x); zo2.mul(x); if (!zs2.Equals(zo2)) { return(false); } zs3.mul(Q.y); zo3.mul(y); if (!zs3.Equals(zo3)) { return(false); } return(true); }
/* set to Affine - (x,y,z) to (x,y) */ public void affine() { if (is_infinity()) { return; } FP2 one = new FP2(1); if (z.Equals(one)) { return; } z.inverse(); FP2 z2 = new FP2(z); z2.sqr(); x.mul(z2); x.reduce(); y.mul(z2); y.mul(z); y.reduce(); z.copy(one); }
/* this+=Q - return 0 for add, 1 for double, -1 for O */ public int add(ECP2 Q) { if (INF) { copy(Q); return(-1); } if (Q.INF) { return(-1); } bool aff = false; if (Q.z.isunity()) { aff = true; } FP2 A, C; FP2 B = new FP2(z); FP2 D = new FP2(z); if (!aff) { A = new FP2(Q.z); C = new FP2(Q.z); A.sqr(); B.sqr(); C.mul(A); D.mul(B); A.mul(x); C.mul(y); } else { A = new FP2(x); C = new FP2(y); B.sqr(); D.mul(B); } B.mul(Q.x); B.sub(A); D.mul(Q.y); D.sub(C); if (B.iszilch()) { if (D.iszilch()) { dbl(); return(1); } else { INF = true; return(-1); } } if (!aff) { z.mul(Q.z); } z.mul(B); FP2 e = new FP2(B); e.sqr(); B.mul(e); A.mul(e); e.copy(A); e.add(A); e.add(B); x.copy(D); x.sqr(); x.sub(e); A.sub(x); y.copy(A); y.mul(D); C.mul(B); y.sub(C); x.norm(); y.norm(); z.norm(); return(0); }
/* Line function */ public static FP12 line(ECP2 A, ECP2 B, FP Qx, FP Qy) { ECP2 P = new ECP2(); FP4 a, b, c; P.copy(A); FP2 ZZ = new FP2(P.getz()); ZZ.sqr(); int D; if (A == B) { D = A.dbl(); // Check this return value in amcl_ec2.c } else { D = A.add(B); } if (D < 0) { return(new FP12(1)); } FP2 Z3 = new FP2(A.getz()); c = new FP4(0); if (D == 0) { // Addition FP2 X = new FP2(B.getx()); FP2 Y = new FP2(B.gety()); FP2 T = new FP2(P.getz()); T.mul(Y); ZZ.mul(T); FP2 NY = new FP2(P.gety()); NY.neg(); ZZ.add(NY); Z3.pmul(Qy); T.mul(P.getx()); X.mul(NY); T.add(X); a = new FP4(Z3, T); ZZ.neg(); ZZ.pmul(Qx); b = new FP4(ZZ); } else { // Doubling FP2 X = new FP2(P.getx()); FP2 Y = new FP2(P.gety()); FP2 T = new FP2(P.getx()); T.sqr(); T.imul(3); Y.sqr(); Y.add(Y); Z3.mul(ZZ); Z3.pmul(Qy); X.mul(T); X.sub(Y); a = new FP4(Z3, X); T.neg(); ZZ.mul(T); ZZ.pmul(Qx); b = new FP4(ZZ); } return(new FP12(a, b, c)); }