github.com/arjunbeliever/ignite@v0.0.0-20220406110515-46bbbbec2587/crypto/bls12381/g2.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package bls12381 18 19 import ( 20 "errors" 21 "math" 22 "math/big" 23 ) 24 25 // PointG2 is type for point in G2. 26 // PointG2 is both used for Affine and Jacobian point representation. 27 // If z is equal to one the point is considered as in affine form. 28 type PointG2 [3]fe2 29 30 // Set copies valeus of one point to another. 31 func (p *PointG2) Set(p2 *PointG2) *PointG2 { 32 p[0].set(&p2[0]) 33 p[1].set(&p2[1]) 34 p[2].set(&p2[2]) 35 return p 36 } 37 38 // Zero returns G2 point in point at infinity representation 39 func (p *PointG2) Zero() *PointG2 { 40 p[0].zero() 41 p[1].one() 42 p[2].zero() 43 return p 44 45 } 46 47 type tempG2 struct { 48 t [9]*fe2 49 } 50 51 // G2 is struct for G2 group. 52 type G2 struct { 53 f *fp2 54 tempG2 55 } 56 57 // NewG2 constructs a new G2 instance. 58 func NewG2() *G2 { 59 return newG2(nil) 60 } 61 62 func newG2(f *fp2) *G2 { 63 if f == nil { 64 f = newFp2() 65 } 66 t := newTempG2() 67 return &G2{f, t} 68 } 69 70 func newTempG2() tempG2 { 71 t := [9]*fe2{} 72 for i := 0; i < 9; i++ { 73 t[i] = &fe2{} 74 } 75 return tempG2{t} 76 } 77 78 // Q returns group order in big.Int. 79 func (g *G2) Q() *big.Int { 80 return new(big.Int).Set(q) 81 } 82 83 func (g *G2) fromBytesUnchecked(in []byte) (*PointG2, error) { 84 p0, err := g.f.fromBytes(in[:96]) 85 if err != nil { 86 return nil, err 87 } 88 p1, err := g.f.fromBytes(in[96:]) 89 if err != nil { 90 return nil, err 91 } 92 p2 := new(fe2).one() 93 return &PointG2{*p0, *p1, *p2}, nil 94 } 95 96 // FromBytes constructs a new point given uncompressed byte input. 97 // FromBytes does not take zcash flags into account. 98 // Byte input expected to be larger than 96 bytes. 99 // First 192 bytes should be concatenation of x and y values 100 // Point (0, 0) is considered as infinity. 101 func (g *G2) FromBytes(in []byte) (*PointG2, error) { 102 if len(in) != 192 { 103 return nil, errors.New("input string should be equal or larger than 192") 104 } 105 p0, err := g.f.fromBytes(in[:96]) 106 if err != nil { 107 return nil, err 108 } 109 p1, err := g.f.fromBytes(in[96:]) 110 if err != nil { 111 return nil, err 112 } 113 // check if given input points to infinity 114 if p0.isZero() && p1.isZero() { 115 return g.Zero(), nil 116 } 117 p2 := new(fe2).one() 118 p := &PointG2{*p0, *p1, *p2} 119 if !g.IsOnCurve(p) { 120 return nil, errors.New("point is not on curve") 121 } 122 return p, nil 123 } 124 125 // DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G1 Point. 126 func (g *G2) DecodePoint(in []byte) (*PointG2, error) { 127 if len(in) != 256 { 128 return nil, errors.New("invalid g2 point length") 129 } 130 pointBytes := make([]byte, 192) 131 x0Bytes, err := decodeFieldElement(in[:64]) 132 if err != nil { 133 return nil, err 134 } 135 x1Bytes, err := decodeFieldElement(in[64:128]) 136 if err != nil { 137 return nil, err 138 } 139 y0Bytes, err := decodeFieldElement(in[128:192]) 140 if err != nil { 141 return nil, err 142 } 143 y1Bytes, err := decodeFieldElement(in[192:]) 144 if err != nil { 145 return nil, err 146 } 147 copy(pointBytes[:48], x1Bytes) 148 copy(pointBytes[48:96], x0Bytes) 149 copy(pointBytes[96:144], y1Bytes) 150 copy(pointBytes[144:192], y0Bytes) 151 return g.FromBytes(pointBytes) 152 } 153 154 // ToBytes serializes a point into bytes in uncompressed form, 155 // does not take zcash flags into account, 156 // returns (0, 0) if point is infinity. 157 func (g *G2) ToBytes(p *PointG2) []byte { 158 out := make([]byte, 192) 159 if g.IsZero(p) { 160 return out 161 } 162 g.Affine(p) 163 copy(out[:96], g.f.toBytes(&p[0])) 164 copy(out[96:], g.f.toBytes(&p[1])) 165 return out 166 } 167 168 // EncodePoint encodes a point into 256 bytes. 169 func (g *G2) EncodePoint(p *PointG2) []byte { 170 // outRaw is 96 bytes 171 outRaw := g.ToBytes(p) 172 out := make([]byte, 256) 173 // encode x 174 copy(out[16:16+48], outRaw[48:96]) 175 copy(out[80:80+48], outRaw[:48]) 176 // encode y 177 copy(out[144:144+48], outRaw[144:]) 178 copy(out[208:208+48], outRaw[96:144]) 179 return out 180 } 181 182 // New creates a new G2 Point which is equal to zero in other words point at infinity. 183 func (g *G2) New() *PointG2 { 184 return new(PointG2).Zero() 185 } 186 187 // Zero returns a new G2 Point which is equal to point at infinity. 188 func (g *G2) Zero() *PointG2 { 189 return new(PointG2).Zero() 190 } 191 192 // One returns a new G2 Point which is equal to generator point. 193 func (g *G2) One() *PointG2 { 194 p := &PointG2{} 195 return p.Set(&g2One) 196 } 197 198 // IsZero returns true if given point is equal to zero. 199 func (g *G2) IsZero(p *PointG2) bool { 200 return p[2].isZero() 201 } 202 203 // Equal checks if given two G2 point is equal in their affine form. 204 func (g *G2) Equal(p1, p2 *PointG2) bool { 205 if g.IsZero(p1) { 206 return g.IsZero(p2) 207 } 208 if g.IsZero(p2) { 209 return g.IsZero(p1) 210 } 211 t := g.t 212 g.f.square(t[0], &p1[2]) 213 g.f.square(t[1], &p2[2]) 214 g.f.mul(t[2], t[0], &p2[0]) 215 g.f.mul(t[3], t[1], &p1[0]) 216 g.f.mul(t[0], t[0], &p1[2]) 217 g.f.mul(t[1], t[1], &p2[2]) 218 g.f.mul(t[1], t[1], &p1[1]) 219 g.f.mul(t[0], t[0], &p2[1]) 220 return t[0].equal(t[1]) && t[2].equal(t[3]) 221 } 222 223 // InCorrectSubgroup checks whether given point is in correct subgroup. 224 func (g *G2) InCorrectSubgroup(p *PointG2) bool { 225 tmp := &PointG2{} 226 g.MulScalar(tmp, p, q) 227 return g.IsZero(tmp) 228 } 229 230 // IsOnCurve checks a G2 point is on curve. 231 func (g *G2) IsOnCurve(p *PointG2) bool { 232 if g.IsZero(p) { 233 return true 234 } 235 t := g.t 236 g.f.square(t[0], &p[1]) 237 g.f.square(t[1], &p[0]) 238 g.f.mul(t[1], t[1], &p[0]) 239 g.f.square(t[2], &p[2]) 240 g.f.square(t[3], t[2]) 241 g.f.mul(t[2], t[2], t[3]) 242 g.f.mul(t[2], b2, t[2]) 243 g.f.add(t[1], t[1], t[2]) 244 return t[0].equal(t[1]) 245 } 246 247 // IsAffine checks a G2 point whether it is in affine form. 248 func (g *G2) IsAffine(p *PointG2) bool { 249 return p[2].isOne() 250 } 251 252 // Affine calculates affine form of given G2 point. 253 func (g *G2) Affine(p *PointG2) *PointG2 { 254 if g.IsZero(p) { 255 return p 256 } 257 if !g.IsAffine(p) { 258 t := g.t 259 g.f.inverse(t[0], &p[2]) 260 g.f.square(t[1], t[0]) 261 g.f.mul(&p[0], &p[0], t[1]) 262 g.f.mul(t[0], t[0], t[1]) 263 g.f.mul(&p[1], &p[1], t[0]) 264 p[2].one() 265 } 266 return p 267 } 268 269 // Add adds two G2 points p1, p2 and assigns the result to point at first argument. 270 func (g *G2) Add(r, p1, p2 *PointG2) *PointG2 { 271 // http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl 272 if g.IsZero(p1) { 273 return r.Set(p2) 274 } 275 if g.IsZero(p2) { 276 return r.Set(p1) 277 } 278 t := g.t 279 g.f.square(t[7], &p1[2]) 280 g.f.mul(t[1], &p2[0], t[7]) 281 g.f.mul(t[2], &p1[2], t[7]) 282 g.f.mul(t[0], &p2[1], t[2]) 283 g.f.square(t[8], &p2[2]) 284 g.f.mul(t[3], &p1[0], t[8]) 285 g.f.mul(t[4], &p2[2], t[8]) 286 g.f.mul(t[2], &p1[1], t[4]) 287 if t[1].equal(t[3]) { 288 if t[0].equal(t[2]) { 289 return g.Double(r, p1) 290 } 291 return r.Zero() 292 } 293 g.f.sub(t[1], t[1], t[3]) 294 g.f.double(t[4], t[1]) 295 g.f.square(t[4], t[4]) 296 g.f.mul(t[5], t[1], t[4]) 297 g.f.sub(t[0], t[0], t[2]) 298 g.f.double(t[0], t[0]) 299 g.f.square(t[6], t[0]) 300 g.f.sub(t[6], t[6], t[5]) 301 g.f.mul(t[3], t[3], t[4]) 302 g.f.double(t[4], t[3]) 303 g.f.sub(&r[0], t[6], t[4]) 304 g.f.sub(t[4], t[3], &r[0]) 305 g.f.mul(t[6], t[2], t[5]) 306 g.f.double(t[6], t[6]) 307 g.f.mul(t[0], t[0], t[4]) 308 g.f.sub(&r[1], t[0], t[6]) 309 g.f.add(t[0], &p1[2], &p2[2]) 310 g.f.square(t[0], t[0]) 311 g.f.sub(t[0], t[0], t[7]) 312 g.f.sub(t[0], t[0], t[8]) 313 g.f.mul(&r[2], t[0], t[1]) 314 return r 315 } 316 317 // Double doubles a G2 point p and assigns the result to the point at first argument. 318 func (g *G2) Double(r, p *PointG2) *PointG2 { 319 // http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l 320 if g.IsZero(p) { 321 return r.Set(p) 322 } 323 t := g.t 324 g.f.square(t[0], &p[0]) 325 g.f.square(t[1], &p[1]) 326 g.f.square(t[2], t[1]) 327 g.f.add(t[1], &p[0], t[1]) 328 g.f.square(t[1], t[1]) 329 g.f.sub(t[1], t[1], t[0]) 330 g.f.sub(t[1], t[1], t[2]) 331 g.f.double(t[1], t[1]) 332 g.f.double(t[3], t[0]) 333 g.f.add(t[0], t[3], t[0]) 334 g.f.square(t[4], t[0]) 335 g.f.double(t[3], t[1]) 336 g.f.sub(&r[0], t[4], t[3]) 337 g.f.sub(t[1], t[1], &r[0]) 338 g.f.double(t[2], t[2]) 339 g.f.double(t[2], t[2]) 340 g.f.double(t[2], t[2]) 341 g.f.mul(t[0], t[0], t[1]) 342 g.f.sub(t[1], t[0], t[2]) 343 g.f.mul(t[0], &p[1], &p[2]) 344 r[1].set(t[1]) 345 g.f.double(&r[2], t[0]) 346 return r 347 } 348 349 // Neg negates a G2 point p and assigns the result to the point at first argument. 350 func (g *G2) Neg(r, p *PointG2) *PointG2 { 351 r[0].set(&p[0]) 352 g.f.neg(&r[1], &p[1]) 353 r[2].set(&p[2]) 354 return r 355 } 356 357 // Sub subtracts two G2 points p1, p2 and assigns the result to point at first argument. 358 func (g *G2) Sub(c, a, b *PointG2) *PointG2 { 359 d := &PointG2{} 360 g.Neg(d, b) 361 g.Add(c, a, d) 362 return c 363 } 364 365 // MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument. 366 func (g *G2) MulScalar(c, p *PointG2, e *big.Int) *PointG2 { 367 q, n := &PointG2{}, &PointG2{} 368 n.Set(p) 369 l := e.BitLen() 370 for i := 0; i < l; i++ { 371 if e.Bit(i) == 1 { 372 g.Add(q, q, n) 373 } 374 g.Double(n, n) 375 } 376 return c.Set(q) 377 } 378 379 // ClearCofactor maps given a G2 point to correct subgroup 380 func (g *G2) ClearCofactor(p *PointG2) { 381 g.MulScalar(p, p, cofactorEFFG2) 382 } 383 384 // MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values 385 // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n 386 // Length of points and scalars are expected to be equal, otherwise an error is returned. 387 // Result is assigned to point at first argument. 388 func (g *G2) MultiExp(r *PointG2, points []*PointG2, powers []*big.Int) (*PointG2, error) { 389 if len(points) != len(powers) { 390 return nil, errors.New("point and scalar vectors should be in same length") 391 } 392 var c uint32 = 3 393 if len(powers) >= 32 { 394 c = uint32(math.Ceil(math.Log10(float64(len(powers))))) 395 } 396 bucketSize, numBits := (1<<c)-1, uint32(g.Q().BitLen()) 397 windows := make([]*PointG2, numBits/c+1) 398 bucket := make([]*PointG2, bucketSize) 399 acc, sum := g.New(), g.New() 400 for i := 0; i < bucketSize; i++ { 401 bucket[i] = g.New() 402 } 403 mask := (uint64(1) << c) - 1 404 j := 0 405 var cur uint32 406 for cur <= numBits { 407 acc.Zero() 408 bucket = make([]*PointG2, (1<<c)-1) 409 for i := 0; i < len(bucket); i++ { 410 bucket[i] = g.New() 411 } 412 for i := 0; i < len(powers); i++ { 413 s0 := powers[i].Uint64() 414 index := uint(s0 & mask) 415 if index != 0 { 416 g.Add(bucket[index-1], bucket[index-1], points[i]) 417 } 418 powers[i] = new(big.Int).Rsh(powers[i], uint(c)) 419 } 420 sum.Zero() 421 for i := len(bucket) - 1; i >= 0; i-- { 422 g.Add(sum, sum, bucket[i]) 423 g.Add(acc, acc, sum) 424 } 425 windows[j] = g.New() 426 windows[j].Set(acc) 427 j++ 428 cur += c 429 } 430 acc.Zero() 431 for i := len(windows) - 1; i >= 0; i-- { 432 for j := uint32(0); j < c; j++ { 433 g.Double(acc, acc) 434 } 435 g.Add(acc, acc, windows[i]) 436 } 437 return r.Set(acc), nil 438 } 439 440 // MapToCurve given a byte slice returns a valid G2 point. 441 // This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method. 442 // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05#section-6.6.2 443 // Input byte slice should be a valid field element, otherwise an error is returned. 444 func (g *G2) MapToCurve(in []byte) (*PointG2, error) { 445 fp2 := g.f 446 u, err := fp2.fromBytes(in) 447 if err != nil { 448 return nil, err 449 } 450 x, y := swuMapG2(fp2, u) 451 isogenyMapG2(fp2, x, y) 452 z := new(fe2).one() 453 q := &PointG2{*x, *y, *z} 454 g.ClearCofactor(q) 455 return g.Affine(q), nil 456 }