private static Precomputed FlippedMillerLoopMixedAddition(BN128G2 base_val, BN128G2 addend) { Fp2 x1 = addend.x, y1 = addend.y, z1 = addend.z; Fp2 x2 = base_val.x, y2 = base_val.y; Fp2 d = x1.Sub(x2.Mul(z1)); // d = x1 - x2 * z1 Fp2 e = y1.Sub(y2.Mul(z1)); // e = y1 - y2 * z1 Fp2 f = d.Squared(); // f = d^2 Fp2 g = e.Squared(); // g = e^2 Fp2 h = d.Mul(f); // h = d * f Fp2 i = x1.Mul(f); // i = x1 * f Fp2 j = h.Add(z1.Mul(g)).Sub(i.Dbl()); // j = h + z1 * g - 2 * i Fp2 x3 = d.Mul(j); // x3 = d * j Fp2 y3 = e.Mul(i.Sub(j)).Sub(h.Mul(y1)); // y3 = e * (i - j) - h * y1) Fp2 z3 = z1.Mul(h); // z3 = Z1*H Fp2 ell0 = Parameters.TWIST.Mul(e.Mul(x2).Sub(d.Mul(y2))); // ell_0 = TWIST * (e * x2 - d * y2) Fp2 ellVV = e.Negate(); // ell_VV = -e Fp2 ellVW = d; // ell_VW = d return(Precomputed.Of( new BN128G2(x3, y3, z3), new EllCoeffs(ell0, ellVW, ellVV) )); }
private static Precomputed FlippedMillerLoopDoubling(BN128G2 g2) { Fp2 x = g2.x, y = g2.y, z = g2.z; Fp2 a = Fp._2_INV.Mul(x.Mul(y)); // a = x * y / 2 Fp2 b = y.Squared(); // b = y^2 Fp2 c = z.Squared(); // c = z^2 Fp2 d = c.Add(c).Add(c); // d = 3 * c Fp2 e = Parameters.B_Fp2.Mul(d); // e = twist_b * d Fp2 f = e.Add(e).Add(e); // f = 3 * e Fp2 g = Fp._2_INV.Mul(b.Add(f)); // g = (b + f) / 2 Fp2 h = y.Add(z).Squared().Sub(b.Add(c)); // h = (y + z)^2 - (b + c) Fp2 i = e.Sub(b); // i = e - b Fp2 j = x.Squared(); // j = x^2 Fp2 e2 = e.Squared(); // e2 = e^2 Fp2 rx = a.Mul(b.Sub(f)); // rx = a * (b - f) Fp2 ry = g.Squared().Sub(e2.Add(e2).Add(e2)); // ry = g^2 - 3 * e^2 Fp2 rz = b.Mul(h); // rz = b * h Fp2 ell0 = Parameters.TWIST.Mul(i); // ell_0 = twist * i Fp2 ellVW = h.Negate(); // ell_VW = -h Fp2 ellVV = j.Add(j).Add(j); // ell_VV = 3 * j return(Precomputed.Of( new BN128G2(rx, ry, rz), new EllCoeffs(ell0, ellVW, ellVV) )); }
public Fp6 Add(Fp6 o) { Fp2 ra = a.Add(o.a); Fp2 rb = b.Add(o.b); Fp2 rc = c.Add(o.c); return(new Fp6(ra, rb, rc)); }
public BN128G2 MulByP() { Fp2 rx = Parameters.TWIST_MUL_BY_P_X.Mul(x.FrobeniusMap(1)); Fp2 ry = Parameters.TWIST_MUL_BY_P_Y.Mul(y.FrobeniusMap(1)); Fp2 rz = z.FrobeniusMap(1); return(new BN128G2(rx, ry, rz)); }
public Fp6 Sub(Fp6 o) { Fp2 ra = a.Sub(o.a); Fp2 rb = b.Sub(o.b); Fp2 rc = c.Sub(o.c); return(new Fp6(ra, rb, rc)); }
public Fp6 MulByNonResidue() { Fp2 ra = NON_RESIDUE.Mul(c); Fp2 rb = a; Fp2 rc = b; return(new Fp6(ra, rb, rc)); }
public Fp6 Mul(Fp2 o) { Fp2 ra = a.Mul(o); Fp2 rb = b.Mul(o); Fp2 rc = c.Mul(o); return(new Fp6(ra, rb, rc)); }
public Fp6 FrobeniusMap(int power) { Fp2 ra = a.FrobeniusMap(power); Fp2 rb = FROBENIUS_COEFFS_B[power % 6].Mul(b.FrobeniusMap(power)); Fp2 rc = FROBENIUS_COEFFS_C[power % 6].Mul(c.FrobeniusMap(power)); return(new Fp6(ra, rb, rc)); }
public Fp6 Mul(Fp6 o) { Fp2 a1 = a, b1 = b, c1 = c; Fp2 a2 = o.a, b2 = o.b, c2 = o.c; Fp2 a1a2 = a1.Mul(a2); Fp2 b1b2 = b1.Mul(b2); Fp2 c1c2 = c1.Mul(c2); Fp2 ra = a1a2.Add(b1.Add(c1).Mul(b2.Add(c2)).Sub(b1b2).Sub(c1c2).MulByNonResidue()); Fp2 rb = a1.Add(b1).Mul(a2.Add(b2)).Sub(a1a2).Sub(b1b2).Add(c1c2.MulByNonResidue()); Fp2 rc = a1.Add(c1).Mul(a2.Add(c2)).Sub(a1a2).Add(b1b2).Sub(c1c2); return(new Fp6(ra, rb, rc)); }
public Fp6 Squared() { Fp2 s0 = a.Squared(); Fp2 ab = a.Mul(b); Fp2 s1 = ab.Dbl(); Fp2 s2 = a.Sub(b).Add(c).Squared(); Fp2 bc = b.Mul(c); Fp2 s3 = bc.Dbl(); Fp2 s4 = c.Squared(); Fp2 ra = s0.Add(s3.MulByNonResidue()); Fp2 rb = s1.Add(s4.MulByNonResidue()); Fp2 rc = s1.Add(s2).Add(s3).Sub(s0).Sub(s4); return(new Fp6(ra, rb, rc)); }
public Fp6 Inverse() { /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 17 */ Fp2 t0 = a.Squared(); Fp2 t1 = b.Squared(); Fp2 t2 = c.Squared(); Fp2 t3 = a.Mul(b); Fp2 t4 = a.Mul(c); Fp2 t5 = b.Mul(c); Fp2 c0 = t0.Sub(t5.MulByNonResidue()); Fp2 c1 = t2.MulByNonResidue().Sub(t3); Fp2 c2 = t1.Sub(t4); // typo in paper referenced above. should be "-" as per Scott, but is "*" Fp2 t6 = a.Mul(c0).Add((c.Mul(c1).Add(b.Mul(c2))).MulByNonResidue()).Inverse(); Fp2 ra = t6.Mul(c0); Fp2 rb = t6.Mul(c1); Fp2 rc = t6.Mul(c2); return(new Fp6(ra, rb, rc)); }
public BN128G2(Fp2 x, Fp2 y, Fp2 z) : base(x, y, z) { }
public Fp6(Fp2 a, Fp2 b, Fp2 c) { this.a = a; this.b = b; this.c = c; }
public Fp12 CyclotomicSquared() { Fp2 z0 = a.a; Fp2 z4 = a.b; Fp2 z3 = a.c; Fp2 z2 = b.a; Fp2 z1 = b.b; Fp2 z5 = b.c; Fp2 t0, t1, t2, t3, t4, t5, tmp; // t0 + t1*y = (z0 + z1*y)^2 = a^2 tmp = z0.Mul(z1); t0 = z0.Add(z1).Mul(z0.Add(Fp6.NON_RESIDUE.Mul(z1))).Sub(tmp).Sub(Fp6.NON_RESIDUE.Mul(tmp)); t1 = tmp.Add(tmp); // t2 + t3*y = (z2 + z3*y)^2 = b^2 tmp = z2.Mul(z3); t2 = z2.Add(z3).Mul(z2.Add(Fp6.NON_RESIDUE.Mul(z3))).Sub(tmp).Sub(Fp6.NON_RESIDUE.Mul(tmp)); t3 = tmp.Add(tmp); // t4 + t5*y = (z4 + z5*y)^2 = c^2 tmp = z4.Mul(z5); t4 = z4.Add(z5).Mul(z4.Add(Fp6.NON_RESIDUE.Mul(z5))).Sub(tmp).Sub(Fp6.NON_RESIDUE.Mul(tmp)); t5 = tmp.Add(tmp); // for A // z0 = 3 * t0 - 2 * z0 z0 = t0.Sub(z0); z0 = z0.Add(z0); z0 = z0.Add(t0); // z1 = 3 * t1 + 2 * z1 z1 = t1.Add(z1); z1 = z1.Add(z1); z1 = z1.Add(t1); // for B // z2 = 3 * (xi * t5) + 2 * z2 tmp = Fp6.NON_RESIDUE.Mul(t5); z2 = tmp.Add(z2); z2 = z2.Add(z2); z2 = z2.Add(tmp); // z3 = 3 * t4 - 2 * z3 z3 = t4.Sub(z3); z3 = z3.Add(z3); z3 = z3.Add(t4); // for C // z4 = 3 * t2 - 2 * z4 z4 = t2.Sub(z4); z4 = z4.Add(z4); z4 = z4.Add(t2); // z5 = 3 * t3 + 2 * z5 z5 = t3.Add(z5); z5 = z5.Add(z5); z5 = z5.Add(t3); return(new Fp12(new Fp6(z0, z4, z3), new Fp6(z2, z1, z5))); }
public EllCoeffs(Fp2 ell0, Fp2 ellVW, Fp2 ellVV) { this.ell0 = ell0; this.ellVW = ellVW; this.ellVV = ellVV; }
public Fp2 Mul(Fp2 o) { return(new Fp2(o.a.Mul(this), o.b.Mul(this))); }
public Fp12 MulBy024(Fp2 ell0, Fp2 ellVW, Fp2 ellVV) { Fp2 z0 = a.a; Fp2 z1 = a.b; Fp2 z2 = a.c; Fp2 z3 = b.a; Fp2 z4 = b.b; Fp2 z5 = b.c; Fp2 x0 = ell0; Fp2 x2 = ellVV; Fp2 x4 = ellVW; Fp2 t0, t1, t2, s0, t3, t4, d0, d2, d4, s1; d0 = z0.Mul(x0); d2 = z2.Mul(x2); d4 = z4.Mul(x4); t2 = z0.Add(z4); t1 = z0.Add(z2); s0 = z1.Add(z3).Add(z5); // For z.a_.a_ = z0. s1 = z1.Mul(x2); t3 = s1.Add(d4); t4 = Fp6.NON_RESIDUE.Mul(t3).Add(d0); z0 = t4; // For z.a_.b_ = z1 t3 = z5.Mul(x4); s1 = s1.Add(t3); t3 = t3.Add(d2); t4 = Fp6.NON_RESIDUE.Mul(t3); t3 = z1.Mul(x0); s1 = s1.Add(t3); t4 = t4.Add(t3); z1 = t4; // For z.a_.c_ = z2 t0 = x0.Add(x2); t3 = t1.Mul(t0).Sub(d0).Sub(d2); t4 = z3.Mul(x4); s1 = s1.Add(t4); t3 = t3.Add(t4); // For z.b_.a_ = z3 (z3 needs z2) t0 = z2.Add(z4); z2 = t3; t1 = x2.Add(x4); t3 = t0.Mul(t1).Sub(d2).Sub(d4); t4 = Fp6.NON_RESIDUE.Mul(t3); t3 = z3.Mul(x0); s1 = s1.Add(t3); t4 = t4.Add(t3); z3 = t4; // For z.b_.b_ = z4 t3 = z5.Mul(x2); s1 = s1.Add(t3); t4 = Fp6.NON_RESIDUE.Mul(t3); t0 = x0.Add(x4); t3 = t2.Mul(t0).Sub(d0).Sub(d4); t4 = t4.Add(t3); z4 = t4; // For z.b_.c_ = z5. t0 = x0.Add(x2).Add(x4); t3 = s0.Mul(t0).Sub(s1); z5 = t3; return(new Fp12(new Fp6(z0, z1, z2), new Fp6(z3, z4, z5))); }