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