From 7d13fd0b7c1f38c6df952d0fd4de0637e57d89f3 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 12 Oct 2023 12:00:58 -0400 Subject: [PATCH 1/6] perf(bw6-761): implement faster final exp hard part --- ecc/bw6-761/internal/fptower/e6_pairing.go | 125 +++++++++++++++------ ecc/bw6-761/pairing.go | 101 ++++++----------- 2 files changed, 126 insertions(+), 100 deletions(-) diff --git a/ecc/bw6-761/internal/fptower/e6_pairing.go b/ecc/bw6-761/internal/fptower/e6_pairing.go index 2ec55cf6d..f293ea1d4 100644 --- a/ecc/bw6-761/internal/fptower/e6_pairing.go +++ b/ecc/bw6-761/internal/fptower/e6_pairing.go @@ -14,16 +14,11 @@ func (z *E6) nSquareCompressed(n int) { } } -// Expt set z to x^t in E6 and return z -func (z *E6) Expt(x *E6) *E6 { - // const tAbsVal uint64 = 9586122913090633729 - // tAbsVal in binary: 1000010100001000110000000000000000000000000000000000000000000001 - // drop the low 46 bits (all 0 except the least significant bit): 100001010000100011 = 136227 - // Shortest addition chains can be found at https://wwwhomes.uni-bielefeld.de/achim/addition_chain.html +// ExptMinus1 set z to x^(t-1) in E6 and return z +// t-1 = 91893752504881257682351033800651177983 +func (z *E6) ExptMinus1(x *E6) *E6 { var result, x33 E6 - - // a shortest addition chain for 136227 result.Set(x) result.nSquare(5) result.Mul(&result, x) @@ -34,55 +29,121 @@ func (z *E6) Expt(x *E6) *E6 { result.Mul(&result, x) result.CyclotomicSquare(&result) result.Mul(&result, x) - - // the remaining 46 bits result.nSquareCompressed(46) result.DecompressKarabina(&result) - result.Mul(&result, x) - z.Set(&result) + return z } -// Expc2 set z to x^c2 in E6 and return z -// ht, hy = 13, 9 -// c1 = ht+hy = 22 (10110) -func (z *E6) Expc2(x *E6) *E6 { +// ExptMinus1Square set z to x^{(t-1)²} in E6 and return z +// (t-1)² = 91893752504881257682351033800651177984 +func (z *E6) ExptMinus1Square(x *E6) *E6 { + var result, t0, t1, t2 E6 + + result.Set(x) + result.CyclotomicSquare(&result) + t0.Mul(x, &result) + t1.CyclotomicSquare(&t0) + t0.Mul(&t0, &t1) + result.Mul(&result, &t0) + t1.Mul(&t1, &result) + t0.Mul(&t0, &t1) + t2.CyclotomicSquare(&t0) + t2.Mul(&t1, &t2) + t0.Mul(&t0, &t2) + t2.nSquare(7) + t1.Mul(&t1, &t2) + t1.nSquare(11) + t1.Mul(&t0, &t1) + t1.nSquare(9) + t0.Mul(&t0, &t1) + t0.CyclotomicSquare(&t0) + result.Mul(&result, &t0) + result.nSquareCompressed(92) + result.DecompressKarabina(&result) + z.Set(&result) + + return z +} +// Expt set z to x^t in E6 and return z +// t = 91893752504881257682351033800651177984 +func (z *E6) Expt(x *E6) *E6 { var result E6 - result.CyclotomicSquare(x) - result.CyclotomicSquare(&result) + result.ExptMinus1(x) result.Mul(&result, x) + z.Set(&result) + + return z +} + +// ExptPlus1 set z to x^(t+1) in E6 and return z +// t+1 = 91893752504881257682351033800651177985 +func (z *E6) ExptPlus1(x *E6) *E6 { + var result, t E6 + + result.ExptMinus1(x) + t.CyclotomicSquare(x) + result.Mul(&result, &t) + z.Set(&result) + + return z +} + +// ExptMinus1Div3 set z to x^(t-1)/3 in E6 and return z +// (t-1)/3 = 3195374304363544576 +func (z *E6) ExptMinus1Div3(x *E6) *E6 { + var result, t0 E6 + + result.Set(x) result.CyclotomicSquare(&result) result.Mul(&result, x) - result.CyclotomicSquare(&result) - + t0.Mul(&result, x) + t0.CyclotomicSquare(&t0) + result.Mul(&result, &t0) + t0.Set(&result) + t0.nSquare(7) + result.Mul(&result, &t0) + result.nSquare(5) + result.Mul(&result, x) + result.nSquareCompressed(46) + result.DecompressKarabina(&result) z.Set(&result) return z } -// Expc1 set z to x^c1 in E6 and return z +// Expc1 set z to z^c1 in E6 and return z // ht, hy = 13, 9 -// c1 = ht**2+3*hy**2 = 412 (110011100) +// c1 = (ht+hy)/2 = 11 func (z *E6) Expc1(x *E6) *E6 { - - var result E6 + var result, t0 E6 result.CyclotomicSquare(x) result.Mul(&result, x) - result.CyclotomicSquare(&result) - result.CyclotomicSquare(&result) - result.CyclotomicSquare(&result) - result.Mul(&result, x) - result.CyclotomicSquare(&result) + t0.Mul(x, &result) + t0.CyclotomicSquare(&t0) + result.Mul(&result, &t0) + z.Set(&result) + + return z +} + +// Expx2 set z to z^c2 in E6 and return z +// ht, hy = 13, 9 +// c2 = (ht**2+3*hy**2)/4 = 103 +func (z *E6) Expc2(x *E6) *E6 { + var result, t0 E6 + + result.CyclotomicSquare(x) result.Mul(&result, x) + t0.Set(&result) + t0.nSquare(4) + result.Mul(&result, &t0) result.CyclotomicSquare(&result) result.Mul(&result, x) - result.CyclotomicSquare(&result) - result.CyclotomicSquare(&result) - z.Set(&result) return z diff --git a/ecc/bw6-761/pairing.go b/ecc/bw6-761/pairing.go index e37bcf079..1f0eedddb 100644 --- a/ecc/bw6-761/pairing.go +++ b/ecc/bw6-761/pairing.go @@ -84,74 +84,39 @@ func FinalExponentiation(z *GT, _z ...*GT) GT { return result } - // Hard part (up to permutation) - // El Housni and Guillevic - // https://eprint.iacr.org/2020/351.pdf - var m1, _m1, m2, _m2, m3, f0, f0_36, g0, g1, _g1, g2, g3, _g3, g4, _g4, g5, _g5, g6, gA, gB, g034, _g1g2, gC, h1, h2, h2g2C, h4 GT - m1.Expt(&result) - _m1.Conjugate(&m1) - m2.Expt(&m1) - _m2.Conjugate(&m2) - m3.Expt(&m2) - f0.Frobenius(&result). - Mul(&f0, &result). - Mul(&f0, &m2) - m2.CyclotomicSquare(&_m1) - f0.Mul(&f0, &m2) - f0_36.CyclotomicSquare(&f0). - CyclotomicSquare(&f0_36). - CyclotomicSquare(&f0_36). - Mul(&f0_36, &f0). - CyclotomicSquare(&f0_36). - CyclotomicSquare(&f0_36) - g0.Mul(&result, &m1). - Frobenius(&g0). - Mul(&g0, &m3). - Mul(&g0, &_m2). - Mul(&g0, &_m1) - g1.Expt(&g0) - _g1.Conjugate(&g1) - g2.Expt(&g1) - g3.Expt(&g2) - _g3.Conjugate(&g3) - g4.Expt(&g3) - _g4.Conjugate(&g4) - g5.Expt(&g4) - _g5.Conjugate(&g5) - g6.Expt(&g5) - gA.Mul(&g3, &_g5). - CyclotomicSquare(&gA). - Mul(&gA, &g6). - Mul(&gA, &g1). - Mul(&gA, &g0) - g034.Mul(&g0, &g3). - Mul(&g034, &_g4) - gB.CyclotomicSquare(&g034). - Mul(&gB, &g034). - Mul(&gB, &g5). - Mul(&gB, &_g1) - _g1g2.Mul(&_g1, &g2) - gC.Mul(&_g3, &_g1g2). - CyclotomicSquare(&gC). - Mul(&gC, &_g1g2). - Mul(&gC, &g0). - CyclotomicSquare(&gC). - Mul(&gC, &g2). - Mul(&gC, &g0). - Mul(&gC, &g4) - - // ht, hy = 13, 9 - // c1 = ht**2+3*hy**2 = 412 - h1.Expc1(&gA) - // c2 = ht+hy = 22 - h2.Expc2(&gB) - h2g2C.CyclotomicSquare(&gC). - Mul(&h2g2C, &h2) - h4.CyclotomicSquare(&h2g2C). - Mul(&h4, &h2g2C). - CyclotomicSquare(&h4) - result.Mul(&h1, &h4). - Mul(&result, &f0_36) + // 2. Hard part (up to permutation) + // (x₀+1)(p²-p+1)/r + // Algorithm 4.4 from https://yelhousni.github.io/phd.pdf + var a, b, c, d, e, f, g, h, i, j, k, t GT + a.ExptMinus1Square(&result) + t.Frobenius(&result) + a.Mul(&a, &t) + b.ExptPlus1(&a) + t.Conjugate(&result) + b.Mul(&b, &t) + t.CyclotomicSquare(&a) + a.Mul(&a, &t) + c.ExptMinus1Div3(&b) + d.ExptMinus1(&c) + e.ExptMinus1Square(&d) + e.Mul(&e, &d) + d.Conjugate(&d) + f.Mul(&d, &b) + g.ExptPlus1(&e) + g.Mul(&g, &f) + h.Mul(&g, &c) + i.Mul(&g, &d) + i.ExptPlus1(&i) + t.Conjugate(&f) + i.Mul(&i, &t) + j.Expc1(&h) + j.Mul(&j, &e) + k.CyclotomicSquare(&j) + k.Mul(&k, &j) + k.Mul(&k, &b) + t.Expc2(&i) + k.Mul(&k, &t) + result.Mul(&a, &k) return result } From 5b7609cfd9d02c475072fa381a865a2043b0a218 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 12 Oct 2023 12:04:47 -0400 Subject: [PATCH 2/6] perf(bw6-761): remove unnecessary computations in MillerLoop --- ecc/bw6-761/pairing.go | 73 +----------------------------------------- 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/ecc/bw6-761/pairing.go b/ecc/bw6-761/pairing.go index 1f0eedddb..04f30f7ba 100644 --- a/ecc/bw6-761/pairing.go +++ b/ecc/bw6-761/pairing.go @@ -152,29 +152,11 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { // precomputations pProj1 := make([]g1Proj, n) p1 := make([]G1Affine, n) - pProj01 := make([]g1Proj, n) // P0+P1 - pProj10 := make([]g1Proj, n) // P0-P1 - l01 := make([]lineEvaluation, n) - l10 := make([]lineEvaluation, n) for k := 0; k < n; k++ { p1[k].Y.Neg(&p0[k].Y) p1[k].X.Mul(&p0[k].X, &thirdRootOneG2) pProj1[k].FromAffine(&p1[k]) - - // l_{p0,p1}(q) - pProj01[k].Set(&pProj1[k]) - pProj01[k].addMixedStep(&l01[k], &p0[k]) - l01[k].r1.Mul(&l01[k].r1, &q[k].X) - l01[k].r0.Mul(&l01[k].r0, &q[k].Y) - - // l_{p0,-p1}(q) - pProj10[k].Neg(&pProj1[k]) - pProj10[k].addMixedStep(&l10[k], &p0[k]) - l10[k].r1.Mul(&l10[k].r1, &q[k].X) - l10[k].r0.Mul(&l10[k].r0, &q[k].Y) } - p01 := BatchProjectiveToAffineG1(pProj01) - p10 := BatchProjectiveToAffineG1(pProj10) // f_{a0+λ*a1,P}(Q) var result GT @@ -242,20 +224,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l0.r0.Mul(&l0.r0, &q[k].Y) switch j { - case -4: - tmp.Neg(&p01[k]) - // pProj1[k] ← pProj1[k]-p01[k] and - // l the line ℓ passing pProj1[k] and -p01[k] - pProj1[k].addMixedStep(&l, &tmp) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) + // cases -4, -2, 2, 4 do not occur, given the static loopCounters case -3: tmp.Neg(&p1[k]) // pProj1[k] ← pProj1[k]-p1[k] and @@ -268,19 +237,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case -2: - // pProj1[k] ← pProj1[k]+p10[k] and - // l the line ℓ passing pProj1[k] and p10[k] - pProj1[k].addMixedStep(&l, &p10[k]) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case -1: tmp.Neg(&p0[k]) // pProj1[k] ← pProj1[k]-p0[k] and @@ -307,20 +263,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case 2: - tmp.Neg(&p10[k]) - // pProj1[k] ← pProj1[k]-p10[k] and - // l the line ℓ passing pProj1[k] and -p10[k] - pProj1[k].addMixedStep(&l, &tmp) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case 3: // pProj1[k] ← pProj1[k]+p1[k] and // l the line ℓ passing pProj1[k] and p1[k] @@ -332,19 +274,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case 4: - // pProj1[k] ← pProj1[k]+p01[k] and - // l the line ℓ passing pProj1[k] and p01[k] - pProj1[k].addMixedStep(&l, &p01[k]) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) default: return GT{}, errors.New("invalid loopCounter") } From 19209bbb2170c07bfcdb4a62af2acea08e6f6877 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 12 Oct 2023 12:09:19 -0400 Subject: [PATCH 3/6] perf(bw6-756): remove unnecessary computations in MillerLoop --- ecc/bw6-756/pairing.go | 72 ------------------------------------------ 1 file changed, 72 deletions(-) diff --git a/ecc/bw6-756/pairing.go b/ecc/bw6-756/pairing.go index d4e1b2945..70dfe9bcd 100644 --- a/ecc/bw6-756/pairing.go +++ b/ecc/bw6-756/pairing.go @@ -189,29 +189,11 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { // precomputations pProj1 := make([]g1Proj, n) p1 := make([]G1Affine, n) - pProj01 := make([]g1Proj, n) // P0+P1 - pProj10 := make([]g1Proj, n) // P0-P1 - l01 := make([]lineEvaluation, n) - l10 := make([]lineEvaluation, n) for k := 0; k < n; k++ { p1[k].Y.Neg(&p0[k].Y) p1[k].X.Mul(&p0[k].X, &thirdRootOneG2) pProj1[k].FromAffine(&p1[k]) - - // l_{p0,p1}(q) - pProj01[k].Set(&pProj1[k]) - pProj01[k].addMixedStep(&l01[k], &p0[k]) - l01[k].r1.Mul(&l01[k].r1, &q[k].X) - l01[k].r0.Mul(&l01[k].r0, &q[k].Y) - - // l_{p0,-p1}(q) - pProj10[k].Neg(&pProj1[k]) - pProj10[k].addMixedStep(&l10[k], &p0[k]) - l10[k].r1.Mul(&l10[k].r1, &q[k].X) - l10[k].r0.Mul(&l10[k].r0, &q[k].Y) } - p01 := BatchProjectiveToAffineG1(pProj01) - p10 := BatchProjectiveToAffineG1(pProj10) // f_{a0+λ*a1,P}(Q) var result GT @@ -279,20 +261,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l0.r0.Mul(&l0.r0, &q[k].Y) switch j { - case -4: - tmp.Neg(&p01[k]) - // pProj1[k] ← pProj1[k]-p01[k] and - // l the line ℓ passing pProj1[k] and -p01[k] - pProj1[k].addMixedStep(&l, &tmp) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case -3: tmp.Neg(&p1[k]) // pProj1[k] ← pProj1[k]-p1[k] and @@ -305,19 +273,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case -2: - // pProj1[k] ← pProj1[k]+p10[k] and - // l the line ℓ passing pProj1[k] and p10[k] - pProj1[k].addMixedStep(&l, &p10[k]) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case -1: tmp.Neg(&p0[k]) // pProj1[k] ← pProj1[k]-p0[k] and @@ -344,20 +299,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case 2: - tmp.Neg(&p10[k]) - // pProj1[k] ← pProj1[k]-p10[k] and - // l the line ℓ passing pProj1[k] and -p10[k] - pProj1[k].addMixedStep(&l, &tmp) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case 3: // pProj1[k] ← pProj1[k]+p1[k] and // l the line ℓ passing pProj1[k] and p1[k] @@ -369,19 +310,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case 4: - // pProj1[k] ← pProj1[k]+p01[k] and - // l the line ℓ passing pProj1[k] and p01[k] - pProj1[k].addMixedStep(&l, &p01[k]) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) default: return GT{}, errors.New("invalid loopCounter") } From fb97a48b3381b0a1758a1d9f7b59326746a352dc Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Thu, 12 Oct 2023 12:12:04 -0400 Subject: [PATCH 4/6] perf(bw6-633): remove unnecessary computations in MillerLoop --- ecc/bw6-633/pairing.go | 73 +----------------------------------------- 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/ecc/bw6-633/pairing.go b/ecc/bw6-633/pairing.go index 2f6fc9102..fec9c44ba 100644 --- a/ecc/bw6-633/pairing.go +++ b/ecc/bw6-633/pairing.go @@ -208,30 +208,12 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { // precomputations pProj0 := make([]g1Proj, n) p1 := make([]G1Affine, n) - pProj01 := make([]g1Proj, n) // P0+P1 - pProj10 := make([]g1Proj, n) // P0-P1 - l01 := make([]lineEvaluation, n) - l10 := make([]lineEvaluation, n) for k := 0; k < n; k++ { p1[k].Y.Set(&p0[k].Y) p1[k].X.Mul(&p0[k].X, &thirdRootOneG1) p0[k].Neg(&p0[k]) pProj0[k].FromAffine(&p0[k]) - - // l_{p0,p1}(q) - pProj01[k].Set(&pProj0[k]) - pProj01[k].addMixedStep(&l01[k], &p1[k]) - l01[k].r1.Mul(&l01[k].r1, &q[k].X) - l01[k].r0.Mul(&l01[k].r0, &q[k].Y) - - // l_{-p0,p1}(q) - pProj10[k].Neg(&pProj0[k]) - pProj10[k].addMixedStep(&l10[k], &p1[k]) - l10[k].r1.Mul(&l10[k].r1, &q[k].X) - l10[k].r0.Mul(&l10[k].r0, &q[k].Y) } - p01 := BatchProjectiveToAffineG1(pProj01) - p10 := BatchProjectiveToAffineG1(pProj10) // f_{a0+λ*a1,P}(Q) var result GT @@ -299,20 +281,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l0.r0.Mul(&l0.r0, &q[k].Y) switch j { - case -4: - tmp.Neg(&p01[k]) - // pProj0[k] ← pProj0[k]-p01[k] and - // l the line ℓ passing pProj0[k] and -p01[k] - pProj0[k].addMixedStep(&l, &tmp) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) + // cases -4, -2, 2, 4 do not occur given the static loopCounters case -3: tmp.Neg(&p1[k]) // pProj0[k] ← pProj0[k]-p1[k] and @@ -325,19 +294,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case -2: - // pProj0[k] ← pProj0[k]+p10[k] and - // l the line ℓ passing pProj0[k] and p10[k] - pProj0[k].addMixedStep(&l, &p10[k]) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case -1: tmp.Neg(&p0[k]) // pProj0[k] ← pProj0[k]-p0[k] and @@ -364,20 +320,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case 2: - tmp.Neg(&p10[k]) - // pProj0[k] ← pProj0[k]-p10[k] and - // l the line ℓ passing pProj0[k] and -p10[k] - pProj0[k].addMixedStep(&l, &tmp) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) case 3: // pProj0[k] ← pProj0[k]+p1[k] and // l the line ℓ passing pProj0[k] and p1[k] @@ -389,19 +331,6 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - case 4: - // pProj0[k] ← pProj0[k]+p01[k] and - // l the line ℓ passing pProj0[k] and p01[k] - pProj0[k].addMixedStep(&l, &p01[k]) - // line evaluation at Q[k] - l.r1.Mul(&l.r1, &q[k].X) - l.r0.Mul(&l.r0, &q[k].Y) - // ℓ × ℓ - prodLines = fptower.Mul034By034(&l.r0, &l.r1, &l.r2, &l01[k].r0, &l01[k].r1, &l01[k].r2) - // ℓ × res - result.MulBy034(&l0.r0, &l0.r1, &l0.r2) - // (ℓ × ℓ) × res - result.MulBy01234(&prodLines) default: return GT{}, errors.New("invalid loopCounter") } From 2230a7e9181dde340fbfa9c6a296185df4ae27dd Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Fri, 13 Oct 2023 13:02:53 -0400 Subject: [PATCH 5/6] perf(bw6-756): implement faster final exp hard part --- ecc/bw6-756/bw6-756.go | 4 +- ecc/bw6-756/internal/fptower/e6_pairing.go | 127 +++++++++++++++------ ecc/bw6-756/pairing.go | 107 ++++++----------- ecc/bw6-761/bw6-761.go | 5 +- ecc/bw6-761/pairing.go | 2 +- 5 files changed, 135 insertions(+), 110 deletions(-) diff --git a/ecc/bw6-756/bw6-756.go b/ecc/bw6-756/bw6-756.go index 6a1c71fed..d7e8570f1 100644 --- a/ecc/bw6-756/bw6-756.go +++ b/ecc/bw6-756/bw6-756.go @@ -3,13 +3,15 @@ // bw6-756: A Brezing--Weng curve (2-chain with bls12-378) // // embedding degree k=6 -// seed x₀=11045256207009841153. +// seed x₀=11045256207009841153 // 𝔽p: p=366325390957376286590726555727219947825377821289246188278797409783441745356050456327989347160777465284190855125642086860525706497928518803244008749360363712553766506755227344593404398783886857865261088226271336335268413437902849 // 𝔽r: r=605248206075306171733248481581800960739847691770924913753520744034740935903401304776283802348837311170974282940417 // (E/𝔽p): Y²=X³+1 // (Eₜ/𝔽p): Y² = X³+33 (M-type twist) // r ∣ #E(Fp) and r ∣ #Eₜ(𝔽p) // +// case t % r % x₀ = 3 +// // Extension fields tower: // // 𝔽p³[u] = 𝔽p/u³-33 diff --git a/ecc/bw6-756/internal/fptower/e6_pairing.go b/ecc/bw6-756/internal/fptower/e6_pairing.go index 6eb52c190..f4af22821 100644 --- a/ecc/bw6-756/internal/fptower/e6_pairing.go +++ b/ecc/bw6-756/internal/fptower/e6_pairing.go @@ -14,61 +14,114 @@ func (z *E6) nSquareCompressed(n int) { } } -// Expt set z to x^t in E6 and return z -func (z *E6) Expt(x *E6) *E6 { +// ExptMinus1 set z to x^t in E6 and return z +// t-1 = 11045256207009841152 +func (z *E6) ExptMinus1(x *E6) *E6 { - // Expt computation is derived from the addition chain: - // - // _1000 = 1 << 3 - // _1001 = 1 + _1000 - // _1001000 = _1001 << 3 - // _1010001 = _1001 + _1001000 - // _10011001 = _1001000 + _1010001 - // i67 = ((_10011001 << 5 + _1001) << 10 + _1010001) << 41 - // return 1 + i67 - // - // Operations: 62 squares 6 multiplies - // - // Generated by github.com/mmcloughlin/addchain v0.4.0. - - // Allocate Temporaries. var result, t0, t1 E6 - // Step 3: result = x^0x8 result.CyclotomicSquare(x) result.nSquare(2) - - // Step 4: t0 = x^0x9 t0.Mul(x, &result) - - // Step 7: t1 = x^0x48 t1.CyclotomicSquare(&t0) t1.nSquare(2) - - // Step 8: result = x^0x51 result.Mul(&t0, &t1) - - // Step 9: t1 = x^0x99 t1.Mul(&t1, &result) - - // Step 14: t1 = x^0x1320 t1.nSquare(5) - - // Step 15: t0 = x^0x1329 t0.Mul(&t0, &t1) - - // Step 25: t0 = x^0x4ca400 t0.nSquare(10) + result.Mul(&result, &t0) + result.nSquareCompressed(41) + result.DecompressKarabina(&result) + z.Set(&result) + + return z +} - // Step 26: result = x^0x4ca451 +// ExptMinus1Square set z to x^t in E6 and return z +// (t-1)^2 = 121997684678489422939424157776272687104 +func (z *E6) ExptMinus1Square(x *E6) *E6 { + var result, t0, t1, t2, t3 E6 + result.CyclotomicSquare(x) + t0.Mul(x, &result) + result.CyclotomicSquare(&t0) + t0.Mul(&t0, &result) + result.Mul(&result, &t0) + t1.CyclotomicSquare(&result) + t1.nSquare(2) + t0.Mul(&t0, &t1) result.Mul(&result, &t0) + t0.Mul(&t0, &result) + result.Mul(&result, &t0) + t1.CyclotomicSquare(&result) + t1.Mul(&result, &t1) + t1.CyclotomicSquare(&t1) + t2.CyclotomicSquare(&t1) + t1.Mul(&t1, &t2) + t2.Mul(&t2, &t1) + t1.Mul(&t1, &t2) + t3.CyclotomicSquare(&t1) + t2.Mul(&t2, &t3) + t1.Mul(&t1, &t2) + t3.CyclotomicSquare(&t1) + t3.CyclotomicSquare(&t3) + t3.Mul(&t1, &t3) + t3.nSquare(2) + t2.Mul(&t2, &t3) + t2.nSquare(11) + t1.Mul(&t1, &t2) + t0.Mul(&t0, &t1) + t0.nSquare(13) + result.Mul(&result, &t0) + result.nSquareCompressed(82) + result.DecompressKarabina(&result) + z.Set(&result) - // Step 67: result = x^0x9948a20000000000 + return z +} + +// Expt set z to x^t in E6 and return z +// t = 11045256207009841153 +func (z *E6) Expt(x *E6) *E6 { + var result E6 + + result.ExptMinus1(x) + result.Mul(&result, x) + z.Set(&result) + + return z +} + +// ExptPlus1 set z to x^(t+1) in E6 and return z +// t+1 = 11045256207009841154 +func (z *E6) ExptPlus1(x *E6) *E6 { + var result, t E6 + + result.ExptMinus1(x) + t.CyclotomicSquare(x) + result.Mul(&result, &t) + z.Set(&result) + + return z +} + +// ExptMinus1Div3 set z to x^(t-1)/3 in E6 and return z +// (t-1)/3 = 3681752069003280384 +func (z *E6) ExptMinus1Div3(x *E6) *E6 { + var result, t0, t1 E6 + result.CyclotomicSquare(x) + t0.Mul(x, &result) + t1.CyclotomicSquare(&t0) + t1.nSquare(2) + result.Mul(&t0, &t1) + t1.Mul(&t1, &result) + t1.nSquare(5) + t0.Mul(&t0, &t1) + t0.nSquare(10) + result.Mul(&result, &t0) result.nSquareCompressed(41) result.DecompressKarabina(&result) - - // Step 68: result = x^0x9948a20000000001 - z.Mul(x, &result) + z.Set(&result) return z } diff --git a/ecc/bw6-756/pairing.go b/ecc/bw6-756/pairing.go index 70dfe9bcd..bd7785642 100644 --- a/ecc/bw6-756/pairing.go +++ b/ecc/bw6-756/pairing.go @@ -59,7 +59,7 @@ func PairingCheck(P []G1Affine, Q []G2Affine) (bool, error) { // FinalExponentiation computes the exponentiation (∏ᵢ zᵢ)ᵈ // where d = (p^6-1)/r = (p^6-1)/Φ_6(p) ⋅ Φ_6(p)/r = (p^3-1)(p+1)(p^2 - p +1)/r // we use instead d=s ⋅ (p^3-1)(p+1)(p^2 - p +1)/r -// where s is the cofactor 12(x_0+1) (El Housni and Guillevic) +// where s is the cofactor (x_0+1) (El Housni and Guillevic) func FinalExponentiation(z *GT, _z ...*GT) GT { var result GT @@ -85,75 +85,41 @@ func FinalExponentiation(z *GT, _z ...*GT) GT { return result } - // Hard part (up to permutation) - // El Housni and Guillevic - // https://eprint.iacr.org/2020/351.pdf - var m1, _m1, m2, _m2, m3, f0, f0_36, g0, g1, _g1, g2, g3, _g3, g4, _g4, g5, _g5, g6, gA, gB, g034, _g1g2, gC, h1, h2, h2g2C, h4 GT - m1.Expt(&result) - _m1.Conjugate(&m1) - m2.Expt(&m1) - _m2.Conjugate(&m2) - m3.Expt(&m2) - f0.Frobenius(&result). - Mul(&f0, &result). - Mul(&f0, &m2) - m2.CyclotomicSquare(&_m1) - f0.Mul(&f0, &m2) - f0_36.CyclotomicSquare(&f0). - CyclotomicSquare(&f0_36). - CyclotomicSquare(&f0_36). - Mul(&f0_36, &f0). - CyclotomicSquare(&f0_36). - CyclotomicSquare(&f0_36) - g0.Mul(&result, &m1). - Frobenius(&g0). - Mul(&g0, &m3). - Mul(&g0, &_m2). - Mul(&g0, &_m1) - g1.Expt(&g0) - _g1.Conjugate(&g1) - g2.Expt(&g1) - g3.Expt(&g2) - _g3.Conjugate(&g3) - g4.Expt(&g3) - _g4.Conjugate(&g4) - g5.Expt(&g4) - _g5.Conjugate(&g5) - g6.Expt(&g5) - gA.Mul(&g3, &_g5). - CyclotomicSquare(&gA). - Mul(&gA, &g6). - Mul(&gA, &g1). - Mul(&gA, &g0) - g034.Mul(&g0, &g3). - Mul(&g034, &_g4) - gB.CyclotomicSquare(&g034). - Mul(&gB, &g034). - Mul(&gB, &g5). - Mul(&gB, &_g1) - _g1g2.Mul(&_g1, &g2) - gC.Mul(&_g3, &_g1g2). - CyclotomicSquare(&gC). - Mul(&gC, &_g1g2). - Mul(&gC, &g0). - CyclotomicSquare(&gC). - Mul(&gC, &g2). - Mul(&gC, &g0). - Mul(&gC, &g4) - // ht, hy = -1, -1 - // c1 = ht**2+3*hy**2 = 4 - h1.CyclotomicSquare(&gA). - CyclotomicSquare(&h1) - // c2 = ht+hy = -2 - h2.CyclotomicSquare(&gB). - Conjugate(&h2) - h2g2C.CyclotomicSquare(&gC). - Mul(&h2g2C, &h2) - h4.CyclotomicSquare(&h2g2C). - Mul(&h4, &h2g2C). - CyclotomicSquare(&h4) - result.Mul(&h1, &h4). - Mul(&result, &f0_36) + // 2. Hard part (up to permutation) + // (x₀+1)(p²-p+1)/r + // Algorithm 4.4 from https://yelhousni.github.io/phd.pdf + var a, b, c, d, e, f, g, h, i, j, k, t GT + a.ExptMinus1Square(&result) + t.Frobenius(&result) + a.Mul(&a, &t) + b.ExptPlus1(&a) + t.Conjugate(&result) + b.Mul(&b, &t) + t.CyclotomicSquare(&a) + a.Mul(&a, &t) + c.ExptMinus1Div3(&b) + d.ExptMinus1(&c) + e.ExptMinus1Square(&d) + e.Mul(&e, &d) + d.Conjugate(&d) + f.Mul(&d, &b) + g.ExptPlus1(&e) + g.Mul(&g, &f) + h.Mul(&g, &c) + i.Mul(&g, &d) + i.ExptPlus1(&i) + t.Conjugate(&f) + i.Mul(&i, &t) + // ht, hy = -1, -1 + // c1 = (ht+hy)/2 = -1 + j.Conjugate(&h) + j.Mul(&j, &e) + k.CyclotomicSquare(&j) + k.Mul(&k, &j) + k.Mul(&k, &b) + // c2 = (ht**2+3*hy**2)/4 = 1 + k.Mul(&k, &i) + result.Mul(&a, &k) return result } @@ -261,6 +227,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l0.r0.Mul(&l0.r0, &q[k].Y) switch j { + // cases -4, -2, 2, 4 do not occur, given the static loopCounters case -3: tmp.Neg(&p1[k]) // pProj1[k] ← pProj1[k]-p1[k] and diff --git a/ecc/bw6-761/bw6-761.go b/ecc/bw6-761/bw6-761.go index 07668c69e..9e1446410 100644 --- a/ecc/bw6-761/bw6-761.go +++ b/ecc/bw6-761/bw6-761.go @@ -10,6 +10,8 @@ // (Eₜ/𝔽p): Y² = X³+4 (M-type twist) // r ∣ #E(Fp) and r ∣ #Eₜ(𝔽p) // +// case t % r % x₀ = 3 +// // Extension fields tower: // // 𝔽p³[u] = 𝔽p/u³+4 @@ -30,9 +32,10 @@ package bw6761 import ( - "github.com/consensys/gnark-crypto/ecc/bw6-761/internal/fptower" "math/big" + "github.com/consensys/gnark-crypto/ecc/bw6-761/internal/fptower" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" diff --git a/ecc/bw6-761/pairing.go b/ecc/bw6-761/pairing.go index 04f30f7ba..12ca16ba0 100644 --- a/ecc/bw6-761/pairing.go +++ b/ecc/bw6-761/pairing.go @@ -58,7 +58,7 @@ func PairingCheck(P []G1Affine, Q []G2Affine) (bool, error) { // FinalExponentiation computes the exponentiation (∏ᵢ zᵢ)ᵈ // where d = (p^6-1)/r = (p^6-1)/Φ_6(p) ⋅ Φ_6(p)/r = (p^3-1)(p+1)(p^2 - p +1)/r // we use instead d=s ⋅ (p^3-1)(p+1)(p^2 - p +1)/r -// where s is the cofactor 12(x_0+1) (El Housni and Guillevic) +// where s is the cofactor (x_0+1) (El Housni and Guillevic) func FinalExponentiation(z *GT, _z ...*GT) GT { var result GT From 6cfca29dfc9a15cffd9dbc0785beb1cb2858ed5b Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Fri, 13 Oct 2023 17:40:24 -0400 Subject: [PATCH 6/6] perf(bw6-633): implement faster final exp hard part --- ecc/bw6-633/bw6-633.go | 2 + ecc/bw6-633/internal/fptower/e6_pairing.go | 136 ++++++++++++++++++++- ecc/bw6-633/pairing.go | 132 ++++++-------------- ecc/bw6-761/internal/fptower/e6_pairing.go | 2 +- 4 files changed, 178 insertions(+), 94 deletions(-) diff --git a/ecc/bw6-633/bw6-633.go b/ecc/bw6-633/bw6-633.go index b34f6c212..6944235c4 100644 --- a/ecc/bw6-633/bw6-633.go +++ b/ecc/bw6-633/bw6-633.go @@ -15,6 +15,8 @@ // 𝔽p³[u] = 𝔽p/u³-2 // 𝔽p⁶[v] = 𝔽p²/v²-u // +// case t % r % u = 0 +// // optimal Ate loops: // // x₀+1, x₀^5-x₀^4-x₀ diff --git a/ecc/bw6-633/internal/fptower/e6_pairing.go b/ecc/bw6-633/internal/fptower/e6_pairing.go index 661a75519..11d659c94 100644 --- a/ecc/bw6-633/internal/fptower/e6_pairing.go +++ b/ecc/bw6-633/internal/fptower/e6_pairing.go @@ -2,14 +2,46 @@ package fptower import "github.com/consensys/gnark-crypto/ecc/bw6-633/fp" +func (z *E6) nSquare(n int) { + for i := 0; i < n; i++ { + z.CyclotomicSquare(z) + } +} + func (z *E6) nSquareCompressed(n int) { for i := 0; i < n; i++ { z.CyclotomicSquareCompressed(z) } } +// Expc1 set z to z^c1 in E6 and return z +// ht, hy = -7, -1 +// c1 = (ht-hy)/2 = -3 +func (z *E6) Expc1(x *E6) *E6 { + var result E6 + result.CyclotomicSquare(x) + result.Mul(x, &result) + z.Conjugate(&result) + + return z +} + +// Expc2 set z to z^c2 in E6 and return z +// ht, hy = -7, -1 +// c2 = (ht**2+3*hy**2)/4 = 13 +func (z *E6) Expc2(x *E6) *E6 { + var result E6 + result.CyclotomicSquare(x) + result.Mul(x, &result) + result.nSquare(2) + result.Mul(x, &result) + z.Set(&result) + + return z +} + // Expt set z to x^t in E6 and return z (t is the seed of the curve) -// -2**32+2**30+2**22-2**20+1 +// t = -3218079743 = -2**32+2**30+2**22-2**20+1 func (z *E6) Expt(x *E6) *E6 { var result, x20, x22, x30, x32 E6 @@ -36,6 +68,108 @@ func (z *E6) Expt(x *E6) *E6 { return z } +// ExptMinus1 set z to x^(t-1) in E6 and return z +// t-1 = -3218079744 +func (z *E6) ExptMinus1(x *E6) *E6 { + var result, t E6 + result.Expt(x) + t.Conjugate(x) + result.Mul(&result, &t) + z.Set(&result) + + return z +} + +// ExptMinus1Squared set z to x^(t-1)^2 in E6 and return z +// (t-1)^2 = 10356037238743105536 +func (z *E6) ExptMinus1Squared(x *E6) *E6 { + var result, t0, t1, t2 E6 + result.CyclotomicSquare(x) + result.CyclotomicSquare(&result) + t1.Mul(x, &result) + result.Mul(&result, &t1) + t0.CyclotomicSquare(&result) + t0.Mul(&t1, &t0) + t2.CyclotomicSquare(&t0) + t2.Mul(&t0, &t2) + t2.CyclotomicSquare(&t2) + t1.Mul(&t1, &t2) + t1.nSquare(5) + t0.Mul(&t0, &t1) + t0.nSquare(11) + result.Mul(&result, &t0) + result.nSquareCompressed(40) + result.DecompressKarabina(&result) + z.Set(&result) + return z +} + +// ExptPlus1 set z to x^(t+1) in E6 and return z +// t + 1 = -3218079742 +func (z *E6) ExptPlus1(x *E6) *E6 { + var result E6 + result.Expt(x) + result.Mul(&result, x) + z.Set(&result) + + return z +} + +// ExptSquarePlus1 set z to x^(t^2+1) in E6 and return z +// t^2 + 1 = 10356037232306946050 +func (z *E6) ExptSquarePlus1(x *E6) *E6 { + var result, t0, t1, t2, t3 E6 + t0.CyclotomicSquare(x) + result.Mul(x, &t0) + t0.Mul(&t0, &result) + t1.Mul(x, &t0) + t0.Mul(&t0, &t1) + t0.CyclotomicSquare(&t0) + t2.Mul(x, &t0) + t0.Mul(&t1, &t2) + t1.Mul(&t1, &t0) + t1.nSquare(2) + t1.Mul(&result, &t1) + t3.CyclotomicSquare(&t1) + t3.nSquare(4) + t2.Mul(&t2, &t3) + t2.nSquareCompressed(15) + t2.DecompressKarabina(&t2) + t1.Mul(&t1, &t2) + t1.nSquare(5) + t0.Mul(&t0, &t1) + t0.nSquare(10) + result.Mul(&result, &t0) + result.nSquareCompressed(20) + result.DecompressKarabina(&result) + result.Mul(x, &result) + result.CyclotomicSquare(&result) + z.Set(&result) + + return z +} + +// ExptMinus1Div3 set z to x^((t-1)/3) in E6 and return z +// (t-1)/3 = -1072693248 +func (z *E6) ExptMinus1Div3(x *E6) *E6 { + var result, t0, t1 E6 + result.CyclotomicSquare(x) + result.Mul(x, &result) + t0.CyclotomicSquare(&result) + t0.CyclotomicSquare(&t0) + t0.Mul(&result, &t0) + t1.CyclotomicSquare(&t0) + t1.nSquare(3) + t0.Mul(&t0, &t1) + t0.nSquare(2) + result.Mul(&result, &t0) + result.nSquareCompressed(20) + result.DecompressKarabina(&result) + z.Conjugate(&result) + + return z +} + // MulBy034 multiplication by sparse element (c0,0,0,c3,c4,0) func (z *E6) MulBy034(c0, c3, c4 *fp.Element) *E6 { diff --git a/ecc/bw6-633/pairing.go b/ecc/bw6-633/pairing.go index fec9c44ba..96d737e9e 100644 --- a/ecc/bw6-633/pairing.go +++ b/ecc/bw6-633/pairing.go @@ -59,7 +59,7 @@ func PairingCheck(P []G1Affine, Q []G2Affine) (bool, error) { // FinalExponentiation computes the exponentiation (∏ᵢ zᵢ)ᵈ // where d = (p^6-1)/r = (p^6-1)/Φ_6(p) ⋅ Φ_6(p)/r = (p^3-1)(p+1)(p^2 - p +1)/r // we use instead d=s ⋅ (p^3-1)(p+1)(p^2 - p +1)/r -// where s is the cofactor 3(x_0+1) (El Housni and Guillevic) +// where s is the cofactor (x^5-x^4-x) (El Housni and Guillevic) func FinalExponentiation(z *GT, _z ...*GT) GT { var result GT @@ -86,97 +86,45 @@ func FinalExponentiation(z *GT, _z ...*GT) GT { } // Hard part (up to permutation) - // El Housni and Guillevic - // https://eprint.iacr.org/2021/1359.pdf - var m [11]GT - var f10, _m1, _m3, _m4, _m5, _m7, _m8, _m8m5, _m6, f11, f11f10, f12, f1, f1u, f1q, f1a GT - m[0].Set(&result) - for i := 1; i < 11; i++ { - m[i].Expt(&m[i-1]) - } - result.Mul(&m[3], &m[1]). - Conjugate(&result). - Mul(&result, &m[2]). - Mul(&result, &m[0]). - CyclotomicSquare(&result). - Mul(&result, &m[4]) - buf.Frobenius(&m[0]).Conjugate(&buf) - result.Mul(&result, &buf) - buf.CyclotomicSquare(&result). - CyclotomicSquare(&buf). - CyclotomicSquare(&buf) - result.Mul(&result, &buf) - _m1.Conjugate(&m[1]) - _m3.Conjugate(&m[3]) - _m4.Conjugate(&m[4]) - _m5.Conjugate(&m[5]) - _m7.Conjugate(&m[7]) - f10.Mul(&m[4], &_m3). - CyclotomicSquare(&f10). - Mul(&f10, &m[2]). - Mul(&f10, &m[6]). - Mul(&f10, &_m5). - CyclotomicSquare(&f10). - Mul(&f10, &_m1). - Mul(&f10, &_m5). - Mul(&f10, &_m7). - CyclotomicSquare(&f10). - Mul(&f10, &m[0]). - Mul(&f10, &m[2]). - Mul(&f10, &m[3]). - Mul(&f10, &_m1). - CyclotomicSquare(&f10). - Mul(&f10, &m[0]). - Mul(&f10, &m[8]). - Mul(&f10, &_m4) - _m8.Conjugate(&m[8]) - _m6.Conjugate(&m[6]) - _m8m5.Mul(&m[5], &_m8) - f11.Mul(&m[7], &_m6). - CyclotomicSquare(&f11). - Mul(&f11, &m[2]). - Mul(&f11, &_m3). - Mul(&f11, &_m8m5). - CyclotomicSquare(&f11). - Mul(&f11, &_m8m5). - Mul(&f11, &m[9]). - Mul(&f11, &_m1) - buf.CyclotomicSquare(&f11) - f11.Mul(&buf, &f11) - f11f10.Mul(&f11, &f10) - buf.CyclotomicSquare(&f11f10) - f11f10.Mul(&f11f10, &buf) - f12.Mul(&m[0], &m[1]). - Mul(&f12, &m[2]). - Mul(&f12, &m[8]). - Mul(&f12, &m[10]) - buf.CyclotomicSquare(&m[5]) - f12.Mul(&f12, &buf) - buf.CyclotomicSquare(&m[9]). - Mul(&buf, &m[6]). - Mul(&buf, &m[4]). - Conjugate(&buf) - f12.Mul(&f12, &buf) - buf.CyclotomicSquare(&f12). // cyclo exp by 13: (ht**2+3*hy**2)//4 - Mul(&buf, &f12). - CyclotomicSquare(&buf). - CyclotomicSquare(&buf) - f12.Mul(&f12, &buf) - f1.Mul(&f11f10, &f12) - f1u.Expt(&f1) - f1q.Mul(&f1u, &f1). - Frobenius(&f1q) - f1a.Conjugate(&f1u). - Mul(&f1a, &f1). - Expt(&f1a). - Expt(&f1a). - Expt(&f1a). - Expt(&f1a) - f1.Conjugate(&f1) - f1a.Mul(&f1a, &f1) - - result.Mul(&result, &f1a). - Mul(&result, &f1q) + // (x₀^5-x₀^4-x₀)(p²-p+1)/r + // Algorithm 4.5 from https://yelhousni.github.io/phd.pdf + var a, b, c, d, e, f, g, h, i, t, mp GT + mp.Frobenius(&result) + a.ExptMinus1Squared(&mp) + a.ExptSquarePlus1(&a) + a.Mul(&result, &a) + t.Conjugate(&mp) + b.ExptPlus1(&a). + Mul(&b, &t) + t.CyclotomicSquare(&a). + Mul(&t, &a) + a.Conjugate(&t) + c.ExptMinus1Div3(&b) + d.ExptMinus1(&c) + d.ExptSquarePlus1(&d) + e.ExptMinus1Squared(&d) + e.ExptSquarePlus1(&e) + e.Mul(&e, &d) + f.ExptPlus1(&e). + Mul(&f, &c). + Conjugate(&f). + Mul(&f, &d) + g.Mul(&f, &d). + Conjugate(&g) + h.ExptPlus1(&g). + Mul(&h, &c). + Mul(&h, &b) + // ht = −7, hy = −1 + // c1 = (ht-hy)/2 = -3 + i.Expc1(&f). + Mul(&i, &e) + // c2 = (ht^2+3*hy^2)/4 = 13 + t.CyclotomicSquare(&i). + Mul(&t, &i). + Mul(&t, &b) + i.Expc2(&h). + Mul(&i, &t) + result.Mul(&a, &i) return result } diff --git a/ecc/bw6-761/internal/fptower/e6_pairing.go b/ecc/bw6-761/internal/fptower/e6_pairing.go index f293ea1d4..21178257e 100644 --- a/ecc/bw6-761/internal/fptower/e6_pairing.go +++ b/ecc/bw6-761/internal/fptower/e6_pairing.go @@ -131,7 +131,7 @@ func (z *E6) Expc1(x *E6) *E6 { return z } -// Expx2 set z to z^c2 in E6 and return z +// Expc2 set z to z^c2 in E6 and return z // ht, hy = 13, 9 // c2 = (ht**2+3*hy**2)/4 = 103 func (z *E6) Expc2(x *E6) *E6 {