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