/// <summary> /// https://eprint.iacr.org/2010/354.pdf /// Algorithm 17 /// </summary> /// <returns></returns> public Fp6 Inverse() { Fp2 a0 = A; Fp2 a1 = B; Fp2 a2 = C; Fp2 t0 = a0.Squared(); Fp2 t1 = a1.Squared(); Fp2 t2 = a2.Squared(); Fp2 t3 = a0 * a1; Fp2 t4 = a0 * a2; Fp2 t5 = a1 * a2; // typo (a2 * a3 in paper)? Fp2 c0 = t0 - t5.MulByNonResidue(); Fp2 c1 = t2.MulByNonResidue() - t3; Fp2 c2 = t1 - t4; // typo in paper referenced above. should be "-" as per Scott, but is "*" Fp2 t6 = a0 * c0; t6 = t6 + a2.MulByNonResidue() * c1; t6 = t6 + a1.MulByNonResidue() * c2; t6 = t6.Inverse(); c0 = c0 * t6; c1 = c1 * t6; c2 = c2 * t6; return(new Fp6(c0, c1, c2)); }
private static Precomputed FlippedMillerLoopDoubling(Bn128Fp2 g2) { Fp2 x = g2.X, y = g2.Y, z = g2.Z; Fp2 a = Fp.InverseOf2.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.Fp2B.Mul(d); // e = twist_b * d Fp2 f = e.Add(e).Add(e); // f = 3 * e Fp2 g = Fp.InverseOf2.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(new Precomputed( new Bn128Fp2(rx, ry, rz), new EllCoeffs(ell0, ellVw, ellVv) )); }
private static Precomputed FlippedMillerLoopMixedAddition(Bn128Fp2 baseElement, Bn128Fp2 addend) { Fp2 x1 = addend.X, y1 = addend.Y, z1 = addend.Z; Fp2 x2 = baseElement.X, y2 = baseElement.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.Double()); // 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(new Precomputed( new Bn128Fp2(x3, y3, z3), new EllCoeffs(ell0, ellVw, ellVv) )); }
/// <summary> /// https://eprint.iacr.org/2010/354.pdf /// Algorithm 16 /// </summary> /// <returns></returns> public Fp6 Squared() { Fp2 a0 = A; Fp2 a1 = B; Fp2 a2 = C; Fp2 c4 = (a0 * a1).Double(); Fp2 c5 = a2.Squared(); Fp2 c1 = c5.MulByNonResidue() + c4; Fp2 c2 = c4 - c5; Fp2 c3 = a0.Squared(); c4 = a0 - a1 + a2; c5 = (a1 * a2).Double(); c4 = c4.Squared(); Fp2 c0 = c5.MulByNonResidue() + c3; c2 = c2 + c4 + c5 - c3; return(new Fp6(c0, c1, c2)); }