1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // For details of the algorithms used, see "Multiplication and Squaring on
8 // Pairing-Friendly Fields, Devegili et al.
9 // http://eprint.iacr.org/2006/471.pdf.
15 // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
18 x, y, z *gfP2 // value is xτ² + yτ + z
21 func newGFp6(pool *bnPool) *gfP6 {
22 return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
25 func (e *gfP6) String() string {
26 return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
29 func (e *gfP6) Put(pool *bnPool) {
35 func (e *gfP6) Set(a *gfP6) *gfP6 {
42 func (e *gfP6) SetZero() *gfP6 {
49 func (e *gfP6) SetOne() *gfP6 {
56 func (e *gfP6) Minimal() {
62 func (e *gfP6) IsZero() bool {
63 return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
66 func (e *gfP6) IsOne() bool {
67 return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
70 func (e *gfP6) Negative(a *gfP6) *gfP6 {
77 func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
82 e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
83 e.y.Mul(e.y, xiToPMinus1Over3, pool)
87 // FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
88 func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
89 // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
90 e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
91 // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
92 e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
97 func (e *gfP6) Add(a, b *gfP6) *gfP6 {
104 func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
111 func (e *gfP6) Double(a *gfP6) *gfP6 {
118 func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
119 // "Multiplication and Squaring on Pairing-Friendly Fields"
120 // Section 4, Karatsuba method.
121 // http://eprint.iacr.org/2006/471.pdf
124 v0.Mul(a.z, b.z, pool)
126 v1.Mul(a.y, b.y, pool)
128 v2.Mul(a.x, b.x, pool)
174 func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
175 e.x.Mul(a.x, b, pool)
176 e.y.Mul(a.y, b, pool)
177 e.z.Mul(a.z, b, pool)
181 func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
182 e.x.MulScalar(a.x, b)
183 e.y.MulScalar(a.y, b)
184 e.z.MulScalar(a.z, b)
188 // MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
189 func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
201 func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
202 v0 := newGFp2(pool).Square(a.z, pool)
203 v1 := newGFp2(pool).Square(a.y, pool)
204 v2 := newGFp2(pool).Square(a.x, pool)
206 c0 := newGFp2(pool).Add(a.x, a.y)
213 c1 := newGFp2(pool).Add(a.y, a.z)
217 xiV2 := newGFp2(pool).MulXi(v2, pool)
220 c2 := newGFp2(pool).Add(a.x, a.z)
241 func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
242 // See "Implementing cryptographic pairings", M. Scott, section 3.2.
243 // ftp://136.206.11.249/pub/crypto/pairings.pdf
245 // Here we can give a short explanation of how it works: let j be a cubic root of
246 // unity in GF(p²) so that 1+j+j²=0.
247 // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
248 // = (xτ² + yτ + z)(Cτ²+Bτ+A)
249 // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
251 // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
252 // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
254 // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
259 t1.Mul(a.x, a.y, pool)
266 t1.Mul(a.y, a.z, pool)
271 t1.Mul(a.x, a.z, pool)