github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/cloudflare/gfp6.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package bn256 19 20 // For details of the algorithms used, see "Multiplication and Squaring on 21 // Pairing-Friendly Fields, Devegili et al. 22 // http://eprint.iacr.org/2006/471.pdf. 23 24 // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ 25 // and ξ=i+9. 26 type gfP6 struct { 27 x, y, z gfP2 // value is xτ² + yτ + z 28 } 29 30 func (e *gfP6) String() string { 31 return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" 32 } 33 34 func (e *gfP6) Set(a *gfP6) *gfP6 { 35 e.x.Set(&a.x) 36 e.y.Set(&a.y) 37 e.z.Set(&a.z) 38 return e 39 } 40 41 func (e *gfP6) SetZero() *gfP6 { 42 e.x.SetZero() 43 e.y.SetZero() 44 e.z.SetZero() 45 return e 46 } 47 48 func (e *gfP6) SetOne() *gfP6 { 49 e.x.SetZero() 50 e.y.SetZero() 51 e.z.SetOne() 52 return e 53 } 54 55 func (e *gfP6) IsZero() bool { 56 return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() 57 } 58 59 func (e *gfP6) IsOne() bool { 60 return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() 61 } 62 63 func (e *gfP6) Neg(a *gfP6) *gfP6 { 64 e.x.Neg(&a.x) 65 e.y.Neg(&a.y) 66 e.z.Neg(&a.z) 67 return e 68 } 69 70 func (e *gfP6) Frobenius(a *gfP6) *gfP6 { 71 e.x.Conjugate(&a.x) 72 e.y.Conjugate(&a.y) 73 e.z.Conjugate(&a.z) 74 75 e.x.Mul(&e.x, xiTo2PMinus2Over3) 76 e.y.Mul(&e.y, xiToPMinus1Over3) 77 return e 78 } 79 80 // FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z 81 func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { 82 // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) 83 e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3) 84 // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) 85 e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3) 86 e.z.Set(&a.z) 87 return e 88 } 89 90 func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 { 91 e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) 92 e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3) 93 e.z.Set(&a.z) 94 return e 95 } 96 97 func (e *gfP6) Add(a, b *gfP6) *gfP6 { 98 e.x.Add(&a.x, &b.x) 99 e.y.Add(&a.y, &b.y) 100 e.z.Add(&a.z, &b.z) 101 return e 102 } 103 104 func (e *gfP6) Sub(a, b *gfP6) *gfP6 { 105 e.x.Sub(&a.x, &b.x) 106 e.y.Sub(&a.y, &b.y) 107 e.z.Sub(&a.z, &b.z) 108 return e 109 } 110 111 func (e *gfP6) Mul(a, b *gfP6) *gfP6 { 112 // "Multiplication and Squaring on Pairing-Friendly Fields" 113 // Section 4, Karatsuba method. 114 // http://eprint.iacr.org/2006/471.pdf 115 v0 := (&gfP2{}).Mul(&a.z, &b.z) 116 v1 := (&gfP2{}).Mul(&a.y, &b.y) 117 v2 := (&gfP2{}).Mul(&a.x, &b.x) 118 119 t0 := (&gfP2{}).Add(&a.x, &a.y) 120 t1 := (&gfP2{}).Add(&b.x, &b.y) 121 tz := (&gfP2{}).Mul(t0, t1) 122 tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0) 123 124 t0.Add(&a.y, &a.z) 125 t1.Add(&b.y, &b.z) 126 ty := (&gfP2{}).Mul(t0, t1) 127 t0.MulXi(v2) 128 ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0) 129 130 t0.Add(&a.x, &a.z) 131 t1.Add(&b.x, &b.z) 132 tx := (&gfP2{}).Mul(t0, t1) 133 tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2) 134 135 e.x.Set(tx) 136 e.y.Set(ty) 137 e.z.Set(tz) 138 return e 139 } 140 141 func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 { 142 e.x.Mul(&a.x, b) 143 e.y.Mul(&a.y, b) 144 e.z.Mul(&a.z, b) 145 return e 146 } 147 148 func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 { 149 e.x.MulScalar(&a.x, b) 150 e.y.MulScalar(&a.y, b) 151 e.z.MulScalar(&a.z, b) 152 return e 153 } 154 155 // MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ 156 func (e *gfP6) MulTau(a *gfP6) *gfP6 { 157 tz := (&gfP2{}).MulXi(&a.x) 158 ty := (&gfP2{}).Set(&a.y) 159 160 e.y.Set(&a.z) 161 e.x.Set(ty) 162 e.z.Set(tz) 163 return e 164 } 165 166 func (e *gfP6) Square(a *gfP6) *gfP6 { 167 v0 := (&gfP2{}).Square(&a.z) 168 v1 := (&gfP2{}).Square(&a.y) 169 v2 := (&gfP2{}).Square(&a.x) 170 171 c0 := (&gfP2{}).Add(&a.x, &a.y) 172 c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0) 173 174 c1 := (&gfP2{}).Add(&a.y, &a.z) 175 c1.Square(c1).Sub(c1, v0).Sub(c1, v1) 176 xiV2 := (&gfP2{}).MulXi(v2) 177 c1.Add(c1, xiV2) 178 179 c2 := (&gfP2{}).Add(&a.x, &a.z) 180 c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2) 181 182 e.x.Set(c2) 183 e.y.Set(c1) 184 e.z.Set(c0) 185 return e 186 } 187 188 func (e *gfP6) Invert(a *gfP6) *gfP6 { 189 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 190 // ftp://136.206.11.249/pub/crypto/pairings.pdf 191 192 // Here we can give a short explanation of how it works: let j be a cubic root of 193 // unity in GF(p²) so that 1+j+j²=0. 194 // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 195 // = (xτ² + yτ + z)(Cτ²+Bτ+A) 196 // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). 197 // 198 // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 199 // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) 200 // 201 // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) 202 t1 := (&gfP2{}).Mul(&a.x, &a.y) 203 t1.MulXi(t1) 204 205 A := (&gfP2{}).Square(&a.z) 206 A.Sub(A, t1) 207 208 B := (&gfP2{}).Square(&a.x) 209 B.MulXi(B) 210 t1.Mul(&a.y, &a.z) 211 B.Sub(B, t1) 212 213 C := (&gfP2{}).Square(&a.y) 214 t1.Mul(&a.x, &a.z) 215 C.Sub(C, t1) 216 217 F := (&gfP2{}).Mul(C, &a.y) 218 F.MulXi(F) 219 t1.Mul(A, &a.z) 220 F.Add(F, t1) 221 t1.Mul(B, &a.x).MulXi(t1) 222 F.Add(F, t1) 223 224 F.Invert(F) 225 226 e.x.Mul(C, F) 227 e.y.Mul(B, F) 228 e.z.Mul(A, F) 229 return e 230 }