github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/internal/fptower/e12.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 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package fptower 18 19 import ( 20 "errors" 21 "github.com/consensys/gnark-crypto/ecc" 22 "github.com/consensys/gnark-crypto/ecc/bls12-378/fp" 23 "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" 24 "math/big" 25 "sync" 26 ) 27 28 var bigIntPool = sync.Pool{ 29 New: func() interface{} { 30 return new(big.Int) 31 }, 32 } 33 34 // E12 is a degree two finite field extension of fp6 35 type E12 struct { 36 C0, C1 E6 37 } 38 39 // Equal returns true if z equals x, false otherwise 40 func (z *E12) Equal(x *E12) bool { 41 return z.C0.Equal(&x.C0) && z.C1.Equal(&x.C1) 42 } 43 44 // String puts E12 in string form 45 func (z *E12) String() string { 46 return (z.C0.String() + "+(" + z.C1.String() + ")*w") 47 } 48 49 // SetString sets a E12 from string 50 func (z *E12) SetString(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 string) *E12 { 51 z.C0.SetString(s0, s1, s2, s3, s4, s5) 52 z.C1.SetString(s6, s7, s8, s9, s10, s11) 53 return z 54 } 55 56 // Set copies x into z and returns z 57 func (z *E12) Set(x *E12) *E12 { 58 z.C0 = x.C0 59 z.C1 = x.C1 60 return z 61 } 62 63 // SetOne sets z to 1 in Montgomery form and returns z 64 func (z *E12) SetOne() *E12 { 65 *z = E12{} 66 z.C0.B0.A0.SetOne() 67 return z 68 } 69 70 // Add sets z=x+y in E12 and returns z 71 func (z *E12) Add(x, y *E12) *E12 { 72 z.C0.Add(&x.C0, &y.C0) 73 z.C1.Add(&x.C1, &y.C1) 74 return z 75 } 76 77 // Sub sets z to x-y and returns z 78 func (z *E12) Sub(x, y *E12) *E12 { 79 z.C0.Sub(&x.C0, &y.C0) 80 z.C1.Sub(&x.C1, &y.C1) 81 return z 82 } 83 84 // Double sets z=2*x and returns z 85 func (z *E12) Double(x *E12) *E12 { 86 z.C0.Double(&x.C0) 87 z.C1.Double(&x.C1) 88 return z 89 } 90 91 // SetRandom used only in tests 92 func (z *E12) SetRandom() (*E12, error) { 93 if _, err := z.C0.SetRandom(); err != nil { 94 return nil, err 95 } 96 if _, err := z.C1.SetRandom(); err != nil { 97 return nil, err 98 } 99 return z, nil 100 } 101 102 // IsZero returns true if z is zero, false otherwise 103 func (z *E12) IsZero() bool { 104 return z.C0.IsZero() && z.C1.IsZero() 105 } 106 107 // IsOne returns true if z is one, false otherwise 108 func (z *E12) IsOne() bool { 109 return z.C0.IsOne() && z.C1.IsZero() 110 } 111 112 // Mul sets z=x*y in E12 and returns z 113 func (z *E12) Mul(x, y *E12) *E12 { 114 var a, b, c E6 115 a.Add(&x.C0, &x.C1) 116 b.Add(&y.C0, &y.C1) 117 a.Mul(&a, &b) 118 b.Mul(&x.C0, &y.C0) 119 c.Mul(&x.C1, &y.C1) 120 z.C1.Sub(&a, &b).Sub(&z.C1, &c) 121 z.C0.MulByNonResidue(&c).Add(&z.C0, &b) 122 return z 123 } 124 125 // Square sets z=x*x in E12 and returns z 126 func (z *E12) Square(x *E12) *E12 { 127 128 //Algorithm 22 from https://eprint.iacr.org/2010/354.pdf 129 var c0, c2, c3 E6 130 c0.Sub(&x.C0, &x.C1) 131 c3.MulByNonResidue(&x.C1).Neg(&c3).Add(&x.C0, &c3) 132 c2.Mul(&x.C0, &x.C1) 133 c0.Mul(&c0, &c3).Add(&c0, &c2) 134 z.C1.Double(&c2) 135 c2.MulByNonResidue(&c2) 136 z.C0.Add(&c0, &c2) 137 138 return z 139 } 140 141 // Karabina's compressed cyclotomic square 142 // https://eprint.iacr.org/2010/542.pdf 143 // Th. 3.2 with minor modifications to fit our tower 144 func (z *E12) CyclotomicSquareCompressed(x *E12) *E12 { 145 146 var t [7]E2 147 148 // t0 = g1^2 149 t[0].Square(&x.C0.B1) 150 // t1 = g5^2 151 t[1].Square(&x.C1.B2) 152 // t5 = g1 + g5 153 t[5].Add(&x.C0.B1, &x.C1.B2) 154 // t2 = (g1 + g5)^2 155 t[2].Square(&t[5]) 156 157 // t3 = g1^2 + g5^2 158 t[3].Add(&t[0], &t[1]) 159 // t5 = 2 * g1 * g5 160 t[5].Sub(&t[2], &t[3]) 161 162 // t6 = g3 + g2 163 t[6].Add(&x.C1.B0, &x.C0.B2) 164 // t3 = (g3 + g2)^2 165 t[3].Square(&t[6]) 166 // t2 = g3^2 167 t[2].Square(&x.C1.B0) 168 169 // t6 = 2 * nr * g1 * g5 170 t[6].MulByNonResidue(&t[5]) 171 // t5 = 4 * nr * g1 * g5 + 2 * g3 172 t[5].Add(&t[6], &x.C1.B0). 173 Double(&t[5]) 174 // z3 = 6 * nr * g1 * g5 + 2 * g3 175 z.C1.B0.Add(&t[5], &t[6]) 176 177 // t4 = nr * g5^2 178 t[4].MulByNonResidue(&t[1]) 179 // t5 = nr * g5^2 + g1^2 180 t[5].Add(&t[0], &t[4]) 181 // t6 = nr * g5^2 + g1^2 - g2 182 t[6].Sub(&t[5], &x.C0.B2) 183 184 // t1 = g2^2 185 t[1].Square(&x.C0.B2) 186 187 // t6 = 2 * nr * g5^2 + 2 * g1^2 - 2*g2 188 t[6].Double(&t[6]) 189 // z2 = 3 * nr * g5^2 + 3 * g1^2 - 2*g2 190 z.C0.B2.Add(&t[6], &t[5]) 191 192 // t4 = nr * g2^2 193 t[4].MulByNonResidue(&t[1]) 194 // t5 = g3^2 + nr * g2^2 195 t[5].Add(&t[2], &t[4]) 196 // t6 = g3^2 + nr * g2^2 - g1 197 t[6].Sub(&t[5], &x.C0.B1) 198 // t6 = 2 * g3^2 + 2 * nr * g2^2 - 2 * g1 199 t[6].Double(&t[6]) 200 // z1 = 3 * g3^2 + 3 * nr * g2^2 - 2 * g1 201 z.C0.B1.Add(&t[6], &t[5]) 202 203 // t0 = g2^2 + g3^2 204 t[0].Add(&t[2], &t[1]) 205 // t5 = 2 * g3 * g2 206 t[5].Sub(&t[3], &t[0]) 207 // t6 = 2 * g3 * g2 + g5 208 t[6].Add(&t[5], &x.C1.B2) 209 // t6 = 4 * g3 * g2 + 2 * g5 210 t[6].Double(&t[6]) 211 // z5 = 6 * g3 * g2 + 2 * g5 212 z.C1.B2.Add(&t[5], &t[6]) 213 214 return z 215 } 216 217 // DecompressKarabina Karabina's cyclotomic square result 218 // if g3 != 0 219 // 220 // g4 = (E * g5^2 + 3 * g1^2 - 2 * g2)/4g3 221 // 222 // if g3 == 0 223 // 224 // g4 = 2g1g5/g2 225 // 226 // if g3=g2=0 then g4=g5=g1=0 and g0=1 (x=1) 227 // Theorem 3.1 is well-defined for all x in Gϕₙ\{1} 228 func (z *E12) DecompressKarabina(x *E12) *E12 { 229 230 var t [3]E2 231 var one E2 232 one.SetOne() 233 234 if x.C1.B2.IsZero() /* g3 == 0 */ { 235 t[0].Mul(&x.C0.B1, &x.C1.B2). 236 Double(&t[0]) 237 // t1 = g2 238 t[1].Set(&x.C0.B2) 239 240 if t[1].IsZero() /* g2 == g3 == 0 */ { 241 return z.SetOne() 242 } 243 } else /* g3 != 0 */ { 244 245 // t0 = g1^2 246 t[0].Square(&x.C0.B1) 247 // t1 = 3 * g1^2 - 2 * g2 248 t[1].Sub(&t[0], &x.C0.B2). 249 Double(&t[1]). 250 Add(&t[1], &t[0]) 251 // t0 = E * g5^2 + t1 252 t[2].Square(&x.C1.B2) 253 t[0].MulByNonResidue(&t[2]). 254 Add(&t[0], &t[1]) 255 // t1 = 4 * g3 256 t[1].Double(&x.C1.B0). 257 Double(&t[1]) 258 } 259 260 // z4 = g4 261 z.C1.B1.Div(&t[0], &t[1]) // costly 262 263 // t1 = g2 * g1 264 t[1].Mul(&x.C0.B2, &x.C0.B1) 265 // t2 = 2 * g4^2 - 3 * g2 * g1 266 t[2].Square(&z.C1.B1). 267 Sub(&t[2], &t[1]). 268 Double(&t[2]). 269 Sub(&t[2], &t[1]) 270 // t1 = g3 * g5 (g3 can be 0) 271 t[1].Mul(&x.C1.B0, &x.C1.B2) 272 // c_0 = E * (2 * g4^2 + g3 * g5 - 3 * g2 * g1) + 1 273 t[2].Add(&t[2], &t[1]) 274 z.C0.B0.MulByNonResidue(&t[2]). 275 Add(&z.C0.B0, &one) 276 277 z.C0.B1.Set(&x.C0.B1) 278 z.C0.B2.Set(&x.C0.B2) 279 z.C1.B0.Set(&x.C1.B0) 280 z.C1.B2.Set(&x.C1.B2) 281 282 return z 283 } 284 285 // BatchDecompressKarabina multiple Karabina's cyclotomic square results 286 // if g3 != 0 287 // 288 // g4 = (E * g5^2 + 3 * g1^2 - 2 * g2)/4g3 289 // 290 // if g3 == 0 291 // 292 // g4 = 2g1g5/g2 293 // 294 // if g3=g2=0 then g4=g5=g1=0 and g0=1 (x=1) 295 // Theorem 3.1 is well-defined for all x in Gϕₙ\{1} 296 // 297 // Divisions by 4g3 or g2 is batched using Montgomery batch inverse 298 func BatchDecompressKarabina(x []E12) []E12 { 299 300 n := len(x) 301 if n == 0 { 302 return x 303 } 304 305 t0 := make([]E2, n) 306 t1 := make([]E2, n) 307 t2 := make([]E2, n) 308 zeroes := make([]bool, n) 309 310 var one E2 311 one.SetOne() 312 313 for i := 0; i < n; i++ { 314 if x[i].C1.B2.IsZero() /* g3 == 0 */ { 315 t0[i].Mul(&x[i].C0.B1, &x[i].C1.B2). 316 Double(&t0[i]) 317 // t1 = g2 318 t1[i].Set(&x[i].C0.B2) 319 320 if t1[i].IsZero() /* g3 == g2 == 0 */ { 321 x[i].SetOne() 322 zeroes[i] = true 323 continue 324 } 325 } else /* g3 != 0 */ { 326 // t0 = g1^2 327 t0[i].Square(&x[i].C0.B1) 328 // t1 = 3 * g1^2 - 2 * g2 329 t1[i].Sub(&t0[i], &x[i].C0.B2). 330 Double(&t1[i]). 331 Add(&t1[i], &t0[i]) 332 // t0 = E * g5^2 + t1 333 t2[i].Square(&x[i].C1.B2) 334 t0[i].MulByNonResidue(&t2[i]). 335 Add(&t0[i], &t1[i]) 336 // t1 = 4 * g3 337 t1[i].Double(&x[i].C1.B0). 338 Double(&t1[i]) 339 } 340 } 341 342 t1 = BatchInvertE2(t1) // costs 1 inverse 343 344 for i := 0; i < n; i++ { 345 if zeroes[i] { 346 continue 347 } 348 349 // z4 = g4 350 x[i].C1.B1.Mul(&t0[i], &t1[i]) 351 352 // t1 = g2 * g1 353 t1[i].Mul(&x[i].C0.B2, &x[i].C0.B1) 354 // t2 = 2 * g4^2 - 3 * g2 * g1 355 t2[i].Square(&x[i].C1.B1) 356 t2[i].Sub(&t2[i], &t1[i]) 357 t2[i].Double(&t2[i]) 358 t2[i].Sub(&t2[i], &t1[i]) 359 360 // t1 = g3 * g5 (g3s can be 0s) 361 t1[i].Mul(&x[i].C1.B0, &x[i].C1.B2) 362 // z0 = E * (2 * g4^2 + g3 * g5 - 3 * g2 * g1) + 1 363 t2[i].Add(&t2[i], &t1[i]) 364 x[i].C0.B0.MulByNonResidue(&t2[i]). 365 Add(&x[i].C0.B0, &one) 366 } 367 368 return x 369 } 370 371 // Granger-Scott's cyclotomic square 372 // https://eprint.iacr.org/2009/565.pdf, 3.2 373 func (z *E12) CyclotomicSquare(x *E12) *E12 { 374 375 // x=(x0,x1,x2,x3,x4,x5,x6,x7) in E2^6 376 // cyclosquare(x)=(3*x4^2*u + 3*x0^2 - 2*x0, 377 // 3*x2^2*u + 3*x3^2 - 2*x1, 378 // 3*x5^2*u + 3*x1^2 - 2*x2, 379 // 6*x1*x5*u + 2*x3, 380 // 6*x0*x4 + 2*x4, 381 // 6*x2*x3 + 2*x5) 382 383 var t [9]E2 384 385 t[0].Square(&x.C1.B1) 386 t[1].Square(&x.C0.B0) 387 t[6].Add(&x.C1.B1, &x.C0.B0).Square(&t[6]).Sub(&t[6], &t[0]).Sub(&t[6], &t[1]) // 2*x4*x0 388 t[2].Square(&x.C0.B2) 389 t[3].Square(&x.C1.B0) 390 t[7].Add(&x.C0.B2, &x.C1.B0).Square(&t[7]).Sub(&t[7], &t[2]).Sub(&t[7], &t[3]) // 2*x2*x3 391 t[4].Square(&x.C1.B2) 392 t[5].Square(&x.C0.B1) 393 t[8].Add(&x.C1.B2, &x.C0.B1).Square(&t[8]).Sub(&t[8], &t[4]).Sub(&t[8], &t[5]).MulByNonResidue(&t[8]) // 2*x5*x1*u 394 395 t[0].MulByNonResidue(&t[0]).Add(&t[0], &t[1]) // x4^2*u + x0^2 396 t[2].MulByNonResidue(&t[2]).Add(&t[2], &t[3]) // x2^2*u + x3^2 397 t[4].MulByNonResidue(&t[4]).Add(&t[4], &t[5]) // x5^2*u + x1^2 398 399 z.C0.B0.Sub(&t[0], &x.C0.B0).Double(&z.C0.B0).Add(&z.C0.B0, &t[0]) 400 z.C0.B1.Sub(&t[2], &x.C0.B1).Double(&z.C0.B1).Add(&z.C0.B1, &t[2]) 401 z.C0.B2.Sub(&t[4], &x.C0.B2).Double(&z.C0.B2).Add(&z.C0.B2, &t[4]) 402 403 z.C1.B0.Add(&t[8], &x.C1.B0).Double(&z.C1.B0).Add(&z.C1.B0, &t[8]) 404 z.C1.B1.Add(&t[6], &x.C1.B1).Double(&z.C1.B1).Add(&z.C1.B1, &t[6]) 405 z.C1.B2.Add(&t[7], &x.C1.B2).Double(&z.C1.B2).Add(&z.C1.B2, &t[7]) 406 407 return z 408 } 409 410 // Inverse sets z to the inverse of x in E12 and returns z 411 // 412 // if x == 0, sets and returns z = x 413 func (z *E12) Inverse(x *E12) *E12 { 414 // Algorithm 23 from https://eprint.iacr.org/2010/354.pdf 415 416 var t0, t1, tmp E6 417 t0.Square(&x.C0) 418 t1.Square(&x.C1) 419 tmp.MulByNonResidue(&t1) 420 t0.Sub(&t0, &tmp) 421 t1.Inverse(&t0) 422 z.C0.Mul(&x.C0, &t1) 423 z.C1.Mul(&x.C1, &t1).Neg(&z.C1) 424 425 return z 426 } 427 428 // BatchInvertE12 returns a new slice with every element in a inverted. 429 // It uses Montgomery batch inversion trick. 430 // 431 // if a[i] == 0, returns result[i] = a[i] 432 func BatchInvertE12(a []E12) []E12 { 433 res := make([]E12, len(a)) 434 if len(a) == 0 { 435 return res 436 } 437 438 zeroes := make([]bool, len(a)) 439 var accumulator E12 440 accumulator.SetOne() 441 442 for i := 0; i < len(a); i++ { 443 if a[i].IsZero() { 444 zeroes[i] = true 445 continue 446 } 447 res[i].Set(&accumulator) 448 accumulator.Mul(&accumulator, &a[i]) 449 } 450 451 accumulator.Inverse(&accumulator) 452 453 for i := len(a) - 1; i >= 0; i-- { 454 if zeroes[i] { 455 continue 456 } 457 res[i].Mul(&res[i], &accumulator) 458 accumulator.Mul(&accumulator, &a[i]) 459 } 460 461 return res 462 } 463 464 // Exp sets z=xᵏ (mod q¹²) and returns it 465 // uses 2-bits windowed method 466 func (z *E12) Exp(x E12, k *big.Int) *E12 { 467 if k.IsUint64() && k.Uint64() == 0 { 468 return z.SetOne() 469 } 470 471 e := k 472 if k.Sign() == -1 { 473 // negative k, we invert 474 // if k < 0: xᵏ (mod q¹²) == (x⁻¹)ᵏ (mod q¹²) 475 x.Inverse(&x) 476 477 // we negate k in a temp big.Int since 478 // Int.Bit(_) of k and -k is different 479 e = bigIntPool.Get().(*big.Int) 480 defer bigIntPool.Put(e) 481 e.Neg(k) 482 } 483 484 var res E12 485 var ops [3]E12 486 487 res.SetOne() 488 ops[0].Set(&x) 489 ops[1].Square(&ops[0]) 490 ops[2].Set(&ops[0]).Mul(&ops[2], &ops[1]) 491 492 b := e.Bytes() 493 for i := range b { 494 w := b[i] 495 mask := byte(0xc0) 496 for j := 0; j < 4; j++ { 497 res.Square(&res).Square(&res) 498 c := (w & mask) >> (6 - 2*j) 499 if c != 0 { 500 res.Mul(&res, &ops[c-1]) 501 } 502 mask = mask >> 2 503 } 504 } 505 z.Set(&res) 506 507 return z 508 } 509 510 // CyclotomicExp sets z=xᵏ (mod q¹²) and returns it 511 // uses 2-NAF decomposition 512 // x must be in the cyclotomic subgroup 513 // TODO: use a windowed method 514 func (z *E12) CyclotomicExp(x E12, k *big.Int) *E12 { 515 if k.IsUint64() && k.Uint64() == 0 { 516 return z.SetOne() 517 } 518 519 e := k 520 if k.Sign() == -1 { 521 // negative k, we invert (=conjugate) 522 // if k < 0: xᵏ (mod q¹²) == (x⁻¹)ᵏ (mod q¹²) 523 x.Conjugate(&x) 524 525 // we negate k in a temp big.Int since 526 // Int.Bit(_) of k and -k is different 527 e = bigIntPool.Get().(*big.Int) 528 defer bigIntPool.Put(e) 529 e.Neg(k) 530 } 531 532 var res, xInv E12 533 xInv.InverseUnitary(&x) 534 res.SetOne() 535 eNAF := make([]int8, e.BitLen()+3) 536 n := ecc.NafDecomposition(e, eNAF[:]) 537 for i := n - 1; i >= 0; i-- { 538 res.CyclotomicSquare(&res) 539 if eNAF[i] == 1 { 540 res.Mul(&res, &x) 541 } else if eNAF[i] == -1 { 542 res.Mul(&res, &xInv) 543 } 544 } 545 z.Set(&res) 546 return z 547 } 548 549 // ExpGLV sets z=xᵏ (q¹²) and returns it 550 // uses 2-dimensional GLV with 2-bits windowed method 551 // x must be in GT 552 // TODO: use 2-NAF 553 // TODO: use higher dimensional decomposition 554 func (z *E12) ExpGLV(x E12, k *big.Int) *E12 { 555 if k.IsUint64() && k.Uint64() == 0 { 556 return z.SetOne() 557 } 558 559 e := k 560 if k.Sign() == -1 { 561 // negative k, we invert (=conjugate) 562 // if k < 0: xᵏ (mod q¹²) == (x⁻¹)ᵏ (mod q¹²) 563 x.Conjugate(&x) 564 565 // we negate k in a temp big.Int since 566 // Int.Bit(_) of k and -k is different 567 e = bigIntPool.Get().(*big.Int) 568 defer bigIntPool.Put(e) 569 e.Neg(k) 570 } 571 572 var table [15]E12 573 var res E12 574 var s1, s2 fr.Element 575 576 res.SetOne() 577 578 // table[b3b2b1b0-1] = b3b2*Frobinius(x) + b1b0*x 579 table[0].Set(&x) 580 table[3].Frobenius(&x) 581 582 // split the scalar, modifies ±x, Frob(x) accordingly 583 s := ecc.SplitScalar(e, &glvBasis) 584 585 if s[0].Sign() == -1 { 586 s[0].Neg(&s[0]) 587 table[0].InverseUnitary(&table[0]) 588 } 589 if s[1].Sign() == -1 { 590 s[1].Neg(&s[1]) 591 table[3].InverseUnitary(&table[3]) 592 } 593 594 // precompute table (2 bits sliding window) 595 // table[b3b2b1b0-1] = b3b2*Frobenius(x) + b1b0*x if b3b2b1b0 != 0 596 table[1].CyclotomicSquare(&table[0]) 597 table[2].Mul(&table[1], &table[0]) 598 table[4].Mul(&table[3], &table[0]) 599 table[5].Mul(&table[3], &table[1]) 600 table[6].Mul(&table[3], &table[2]) 601 table[7].CyclotomicSquare(&table[3]) 602 table[8].Mul(&table[7], &table[0]) 603 table[9].Mul(&table[7], &table[1]) 604 table[10].Mul(&table[7], &table[2]) 605 table[11].Mul(&table[7], &table[3]) 606 table[12].Mul(&table[11], &table[0]) 607 table[13].Mul(&table[11], &table[1]) 608 table[14].Mul(&table[11], &table[2]) 609 610 // bounds on the lattice base vectors guarantee that s1, s2 are len(r)/2 bits long max 611 s1 = s1.SetBigInt(&s[0]).Bits() 612 s2 = s2.SetBigInt(&s[1]).Bits() 613 614 maxBit := s1.BitLen() 615 if s2.BitLen() > maxBit { 616 maxBit = s2.BitLen() 617 } 618 hiWordIndex := (maxBit - 1) / 64 619 620 // loop starts from len(s1)/2 due to the bounds 621 for i := hiWordIndex; i >= 0; i-- { 622 mask := uint64(3) << 62 623 for j := 0; j < 32; j++ { 624 res.CyclotomicSquare(&res).CyclotomicSquare(&res) 625 b1 := (s1[i] & mask) >> (62 - 2*j) 626 b2 := (s2[i] & mask) >> (62 - 2*j) 627 if b1|b2 != 0 { 628 s := (b2<<2 | b1) 629 res.Mul(&res, &table[s-1]) 630 } 631 mask = mask >> 2 632 } 633 } 634 635 z.Set(&res) 636 return z 637 } 638 639 // InverseUnitary inverses a unitary element 640 func (z *E12) InverseUnitary(x *E12) *E12 { 641 return z.Conjugate(x) 642 } 643 644 // Conjugate sets z to x conjugated and returns z 645 func (z *E12) Conjugate(x *E12) *E12 { 646 *z = *x 647 z.C1.Neg(&z.C1) 648 return z 649 } 650 651 // SizeOfGT represents the size in bytes that a GT element need in binary form 652 const SizeOfGT = 48 * 12 653 654 // Marshal converts z to a byte slice 655 func (z *E12) Marshal() []byte { 656 b := z.Bytes() 657 return b[:] 658 } 659 660 // Unmarshal is an alias to SetBytes() 661 func (z *E12) Unmarshal(buf []byte) error { 662 return z.SetBytes(buf) 663 } 664 665 // Bytes returns the regular (non montgomery) value 666 // of z as a big-endian byte array. 667 // z.C1.B2.A1 | z.C1.B2.A0 | z.C1.B1.A1 | ... 668 func (z *E12) Bytes() (r [SizeOfGT]byte) { 669 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[528:528+fp.Bytes]), z.C0.B0.A0) 670 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[480:480+fp.Bytes]), z.C0.B0.A1) 671 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[432:432+fp.Bytes]), z.C0.B1.A0) 672 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[384:384+fp.Bytes]), z.C0.B1.A1) 673 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[336:336+fp.Bytes]), z.C0.B2.A0) 674 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[288:288+fp.Bytes]), z.C0.B2.A1) 675 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[240:240+fp.Bytes]), z.C1.B0.A0) 676 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[192:192+fp.Bytes]), z.C1.B0.A1) 677 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[144:144+fp.Bytes]), z.C1.B1.A0) 678 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[96:96+fp.Bytes]), z.C1.B1.A1) 679 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[48:48+fp.Bytes]), z.C1.B2.A0) 680 fp.BigEndian.PutElement((*[fp.Bytes]byte)(r[0:0+fp.Bytes]), z.C1.B2.A1) 681 682 return 683 } 684 685 // SetBytes interprets e as the bytes of a big-endian GT 686 // sets z to that value (in Montgomery form), and returns z. 687 // size(e) == 48 * 12 688 // z.C1.B2.A1 | z.C1.B2.A0 | z.C1.B1.A1 | ... 689 func (z *E12) SetBytes(e []byte) error { 690 if len(e) != SizeOfGT { 691 return errors.New("invalid buffer size") 692 } 693 if err := z.C0.B0.A0.SetBytesCanonical(e[528 : 528+fp.Bytes]); err != nil { 694 return err 695 } 696 if err := z.C0.B0.A1.SetBytesCanonical(e[480 : 480+fp.Bytes]); err != nil { 697 return err 698 } 699 if err := z.C0.B1.A0.SetBytesCanonical(e[432 : 432+fp.Bytes]); err != nil { 700 return err 701 } 702 if err := z.C0.B1.A1.SetBytesCanonical(e[384 : 384+fp.Bytes]); err != nil { 703 return err 704 } 705 if err := z.C0.B2.A0.SetBytesCanonical(e[336 : 336+fp.Bytes]); err != nil { 706 return err 707 } 708 if err := z.C0.B2.A1.SetBytesCanonical(e[288 : 288+fp.Bytes]); err != nil { 709 return err 710 } 711 if err := z.C1.B0.A0.SetBytesCanonical(e[240 : 240+fp.Bytes]); err != nil { 712 return err 713 } 714 if err := z.C1.B0.A1.SetBytesCanonical(e[192 : 192+fp.Bytes]); err != nil { 715 return err 716 } 717 if err := z.C1.B1.A0.SetBytesCanonical(e[144 : 144+fp.Bytes]); err != nil { 718 return err 719 } 720 if err := z.C1.B1.A1.SetBytesCanonical(e[96 : 96+fp.Bytes]); err != nil { 721 return err 722 } 723 if err := z.C1.B2.A0.SetBytesCanonical(e[48 : 48+fp.Bytes]); err != nil { 724 return err 725 } 726 if err := z.C1.B2.A1.SetBytesCanonical(e[0 : 0+fp.Bytes]); err != nil { 727 return err 728 } 729 730 return nil 731 } 732 733 // IsInSubGroup ensures GT/E12 is in correct subgroup 734 func (z *E12) IsInSubGroup() bool { 735 var a, b E12 736 737 // check z^(phi_k(p)) == 1 738 a.FrobeniusSquare(z) 739 b.FrobeniusSquare(&a).Mul(&b, z) 740 741 if !a.Equal(&b) { 742 return false 743 } 744 745 // check z^(p+1-t) == 1 746 a.Frobenius(z) 747 b.Expt(z) 748 749 return a.Equal(&b) 750 } 751 752 // CompressTorus GT/E12 element to half its size 753 // z must be in the cyclotomic subgroup 754 // i.e. z^(p^4-p^2+1)=1 755 // e.g. GT 756 // "COMPRESSION IN FINITE FIELDS AND TORUS-BASED CRYPTOGRAPHY", K. RUBIN AND A. SILVERBERG 757 // z.C1 == 0 only when z \in {-1,1} 758 func (z *E12) CompressTorus() (E6, error) { 759 760 if z.C1.IsZero() { 761 return E6{}, errors.New("invalid input") 762 } 763 764 var res, tmp, one E6 765 one.SetOne() 766 tmp.Inverse(&z.C1) 767 res.Add(&z.C0, &one). 768 Mul(&res, &tmp) 769 770 return res, nil 771 } 772 773 // BatchCompressTorus GT/E12 elements to half their size using a batch inversion. 774 // 775 // if len(x) == 0 or if any of the x[i].C1 coordinate is 0, this function returns an error. 776 func BatchCompressTorus(x []E12) ([]E6, error) { 777 778 n := len(x) 779 if n == 0 { 780 return nil, errors.New("invalid input size") 781 } 782 783 var one E6 784 one.SetOne() 785 res := make([]E6, n) 786 787 for i := 0; i < n; i++ { 788 res[i].Set(&x[i].C1) 789 // throw an error if any of the x[i].C1 is 0 790 if res[i].IsZero() { 791 return nil, errors.New("invalid input; C1 is 0") 792 } 793 } 794 795 t := BatchInvertE6(res) // costs 1 inverse 796 797 for i := 0; i < n; i++ { 798 res[i].Add(&x[i].C0, &one). 799 Mul(&res[i], &t[i]) 800 } 801 802 return res, nil 803 } 804 805 // DecompressTorus GT/E12 a compressed element 806 // element must be in the cyclotomic subgroup 807 // "COMPRESSION IN FINITE FIELDS AND TORUS-BASED CRYPTOGRAPHY", K. RUBIN AND A. SILVERBERG 808 func (z *E6) DecompressTorus() E12 { 809 810 var res, num, denum E12 811 num.C0.Set(z) 812 num.C1.SetOne() 813 denum.C0.Set(z) 814 denum.C1.SetOne().Neg(&denum.C1) 815 res.Inverse(&denum). 816 Mul(&res, &num) 817 818 return res 819 } 820 821 // BatchDecompressTorus GT/E12 compressed elements 822 // using a batch inversion 823 func BatchDecompressTorus(x []E6) ([]E12, error) { 824 825 n := len(x) 826 if n == 0 { 827 return []E12{}, errors.New("invalid input size") 828 } 829 830 res := make([]E12, n) 831 num := make([]E12, n) 832 denum := make([]E12, n) 833 834 for i := 0; i < n; i++ { 835 num[i].C0.Set(&x[i]) 836 num[i].C1.SetOne() 837 denum[i].C0.Set(&x[i]) 838 denum[i].C1.SetOne().Neg(&denum[i].C1) 839 } 840 841 denum = BatchInvertE12(denum) // costs 1 inverse 842 843 for i := 0; i < n; i++ { 844 res[i].Mul(&num[i], &denum[i]) 845 } 846 847 return res, nil 848 } 849 850 // Select is conditional move. 851 // If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. 852 func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { 853 //Might be able to save a nanosecond or two by an aggregate implementation 854 855 z.C0.Select(cond, &caseZ.C0, &caseNz.C0) 856 z.C1.Select(cond, &caseZ.C1, &caseNz.C1) 857 858 return z 859 } 860 861 // Div divides an element in E12 by an element in E12 862 func (z *E12) Div(x *E12, y *E12) *E12 { 863 var r E12 864 r.Inverse(y).Mul(x, &r) 865 return z.Set(&r) 866 }