github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-315/internal/fptower/e4.go (about) 1 // Copyright 2020 ConsenSys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fptower 16 17 import ( 18 "math/big" 19 20 "github.com/consensys/gnark-crypto/ecc/bls24-315/fp" 21 ) 22 23 // E4 is a degree two finite field extension of fp2 24 type E4 struct { 25 B0, B1 E2 26 } 27 28 // Equal returns true if z equals x, false otherwise 29 func (z *E4) Equal(x *E4) bool { 30 return z.B0.Equal(&x.B0) && z.B1.Equal(&x.B1) 31 } 32 33 // Cmp compares (lexicographic order) z and x and returns: 34 // 35 // -1 if z < x 36 // 0 if z == x 37 // +1 if z > x 38 func (z *E4) Cmp(x *E4) int { 39 if a1 := z.B1.Cmp(&x.B1); a1 != 0 { 40 return a1 41 } 42 return z.B0.Cmp(&x.B0) 43 } 44 45 // LexicographicallyLargest returns true if this element is strictly lexicographically 46 // larger than its negation, false otherwise 47 func (z *E4) LexicographicallyLargest() bool { 48 // adapted from github.com/zkcrypto/bls12_381 49 if z.B1.IsZero() { 50 return z.B0.LexicographicallyLargest() 51 } 52 return z.B1.LexicographicallyLargest() 53 } 54 55 // String puts E4 in string form 56 func (z *E4) String() string { 57 return (z.B0.String() + "+(" + z.B1.String() + ")*v") 58 } 59 60 // SetString sets a E4 from string 61 func (z *E4) SetString(s0, s1, s2, s3 string) *E4 { 62 z.B0.SetString(s0, s1) 63 z.B1.SetString(s2, s3) 64 return z 65 } 66 67 // Set copies x into z and returns z 68 func (z *E4) Set(x *E4) *E4 { 69 z.B0 = x.B0 70 z.B1 = x.B1 71 return z 72 } 73 74 // SetZero sets an E4 elmt to zero 75 func (z *E4) SetZero() *E4 { 76 z.B0.SetZero() 77 z.B1.SetZero() 78 return z 79 } 80 81 // SetOne sets z to 1 in Montgomery form and returns z 82 func (z *E4) SetOne() *E4 { 83 *z = E4{} 84 z.B0.A0.SetOne() 85 return z 86 } 87 88 // MulByElement multiplies an element in E4 by an element in fp 89 func (z *E4) MulByElement(x *E4, y *fp.Element) *E4 { 90 var yCopy fp.Element 91 yCopy.Set(y) 92 z.B0.MulByElement(&x.B0, &yCopy) 93 z.B1.MulByElement(&x.B1, &yCopy) 94 return z 95 } 96 97 // Add set z=x+y in E4 and return z 98 func (z *E4) Add(x, y *E4) *E4 { 99 z.B0.Add(&x.B0, &y.B0) 100 z.B1.Add(&x.B1, &y.B1) 101 return z 102 } 103 104 // Sub sets z to x sub y and return z 105 func (z *E4) Sub(x, y *E4) *E4 { 106 z.B0.Sub(&x.B0, &y.B0) 107 z.B1.Sub(&x.B1, &y.B1) 108 return z 109 } 110 111 // Double sets z=2*x and returns z 112 func (z *E4) Double(x *E4) *E4 { 113 z.B0.Double(&x.B0) 114 z.B1.Double(&x.B1) 115 return z 116 } 117 118 // Neg negates an E4 element 119 func (z *E4) Neg(x *E4) *E4 { 120 z.B0.Neg(&x.B0) 121 z.B1.Neg(&x.B1) 122 return z 123 } 124 125 // SetRandom used only in tests 126 func (z *E4) SetRandom() (*E4, error) { 127 if _, err := z.B0.SetRandom(); err != nil { 128 return nil, err 129 } 130 if _, err := z.B1.SetRandom(); err != nil { 131 return nil, err 132 } 133 return z, nil 134 } 135 136 // IsZero returns true if z is zero, false otherwise 137 func (z *E4) IsZero() bool { 138 return z.B0.IsZero() && z.B1.IsZero() 139 } 140 141 // IsOne returns true if z is one, false otherwise 142 func (z *E4) IsOne() bool { 143 return z.B0.IsOne() && z.B1.IsZero() 144 } 145 146 // MulByNonResidue mul x by (0,1) 147 func (z *E4) MulByNonResidue(x *E4) *E4 { 148 z.B1, z.B0 = x.B0, x.B1 149 z.B0.MulByNonResidue(&z.B0) 150 return z 151 } 152 153 // MulByNonResidueInv mul x by (0,1)^{-1} 154 func (z *E4) MulByNonResidueInv(x *E4) *E4 { 155 a := x.B1 156 var uInv E2 157 uInv.A1.SetString("6108483493771298205388567675447533806912846525679192205394505462405828322019437284165171866703") 158 z.B1.Mul(&x.B0, &uInv) 159 z.B0 = a 160 return z 161 } 162 163 // Mul set z=x*y in E4 and return z 164 func (z *E4) Mul(x, y *E4) *E4 { 165 var a, b, c E2 166 a.Add(&x.B0, &x.B1) 167 b.Add(&y.B0, &y.B1) 168 a.Mul(&a, &b) 169 b.Mul(&x.B0, &y.B0) 170 c.Mul(&x.B1, &y.B1) 171 z.B1.Sub(&a, &b).Sub(&z.B1, &c) 172 z.B0.MulByNonResidue(&c).Add(&z.B0, &b) 173 return z 174 } 175 176 // Square set z=x*x in E4 and return z 177 func (z *E4) Square(x *E4) *E4 { 178 179 //Algorithm 22 from https://eprint.iacr.org/2010/354.pdf 180 var c0, c2, c3 E2 181 c0.Sub(&x.B0, &x.B1) 182 c3.MulByNonResidue(&x.B1).Sub(&x.B0, &c3) 183 c2.Mul(&x.B0, &x.B1) 184 c0.Mul(&c0, &c3).Add(&c0, &c2) 185 z.B1.Double(&c2) 186 c2.MulByNonResidue(&c2) 187 z.B0.Add(&c0, &c2) 188 189 return z 190 } 191 192 // Inverse set z to the inverse of x in E4 and return z 193 // 194 // if x == 0, sets and returns z = x 195 func (z *E4) Inverse(x *E4) *E4 { 196 // Algorithm 23 from https://eprint.iacr.org/2010/354.pdf 197 198 var t0, t1, tmp E2 199 t0.Square(&x.B0) 200 t1.Square(&x.B1) 201 tmp.MulByNonResidue(&t1) 202 t0.Sub(&t0, &tmp) 203 t1.Inverse(&t0) 204 z.B0.Mul(&x.B0, &t1) 205 z.B1.Mul(&x.B1, &t1).Neg(&z.B1) 206 207 return z 208 } 209 210 // Exp sets z=xᵏ (mod q⁴) and returns it 211 func (z *E4) Exp(x E4, k *big.Int) *E4 { 212 if k.IsUint64() && k.Uint64() == 0 { 213 return z.SetOne() 214 } 215 216 e := k 217 if k.Sign() == -1 { 218 // negative k, we invert 219 // if k < 0: xᵏ (mod q⁴) == (x⁻¹)ᵏ (mod q⁴) 220 x.Inverse(&x) 221 222 // we negate k in a temp big.Int since 223 // Int.Bit(_) of k and -k is different 224 e = bigIntPool.Get().(*big.Int) 225 defer bigIntPool.Put(e) 226 e.Neg(k) 227 } 228 229 z.SetOne() 230 b := e.Bytes() 231 for i := 0; i < len(b); i++ { 232 w := b[i] 233 for j := 0; j < 8; j++ { 234 z.Square(z) 235 if (w & (0b10000000 >> j)) != 0 { 236 z.Mul(z, &x) 237 } 238 } 239 } 240 241 return z 242 } 243 244 // Conjugate set z to x conjugated and return z 245 func (z *E4) Conjugate(x *E4) *E4 { 246 z.B0 = x.B0 247 z.B1.Neg(&x.B1) 248 return z 249 } 250 251 func (z *E4) Halve() { 252 253 z.B0.A0.Halve() 254 z.B0.A1.Halve() 255 z.B1.A0.Halve() 256 z.B1.A1.Halve() 257 } 258 259 // norm sets x to the norm of z 260 func (z *E4) norm(x *E2) { 261 var tmp E2 262 tmp.Square(&z.B1).MulByNonResidue(&tmp) 263 x.Square(&z.B0).Sub(x, &tmp) 264 } 265 266 // Legendre returns the Legendre symbol of z 267 func (z *E4) Legendre() int { 268 var n E2 269 z.norm(&n) 270 return n.Legendre() 271 } 272 273 // Sqrt sets z to the square root of and returns z 274 // The function does not test whether the square root 275 // exists or not, it's up to the caller to call 276 // Legendre beforehand. 277 // cf https://eprint.iacr.org/2012/685.pdf (algo 10) 278 func (z *E4) Sqrt(x *E4) *E4 { 279 280 // precomputation 281 var b, c, d, e, f, x0, _g E4 282 var _b, o E2 283 284 // c must be a non square (works for p=1 mod 12 hence 1 mod 4, only bls377 has such a p currently) 285 c.B1.SetOne() 286 287 q := fp.Modulus() 288 var exp, one big.Int 289 one.SetUint64(1) 290 exp.Mul(q, q).Sub(&exp, &one).Rsh(&exp, 1) 291 d.Exp(c, &exp) 292 e.Mul(&d, &c).Inverse(&e) 293 f.Mul(&d, &c).Square(&f) 294 295 // computation 296 exp.Rsh(&exp, 1) 297 b.Exp(*x, &exp) 298 b.norm(&_b) 299 o.SetOne() 300 if _b.Equal(&o) { 301 x0.Square(&b).Mul(&x0, x) 302 _b.Set(&x0.B0).Sqrt(&_b) 303 _g.B0.Set(&_b) 304 z.Conjugate(&b).Mul(z, &_g) 305 return z 306 } 307 x0.Square(&b).Mul(&x0, x).Mul(&x0, &f) 308 _b.Set(&x0.B0).Sqrt(&_b) 309 _g.B0.Set(&_b) 310 z.Conjugate(&b).Mul(z, &_g).Mul(z, &e) 311 312 return z 313 } 314 315 // BatchInvertE4 returns a new slice with every element inverted. 316 // Uses Montgomery batch inversion trick 317 // 318 // if a[i] == 0, returns result[i] = a[i] 319 func BatchInvertE4(a []E4) []E4 { 320 res := make([]E4, len(a)) 321 if len(a) == 0 { 322 return res 323 } 324 325 zeroes := make([]bool, len(a)) 326 var accumulator E4 327 accumulator.SetOne() 328 329 for i := 0; i < len(a); i++ { 330 if a[i].IsZero() { 331 zeroes[i] = true 332 continue 333 } 334 res[i].Set(&accumulator) 335 accumulator.Mul(&accumulator, &a[i]) 336 } 337 338 accumulator.Inverse(&accumulator) 339 340 for i := len(a) - 1; i >= 0; i-- { 341 if zeroes[i] { 342 continue 343 } 344 res[i].Mul(&res[i], &accumulator) 345 accumulator.Mul(&accumulator, &a[i]) 346 } 347 348 return res 349 } 350 351 func (z *E4) Div(x *E4, y *E4) *E4 { 352 var r E4 353 r.Inverse(y).Mul(x, &r) 354 return z.Set(&r) 355 }