github.com/snowblossomcoin/go-ethereum@v1.9.25/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 } else { 291 return r.Zero() 292 } 293 } 294 g.f.sub(t[1], t[1], t[3]) 295 g.f.double(t[4], t[1]) 296 g.f.square(t[4], t[4]) 297 g.f.mul(t[5], t[1], t[4]) 298 g.f.sub(t[0], t[0], t[2]) 299 g.f.double(t[0], t[0]) 300 g.f.square(t[6], t[0]) 301 g.f.sub(t[6], t[6], t[5]) 302 g.f.mul(t[3], t[3], t[4]) 303 g.f.double(t[4], t[3]) 304 g.f.sub(&r[0], t[6], t[4]) 305 g.f.sub(t[4], t[3], &r[0]) 306 g.f.mul(t[6], t[2], t[5]) 307 g.f.double(t[6], t[6]) 308 g.f.mul(t[0], t[0], t[4]) 309 g.f.sub(&r[1], t[0], t[6]) 310 g.f.add(t[0], &p1[2], &p2[2]) 311 g.f.square(t[0], t[0]) 312 g.f.sub(t[0], t[0], t[7]) 313 g.f.sub(t[0], t[0], t[8]) 314 g.f.mul(&r[2], t[0], t[1]) 315 return r 316 } 317 318 // Double doubles a G2 point p and assigns the result to the point at first argument. 319 func (g *G2) Double(r, p *PointG2) *PointG2 { 320 // http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l 321 if g.IsZero(p) { 322 return r.Set(p) 323 } 324 t := g.t 325 g.f.square(t[0], &p[0]) 326 g.f.square(t[1], &p[1]) 327 g.f.square(t[2], t[1]) 328 g.f.add(t[1], &p[0], t[1]) 329 g.f.square(t[1], t[1]) 330 g.f.sub(t[1], t[1], t[0]) 331 g.f.sub(t[1], t[1], t[2]) 332 g.f.double(t[1], t[1]) 333 g.f.double(t[3], t[0]) 334 g.f.add(t[0], t[3], t[0]) 335 g.f.square(t[4], t[0]) 336 g.f.double(t[3], t[1]) 337 g.f.sub(&r[0], t[4], t[3]) 338 g.f.sub(t[1], t[1], &r[0]) 339 g.f.double(t[2], t[2]) 340 g.f.double(t[2], t[2]) 341 g.f.double(t[2], t[2]) 342 g.f.mul(t[0], t[0], t[1]) 343 g.f.sub(t[1], t[0], t[2]) 344 g.f.mul(t[0], &p[1], &p[2]) 345 r[1].set(t[1]) 346 g.f.double(&r[2], t[0]) 347 return r 348 } 349 350 // Neg negates a G2 point p and assigns the result to the point at first argument. 351 func (g *G2) Neg(r, p *PointG2) *PointG2 { 352 r[0].set(&p[0]) 353 g.f.neg(&r[1], &p[1]) 354 r[2].set(&p[2]) 355 return r 356 } 357 358 // Sub subtracts two G2 points p1, p2 and assigns the result to point at first argument. 359 func (g *G2) Sub(c, a, b *PointG2) *PointG2 { 360 d := &PointG2{} 361 g.Neg(d, b) 362 g.Add(c, a, d) 363 return c 364 } 365 366 // MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument. 367 func (g *G2) MulScalar(c, p *PointG2, e *big.Int) *PointG2 { 368 q, n := &PointG2{}, &PointG2{} 369 n.Set(p) 370 l := e.BitLen() 371 for i := 0; i < l; i++ { 372 if e.Bit(i) == 1 { 373 g.Add(q, q, n) 374 } 375 g.Double(n, n) 376 } 377 return c.Set(q) 378 } 379 380 // ClearCofactor maps given a G2 point to correct subgroup 381 func (g *G2) ClearCofactor(p *PointG2) { 382 g.MulScalar(p, p, cofactorEFFG2) 383 } 384 385 // MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values 386 // (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 387 // Length of points and scalars are expected to be equal, otherwise an error is returned. 388 // Result is assigned to point at first argument. 389 func (g *G2) MultiExp(r *PointG2, points []*PointG2, powers []*big.Int) (*PointG2, error) { 390 if len(points) != len(powers) { 391 return nil, errors.New("point and scalar vectors should be in same length") 392 } 393 var c uint32 = 3 394 if len(powers) >= 32 { 395 c = uint32(math.Ceil(math.Log10(float64(len(powers))))) 396 } 397 bucketSize, numBits := (1<<c)-1, uint32(g.Q().BitLen()) 398 windows := make([]*PointG2, numBits/c+1) 399 bucket := make([]*PointG2, bucketSize) 400 acc, sum := g.New(), g.New() 401 for i := 0; i < bucketSize; i++ { 402 bucket[i] = g.New() 403 } 404 mask := (uint64(1) << c) - 1 405 j := 0 406 var cur uint32 407 for cur <= numBits { 408 acc.Zero() 409 bucket = make([]*PointG2, (1<<c)-1) 410 for i := 0; i < len(bucket); i++ { 411 bucket[i] = g.New() 412 } 413 for i := 0; i < len(powers); i++ { 414 s0 := powers[i].Uint64() 415 index := uint(s0 & mask) 416 if index != 0 { 417 g.Add(bucket[index-1], bucket[index-1], points[i]) 418 } 419 powers[i] = new(big.Int).Rsh(powers[i], uint(c)) 420 } 421 sum.Zero() 422 for i := len(bucket) - 1; i >= 0; i-- { 423 g.Add(sum, sum, bucket[i]) 424 g.Add(acc, acc, sum) 425 } 426 windows[j] = g.New() 427 windows[j].Set(acc) 428 j++ 429 cur += c 430 } 431 acc.Zero() 432 for i := len(windows) - 1; i >= 0; i-- { 433 for j := uint32(0); j < c; j++ { 434 g.Double(acc, acc) 435 } 436 g.Add(acc, acc, windows[i]) 437 } 438 return r.Set(acc), nil 439 } 440 441 // MapToCurve given a byte slice returns a valid G2 point. 442 // This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method. 443 // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05#section-6.6.2 444 // Input byte slice should be a valid field element, otherwise an error is returned. 445 func (g *G2) MapToCurve(in []byte) (*PointG2, error) { 446 fp2 := g.f 447 u, err := fp2.fromBytes(in) 448 if err != nil { 449 return nil, err 450 } 451 x, y := swuMapG2(fp2, u) 452 isogenyMapG2(fp2, x, y) 453 z := new(fe2).one() 454 q := &PointG2{*x, *y, *z} 455 g.ClearCofactor(q) 456 return g.Affine(q), nil 457 }