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  }