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