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