def untwist(P): q = P.X.q root = Fq6(Fq2.zero(q), Fq2.one(q), Fq2.zero(q)) zero = Fq6.zero(q) omega2 = Fq12(root, zero) omega3 = Fq12(zero, root) return EC.from_affine(omega2.inverse() * P.x, omega3.inverse() * P.y)
def twist(P): q = P.X.q root = Fq6(Fq2.zero(q), Fq2.one(q), Fq2.zero(q)) zero = Fq6.zero(q) omega2 = Fq12(root, zero) omega3 = Fq12(zero, root) c0 = omega2 * P.x c1 = omega3 * P.y return TwistedEC.from_affine(c0.c0.c0, c1.c0.c0)
def untwist(point: AffinePoint, ec=default_ec) -> AffinePoint: """ Given a point on G2 on the twisted curve, this converts it's coordinates back from Fq2 to Fq12. See Craig Costello book, look up twists. """ f = Fq12.one(ec.q) wsq = Fq12(ec.q, f.root, Fq6.zero(ec.q)) wcu = Fq12(ec.q, Fq6.zero(ec.q), f.root) return AffinePoint(point.x / wsq, point.y / wcu, False, ec)
def twist(point: AffinePoint, ec=default_ec_twist) -> AffinePoint: """ Given an untwisted point, this converts it's coordinates to a point on the twisted curve. See Craig Costello book, look up twists. """ f = Fq12.one(ec.q) wsq = Fq12(ec.q, f.root, Fq6.zero(ec.q)) wcu = Fq12(ec.q, Fq6.zero(ec.q), f.root) new_x = point.x * wsq new_y = point.y * wcu return AffinePoint(new_x, new_y, False, ec)
def test_fields(): a = Fq(17, 30) b = Fq(17, -18) c = Fq2(17, a, b) d = Fq2(17, a + a, -5) e = c * d f = e * d assert f != e e_sq = e * e e_sqrt = e_sq.modsqrt() assert pow(e_sqrt, 2) == e_sq a2 = Fq( 172487123095712930573140951348, 3012492130751239573498573249085723940848571098237509182375, ) b2 = Fq(172487123095712930573140951348, 3432984572394572309458723045723849) c2 = Fq2(172487123095712930573140951348, a2, b2) assert b2 != c2 g = Fq6(17, c, d, d * d * c) h = Fq6(17, a + a * c, c * b * a, b * b * d * 21) i = Fq12(17, g, h) assert ~(~i) == i assert (~(i.root)) * i.root == Fq6.one(17) x = Fq12(17, Fq6.zero(17), i.root) assert (~x) * x == Fq12.one(17) j = Fq6(17, a + a * c, Fq2.zero(17), Fq2.zero(17)) j2 = Fq6(17, a + a * c, Fq2.zero(17), Fq2.one(17)) assert j == (a + a * c) assert j2 != (a + a * c) assert j != j2 # Test frob_coeffs one = Fq(default_ec.q, 1) two = one + one a = Fq2(default_ec.q, two, two) b = Fq6(default_ec.q, a, a, a) c = Fq12(default_ec.q, b, b) for base in (a, b, c): for expo in range(1, base.extension): assert base.qi_power(expo) == pow(base, pow(default_ec.q, expo))
def setUp(self): self.a1 = Fq(3, 11) self.b1 = Fq(4, 11) self.c1 = Fq(7, 11) self.d1 = Fq(12, 11) self.e1 = Fq(2, 11) self.f1 = Fq(9, 11) self.g1 = Fq(6, 11) self.a2 = Fq2(self.a1, self.b1) self.b2 = Fq2(self.b1, self.c1) self.c2 = Fq2(self.c1, self.d1) self.d2 = Fq2(self.d1, self.e1) self.e2 = Fq2(self.e1, self.f1) self.f2 = Fq2(self.f1, self.g1) self.a6 = Fq6(self.a2, self.b2, self.c2) self.b6 = Fq6(self.b2, self.c2, self.d2) self.c6 = Fq6(self.d2, self.e2, self.f2) self.a12 = Fq12(self.a6, self.b6) self.b12 = Fq12(self.b6, self.c6)
# * uses curve impl from curve_ops # * only supports BLS12-381 # * Miller loop implementation avoids computing inversions # # (C) 2019 Riad S. Wahby <*****@*****.**> from functools import reduce from operator import mul from consts import p, ell_u, k_final from curve_ops import from_jacobian, point_double, point_add, to_coZ from fields import Fq, Fq2, Fq6, Fq12 # constants for untwisting ut_root = Fq12.one(p).root ut_wsq_inv = ~Fq12(p, ut_root, Fq6.zero(p)) ut_wcu_inv = ~Fq12(p, Fq6.zero(p), ut_root) del ut_root def _untwist(R): assert all(isinstance(pp, Fq2) for pp in R) (x, y, z) = R return (x * ut_wsq_inv, y * ut_wcu_inv, z) def _double_eval(R, P): (xP, yP) = P (xR, yR, zR) = _untwist(R) zR3 = pow(zR, 3)