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