diff --git a/std/algebra/emulated/fields_bw6761/e6.go b/std/algebra/emulated/fields_bw6761/e6.go index 475d93475..2528891e0 100644 --- a/std/algebra/emulated/fields_bw6761/e6.go +++ b/std/algebra/emulated/fields_bw6761/e6.go @@ -853,6 +853,51 @@ func (e Ext6) squareEmulatedTower(x *E6) *E6 { } } +// Granger-Scott's cyclotomic square +// https://eprint.iacr.org/2009/565.pdf, 3.2 +func (e Ext6) CyclotomicSquareGS(x *E6) *E6 { + return e.cyclotomicSquareGSEval(x) +} + +// cyclotomicSquareGSEval computes [Ext6.CyclotomicSquareGS] but with the non-native Eval method. +func (e Ext6) cyclotomicSquareGSEval(x *E6) *E6 { + // x=(x0,x2,x4,x1,x3,x5) in E6 + // cyclosquare(x) = 3*x4²*u + 3*x0² - 2*x0, + // 6*x1*x5*u + 2*x3, + // 3*x2²*u + 3*x3² - 2*x1, + // 6*x0*x4 + 2*x4, + // 3*x5²*u + 3*x1² - 2*x2, + // 6*x2*x3 + 2*x5, + u := e.fp.NewElement(-4) + mone := e.fp.NewElement(-1) + g0 := x.A0 + g1 := x.A2 + g2 := x.A4 + g3 := x.A1 + g4 := x.A3 + g5 := x.A5 + // h0 = 3*x4²*u + 3*x0² - 2*x0 + h0 := e.fp.Eval([][]*baseEl{{u, &g4, &g4}, {&g0, &g0}, {mone, &g0}}, []int{3, 3, 2}) + // h1 = 3*x2²*u + 3*x3² - 2*x1 + h1 := e.fp.Eval([][]*baseEl{{u, &g2, &g2}, {&g3, &g3}, {mone, &g1}}, []int{3, 3, 2}) + // h2 = 3*x5²*u + 3*x1² - 2*x2 + h2 := e.fp.Eval([][]*baseEl{{u, &g5, &g5}, {&g1, &g1}, {mone, &g2}}, []int{3, 3, 2}) + // h3 = 6*x1*x5*u + 2*x3 + h3 := e.fp.Eval([][]*baseEl{{u, &g1, &g5}, {&g3}}, []int{6, 2}) + // h4 = 6*x0*x4 + 2*x4 + h4 := e.fp.Eval([][]*baseEl{{&g0, &g4}, {&g4}}, []int{6, 2}) + // h5 = 6*x2*x3 + 2*x5 + h5 := e.fp.Eval([][]*baseEl{{&g2, &g3}, {&g5}}, []int{6, 2}) + return &E6{ + A0: *h0, + A1: *h3, + A2: *h1, + A3: *h4, + A4: *h2, + A5: *h5, + } +} + // Karabina's compressed cyclotomic square SQR12345 // https://eprint.iacr.org/2010/542.pdf // Sec. 5.6 with minor modifications to fit our tower diff --git a/std/algebra/emulated/fields_bw6761/e6_pairing.go b/std/algebra/emulated/fields_bw6761/e6_pairing.go index 47a1fec18..a4a40e840 100644 --- a/std/algebra/emulated/fields_bw6761/e6_pairing.go +++ b/std/algebra/emulated/fields_bw6761/e6_pairing.go @@ -26,7 +26,7 @@ func (e Ext6) ExpX0Minus1(z *E6) *E6 { result = e.Mul(result, z33) result = e.nSquareKarabina12345(result, 4) result = e.Mul(result, z) - result = e.nSquareKarabina12345(result, 1) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) result = e.nSquareKarabina12345(result, 46) @@ -39,11 +39,11 @@ func (e Ext6) ExpX0Minus1Square(z *E6) *E6 { z = e.Reduce(z) result := e.Copy(z) result = e.nSquareKarabina12345(result, 3) - t0 := e.nSquareKarabina12345(result, 1) + t0 := e.CyclotomicSquareGS(result) t2 := e.Mul(z, t0) result = e.Mul(result, t2) t0 = e.Mul(z, result) - t1 := e.nSquareKarabina12345(t0, 1) + t1 := e.CyclotomicSquareGS(t0) t1 = e.Mul(t2, t1) t3 := e.nSquareKarabina12345(t1, 7) t2 = e.Mul(t2, t3) @@ -65,7 +65,7 @@ func (e Ext6) ExpX0Minus1Square(z *E6) *E6 { func (e Ext6) ExpX0Plus1(z *E6) *E6 { z = e.Reduce(z) result := e.Copy(z) - t := e.nSquareKarabina12345(result, 1) + t := e.CyclotomicSquareGS(result) result = e.nSquareKarabina12345(t, 4) result = e.Mul(result, z) z33 := e.Copy(result) @@ -73,7 +73,7 @@ func (e Ext6) ExpX0Plus1(z *E6) *E6 { result = e.Mul(result, z33) result = e.nSquareKarabina12345(result, 4) result = e.Mul(result, z) - result = e.nSquareKarabina12345(result, 1) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) result = e.nSquareKarabina12345(result, 46) result = e.Mul(result, t) @@ -86,9 +86,10 @@ func (e Ext6) ExpX0Plus1(z *E6) *E6 { func (e Ext6) ExptMinus1Div3(z *E6) *E6 { z = e.Reduce(z) result := e.Copy(z) - result = e.nSquareKarabina12345(result, 2) + result = e.CyclotomicSquareGS(result) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) - result = e.nSquareKarabina12345(result, 1) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) t0 := e.nSquareKarabina12345(result, 7) result = e.Mul(result, t0) @@ -105,9 +106,10 @@ func (e Ext6) ExptMinus1Div3(z *E6) *E6 { func (e Ext6) ExpC1(z *E6) *E6 { z = e.Reduce(z) result := e.Copy(z) - result = e.nSquareKarabina12345(result, 2) + result = e.CyclotomicSquareGS(result) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) - result = e.nSquareKarabina12345(result, 1) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) return result @@ -118,11 +120,11 @@ func (e Ext6) ExpC1(z *E6) *E6 { // C2 = (ht**2+3*hy**2)/4 = 103 func (e Ext6) ExpC2(z *E6) *E6 { z = e.Reduce(z) - result := e.nSquareKarabina12345(z, 1) + result := e.CyclotomicSquareGS(z) result = e.Mul(result, z) t0 := e.nSquareKarabina12345(result, 4) result = e.Mul(result, t0) - result = e.nSquareKarabina12345(result, 1) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) return result @@ -463,7 +465,7 @@ func (e Ext6) AssertFinalExponentiationIsOne(x *E6) { func (e Ext6) ExpByU2(z *E6) *E6 { z = e.Reduce(z) result := e.Copy(z) - t := e.nSquareKarabina12345(result, 1) + t := e.CyclotomicSquareGS(result) result = e.nSquareKarabina12345(t, 4) result = e.Mul(result, z) z33 := e.Copy(result) @@ -471,7 +473,7 @@ func (e Ext6) ExpByU2(z *E6) *E6 { result = e.Mul(result, z33) result = e.nSquareKarabina12345(result, 4) result = e.Mul(result, z) - result = e.nSquareKarabina12345(result, 1) + result = e.CyclotomicSquareGS(result) result = e.Mul(result, z) result = e.nSquareKarabina12345(result, 46) result = e.Mul(result, t) @@ -482,9 +484,9 @@ func (e Ext6) ExpByU2(z *E6) *E6 { // ExpByU1 set z to z^(x₀^3-x₀^2+1) in E12 and return z // x₀^3-x₀^2+1 = 880904806456922042166256752416502360965158762994674434049 func (e Ext6) ExpByU1(x *E6) *E6 { - t5 := e.nSquareKarabina12345(x, 1) + t5 := e.CyclotomicSquareGS(x) z := e.Mul(x, t5) - t0 := e.nSquareKarabina12345(z, 1) + t0 := e.CyclotomicSquareGS(z) t6 := e.Mul(x, t0) t8 := e.Mul(x, t6) t7 := e.Mul(t5, t8) @@ -493,7 +495,7 @@ func (e Ext6) ExpByU1(x *E6) *E6 { t2 := e.Mul(x, t3) t1 := e.Mul(t6, t2) t0 = e.Mul(t8, t1) - t4 := e.nSquareKarabina12345(t0, 1) + t4 := e.CyclotomicSquareGS(t0) t4 = e.Mul(z, t4) t8 = e.Mul(t8, t4) t2 = e.Mul(t2, t8)