github.com/amazechain/amc@v0.1.3/common/crypto/bls12381/g2.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 //noling:golint 18 package bls12381 19 20 import ( 21 "errors" 22 "math" 23 "math/big" 24 ) 25 26 // PointG2 is type for point in G2. 27 // PointG2 is both used for Affine and Jacobian point representation. 28 // If z is equal to one the point is considered as in affine form. 29 type PointG2 [3]fe2 30 31 // Set copies valeus of one point to another. 32 func (p *PointG2) Set(p2 *PointG2) *PointG2 { 33 p[0].set(&p2[0]) 34 p[1].set(&p2[1]) 35 p[2].set(&p2[2]) 36 return p 37 } 38 39 // Zero returns G2 point in point at infinity representation 40 func (p *PointG2) Zero() *PointG2 { 41 p[0].zero() 42 p[1].one() 43 p[2].zero() 44 return p 45 46 } 47 48 type tempG2 struct { 49 t [9]*fe2 50 } 51 52 // G2 is struct for G2 group. 53 type G2 struct { 54 f *fp2 55 tempG2 56 } 57 58 // NewG2 constructs a new G2 instance. 59 func NewG2() *G2 { 60 return newG2(nil) 61 } 62 63 func newG2(f *fp2) *G2 { 64 if f == nil { 65 f = newFp2() 66 } 67 t := newTempG2() 68 return &G2{f, t} 69 } 70 71 func newTempG2() tempG2 { 72 t := [9]*fe2{} 73 for i := 0; i < 9; i++ { 74 t[i] = &fe2{} 75 } 76 return tempG2{t} 77 } 78 79 // Q returns group order in big.Int. 80 func (g *G2) Q() *big.Int { 81 return new(big.Int).Set(q) 82 } 83 84 func (g *G2) fromBytesUnchecked(in []byte) (*PointG2, error) { 85 p0, err := g.f.fromBytes(in[:96]) 86 if err != nil { 87 return nil, err 88 } 89 p1, err := g.f.fromBytes(in[96:]) 90 if err != nil { 91 return nil, err 92 } 93 p2 := new(fe2).one() 94 return &PointG2{*p0, *p1, *p2}, nil 95 } 96 97 // FromBytes constructs a new point given uncompressed byte input. 98 // FromBytes does not take zcash flags into account. 99 // Byte input expected to be larger than 96 bytes. 100 // First 192 bytes should be concatenation of x and y values 101 // Point (0, 0) is considered as infinity. 102 func (g *G2) FromBytes(in []byte) (*PointG2, error) { 103 if len(in) != 192 { 104 return nil, errors.New("input string should be equal or larger than 192") 105 } 106 p0, err := g.f.fromBytes(in[:96]) 107 if err != nil { 108 return nil, err 109 } 110 p1, err := g.f.fromBytes(in[96:]) 111 if err != nil { 112 return nil, err 113 } 114 // check if given input points to infinity 115 if p0.isZero() && p1.isZero() { 116 return g.Zero(), nil 117 } 118 p2 := new(fe2).one() 119 p := &PointG2{*p0, *p1, *p2} 120 if !g.IsOnCurve(p) { 121 return nil, errors.New("point is not on curve") 122 } 123 return p, nil 124 } 125 126 // DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G1 Point. 127 func (g *G2) DecodePoint(in []byte) (*PointG2, error) { 128 if len(in) != 256 { 129 return nil, errors.New("invalid g2 point length") 130 } 131 pointBytes := make([]byte, 192) 132 x0Bytes, err := decodeFieldElement(in[:64]) 133 if err != nil { 134 return nil, err 135 } 136 x1Bytes, err := decodeFieldElement(in[64:128]) 137 if err != nil { 138 return nil, err 139 } 140 y0Bytes, err := decodeFieldElement(in[128:192]) 141 if err != nil { 142 return nil, err 143 } 144 y1Bytes, err := decodeFieldElement(in[192:]) 145 if err != nil { 146 return nil, err 147 } 148 copy(pointBytes[:48], x1Bytes) 149 copy(pointBytes[48:96], x0Bytes) 150 copy(pointBytes[96:144], y1Bytes) 151 copy(pointBytes[144:192], y0Bytes) 152 return g.FromBytes(pointBytes) 153 } 154 155 // ToBytes serializes a point into bytes in uncompressed form, 156 // does not take zcash flags into account, 157 // returns (0, 0) if point is infinity. 158 func (g *G2) ToBytes(p *PointG2) []byte { 159 out := make([]byte, 192) 160 if g.IsZero(p) { 161 return out 162 } 163 g.Affine(p) 164 copy(out[:96], g.f.toBytes(&p[0])) 165 copy(out[96:], g.f.toBytes(&p[1])) 166 return out 167 } 168 169 // EncodePoint encodes a point into 256 bytes. 170 func (g *G2) EncodePoint(p *PointG2) []byte { 171 // outRaw is 96 bytes 172 outRaw := g.ToBytes(p) 173 out := make([]byte, 256) 174 // encode x 175 copy(out[16:16+48], outRaw[48:96]) 176 copy(out[80:80+48], outRaw[:48]) 177 // encode y 178 copy(out[144:144+48], outRaw[144:]) 179 copy(out[208:208+48], outRaw[96:144]) 180 return out 181 } 182 183 // New creates a new G2 Point which is equal to zero in other words point at infinity. 184 func (g *G2) New() *PointG2 { 185 return new(PointG2).Zero() 186 } 187 188 // Zero returns a new G2 Point which is equal to point at infinity. 189 func (g *G2) Zero() *PointG2 { 190 return new(PointG2).Zero() 191 } 192 193 // One returns a new G2 Point which is equal to generator point. 194 func (g *G2) One() *PointG2 { 195 p := &PointG2{} 196 return p.Set(&g2One) 197 } 198 199 // IsZero returns true if given point is equal to zero. 200 func (g *G2) IsZero(p *PointG2) bool { 201 return p[2].isZero() 202 } 203 204 // Equal checks if given two G2 point is equal in their affine form. 205 func (g *G2) Equal(p1, p2 *PointG2) bool { 206 if g.IsZero(p1) { 207 return g.IsZero(p2) 208 } 209 if g.IsZero(p2) { 210 return g.IsZero(p1) 211 } 212 t := g.t 213 g.f.square(t[0], &p1[2]) 214 g.f.square(t[1], &p2[2]) 215 g.f.mul(t[2], t[0], &p2[0]) 216 g.f.mul(t[3], t[1], &p1[0]) 217 g.f.mul(t[0], t[0], &p1[2]) 218 g.f.mul(t[1], t[1], &p2[2]) 219 g.f.mul(t[1], t[1], &p1[1]) 220 g.f.mul(t[0], t[0], &p2[1]) 221 return t[0].equal(t[1]) && t[2].equal(t[3]) 222 } 223 224 // InCorrectSubgroup checks whether given point is in correct subgroup. 225 func (g *G2) InCorrectSubgroup(p *PointG2) bool { 226 tmp := &PointG2{} 227 g.MulScalar(tmp, p, q) 228 return g.IsZero(tmp) 229 } 230 231 // IsOnCurve checks a G2 point is on curve. 232 func (g *G2) IsOnCurve(p *PointG2) bool { 233 if g.IsZero(p) { 234 return true 235 } 236 t := g.t 237 g.f.square(t[0], &p[1]) 238 g.f.square(t[1], &p[0]) 239 g.f.mul(t[1], t[1], &p[0]) 240 g.f.square(t[2], &p[2]) 241 g.f.square(t[3], t[2]) 242 g.f.mul(t[2], t[2], t[3]) 243 g.f.mul(t[2], b2, t[2]) 244 g.f.add(t[1], t[1], t[2]) 245 return t[0].equal(t[1]) 246 } 247 248 // IsAffine checks a G2 point whether it is in affine form. 249 func (g *G2) IsAffine(p *PointG2) bool { 250 return p[2].isOne() 251 } 252 253 // Affine calculates affine form of given G2 point. 254 func (g *G2) Affine(p *PointG2) *PointG2 { 255 if g.IsZero(p) { 256 return p 257 } 258 if !g.IsAffine(p) { 259 t := g.t 260 g.f.inverse(t[0], &p[2]) 261 g.f.square(t[1], t[0]) 262 g.f.mul(&p[0], &p[0], t[1]) 263 g.f.mul(t[0], t[0], t[1]) 264 g.f.mul(&p[1], &p[1], t[0]) 265 p[2].one() 266 } 267 return p 268 } 269 270 // Add adds two G2 points p1, p2 and assigns the result to point at first argument. 271 func (g *G2) Add(r, p1, p2 *PointG2) *PointG2 { 272 // http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl 273 if g.IsZero(p1) { 274 return r.Set(p2) 275 } 276 if g.IsZero(p2) { 277 return r.Set(p1) 278 } 279 t := g.t 280 g.f.square(t[7], &p1[2]) 281 g.f.mul(t[1], &p2[0], t[7]) 282 g.f.mul(t[2], &p1[2], t[7]) 283 g.f.mul(t[0], &p2[1], t[2]) 284 g.f.square(t[8], &p2[2]) 285 g.f.mul(t[3], &p1[0], t[8]) 286 g.f.mul(t[4], &p2[2], t[8]) 287 g.f.mul(t[2], &p1[1], t[4]) 288 if t[1].equal(t[3]) { 289 if t[0].equal(t[2]) { 290 return g.Double(r, p1) 291 } 292 return r.Zero() 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 }