github.com/core-coin/go-core/v2@v2.1.9/crypto/bn256/google/gfp6.go (about) 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. 4 5 package bn256 6 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. 10 11 import ( 12 "math/big" 13 ) 14 15 // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ 16 // and ξ=i+9. 17 type gfP6 struct { 18 x, y, z *gfP2 // value is xτ² + yτ + z 19 } 20 21 func newGFp6(pool *bnPool) *gfP6 { 22 return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} 23 } 24 25 func (e *gfP6) String() string { 26 return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" 27 } 28 29 func (e *gfP6) Put(pool *bnPool) { 30 e.x.Put(pool) 31 e.y.Put(pool) 32 e.z.Put(pool) 33 } 34 35 func (e *gfP6) Set(a *gfP6) *gfP6 { 36 e.x.Set(a.x) 37 e.y.Set(a.y) 38 e.z.Set(a.z) 39 return e 40 } 41 42 func (e *gfP6) SetZero() *gfP6 { 43 e.x.SetZero() 44 e.y.SetZero() 45 e.z.SetZero() 46 return e 47 } 48 49 func (e *gfP6) SetOne() *gfP6 { 50 e.x.SetZero() 51 e.y.SetZero() 52 e.z.SetOne() 53 return e 54 } 55 56 func (e *gfP6) Minimal() { 57 e.x.Minimal() 58 e.y.Minimal() 59 e.z.Minimal() 60 } 61 62 func (e *gfP6) IsZero() bool { 63 return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() 64 } 65 66 func (e *gfP6) IsOne() bool { 67 return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() 68 } 69 70 func (e *gfP6) Negative(a *gfP6) *gfP6 { 71 e.x.Negative(a.x) 72 e.y.Negative(a.y) 73 e.z.Negative(a.z) 74 return e 75 } 76 77 func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { 78 e.x.Conjugate(a.x) 79 e.y.Conjugate(a.y) 80 e.z.Conjugate(a.z) 81 82 e.x.Mul(e.x, xiTo2PMinus2Over3, pool) 83 e.y.Mul(e.y, xiToPMinus1Over3, pool) 84 return e 85 } 86 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) 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) Double(a *gfP6) *gfP6 { 112 e.x.Double(a.x) 113 e.y.Double(a.y) 114 e.z.Double(a.z) 115 return e 116 } 117 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 122 123 v0 := newGFp2(pool) 124 v0.Mul(a.z, b.z, pool) 125 v1 := newGFp2(pool) 126 v1.Mul(a.y, b.y, pool) 127 v2 := newGFp2(pool) 128 v2.Mul(a.x, b.x, pool) 129 130 t0 := newGFp2(pool) 131 t0.Add(a.x, a.y) 132 t1 := newGFp2(pool) 133 t1.Add(b.x, b.y) 134 tz := newGFp2(pool) 135 tz.Mul(t0, t1, pool) 136 137 tz.Sub(tz, v1) 138 tz.Sub(tz, v2) 139 tz.MulXi(tz, pool) 140 tz.Add(tz, v0) 141 142 t0.Add(a.y, a.z) 143 t1.Add(b.y, b.z) 144 ty := newGFp2(pool) 145 ty.Mul(t0, t1, pool) 146 ty.Sub(ty, v0) 147 ty.Sub(ty, v1) 148 t0.MulXi(v2, pool) 149 ty.Add(ty, t0) 150 151 t0.Add(a.x, a.z) 152 t1.Add(b.x, b.z) 153 tx := newGFp2(pool) 154 tx.Mul(t0, t1, pool) 155 tx.Sub(tx, v0) 156 tx.Add(tx, v1) 157 tx.Sub(tx, v2) 158 159 e.x.Set(tx) 160 e.y.Set(ty) 161 e.z.Set(tz) 162 163 t0.Put(pool) 164 t1.Put(pool) 165 tx.Put(pool) 166 ty.Put(pool) 167 tz.Put(pool) 168 v0.Put(pool) 169 v1.Put(pool) 170 v2.Put(pool) 171 return e 172 } 173 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) 178 return e 179 } 180 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) 185 return e 186 } 187 188 // MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ 189 func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { 190 tz := newGFp2(pool) 191 tz.MulXi(a.x, pool) 192 ty := newGFp2(pool) 193 ty.Set(a.y) 194 e.y.Set(a.z) 195 e.x.Set(ty) 196 e.z.Set(tz) 197 tz.Put(pool) 198 ty.Put(pool) 199 } 200 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) 205 206 c0 := newGFp2(pool).Add(a.x, a.y) 207 c0.Square(c0, pool) 208 c0.Sub(c0, v1) 209 c0.Sub(c0, v2) 210 c0.MulXi(c0, pool) 211 c0.Add(c0, v0) 212 213 c1 := newGFp2(pool).Add(a.y, a.z) 214 c1.Square(c1, pool) 215 c1.Sub(c1, v0) 216 c1.Sub(c1, v1) 217 xiV2 := newGFp2(pool).MulXi(v2, pool) 218 c1.Add(c1, xiV2) 219 220 c2 := newGFp2(pool).Add(a.x, a.z) 221 c2.Square(c2, pool) 222 c2.Sub(c2, v0) 223 c2.Add(c2, v1) 224 c2.Sub(c2, v2) 225 226 e.x.Set(c2) 227 e.y.Set(c1) 228 e.z.Set(c0) 229 230 v0.Put(pool) 231 v1.Put(pool) 232 v2.Put(pool) 233 c0.Put(pool) 234 c1.Put(pool) 235 c2.Put(pool) 236 xiV2.Put(pool) 237 238 return e 239 } 240 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 244 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). 250 // 251 // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 252 // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) 253 // 254 // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) 255 t1 := newGFp2(pool) 256 257 A := newGFp2(pool) 258 A.Square(a.z, pool) 259 t1.Mul(a.x, a.y, pool) 260 t1.MulXi(t1, pool) 261 A.Sub(A, t1) 262 263 B := newGFp2(pool) 264 B.Square(a.x, pool) 265 B.MulXi(B, pool) 266 t1.Mul(a.y, a.z, pool) 267 B.Sub(B, t1) 268 269 C_ := newGFp2(pool) 270 C_.Square(a.y, pool) 271 t1.Mul(a.x, a.z, pool) 272 C_.Sub(C_, t1) 273 274 F := newGFp2(pool) 275 F.Mul(C_, a.y, pool) 276 F.MulXi(F, pool) 277 t1.Mul(A, a.z, pool) 278 F.Add(F, t1) 279 t1.Mul(B, a.x, pool) 280 t1.MulXi(t1, pool) 281 F.Add(F, t1) 282 283 F.Invert(F, pool) 284 285 e.x.Mul(C_, F, pool) 286 e.y.Mul(B, F, pool) 287 e.z.Mul(A, F, pool) 288 289 t1.Put(pool) 290 A.Put(pool) 291 B.Put(pool) 292 C_.Put(pool) 293 F.Put(pool) 294 295 return e 296 }