github.com/ethereum/go-ethereum@v1.16.1/crypto/bn256/google/twist.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package bn256
     6  
     7  import (
     8  	"math/big"
     9  )
    10  
    11  // twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
    12  // kept in Jacobian form and t=z² when valid. The group G₂ is the set of
    13  // n-torsion points of this curve over GF(p²) (where n = Order)
    14  type twistPoint struct {
    15  	x, y, z, t *gfP2
    16  }
    17  
    18  var twistB = &gfP2{
    19  	bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"),
    20  	bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
    21  }
    22  
    23  // twistGen is the generator of group G₂.
    24  var twistGen = &twistPoint{
    25  	&gfP2{
    26  		bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"),
    27  		bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
    28  	},
    29  	&gfP2{
    30  		bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"),
    31  		bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
    32  	},
    33  	&gfP2{
    34  		bigFromBase10("0"),
    35  		bigFromBase10("1"),
    36  	},
    37  	&gfP2{
    38  		bigFromBase10("0"),
    39  		bigFromBase10("1"),
    40  	},
    41  }
    42  
    43  func newTwistPoint(pool *bnPool) *twistPoint {
    44  	return &twistPoint{
    45  		newGFp2(pool),
    46  		newGFp2(pool),
    47  		newGFp2(pool),
    48  		newGFp2(pool),
    49  	}
    50  }
    51  
    52  func (c *twistPoint) String() string {
    53  	return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
    54  }
    55  
    56  func (c *twistPoint) Put(pool *bnPool) {
    57  	c.x.Put(pool)
    58  	c.y.Put(pool)
    59  	c.z.Put(pool)
    60  	c.t.Put(pool)
    61  }
    62  
    63  func (c *twistPoint) Set(a *twistPoint) {
    64  	c.x.Set(a.x)
    65  	c.y.Set(a.y)
    66  	c.z.Set(a.z)
    67  	c.t.Set(a.t)
    68  }
    69  
    70  // IsOnCurve returns true iff c is on the curve and is in the correct subgroup, where c must be in affine form.
    71  func (c *twistPoint) IsOnCurve() bool {
    72  	pool := new(bnPool)
    73  	yy := newGFp2(pool).Square(c.y, pool)
    74  	xxx := newGFp2(pool).Square(c.x, pool)
    75  	xxx.Mul(xxx, c.x, pool)
    76  	yy.Sub(yy, xxx)
    77  	yy.Sub(yy, twistB)
    78  	yy.Minimal()
    79  
    80  	if yy.x.Sign() != 0 || yy.y.Sign() != 0 {
    81  		return false
    82  	}
    83  	// Subgroup check: multiply the point by the group order and
    84  	// verify that it becomes the point at infinity.
    85  	cneg := newTwistPoint(pool)
    86  	cneg.Mul(c, Order, pool)
    87  	return cneg.z.IsZero()
    88  }
    89  
    90  func (c *twistPoint) SetInfinity() {
    91  	c.z.SetZero()
    92  }
    93  
    94  func (c *twistPoint) IsInfinity() bool {
    95  	return c.z.IsZero()
    96  }
    97  
    98  func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
    99  	// For additional comments, see the same function in curve.go.
   100  
   101  	if a.IsInfinity() {
   102  		c.Set(b)
   103  		return
   104  	}
   105  	if b.IsInfinity() {
   106  		c.Set(a)
   107  		return
   108  	}
   109  
   110  	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
   111  	z1z1 := newGFp2(pool).Square(a.z, pool)
   112  	z2z2 := newGFp2(pool).Square(b.z, pool)
   113  	u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
   114  	u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
   115  
   116  	t := newGFp2(pool).Mul(b.z, z2z2, pool)
   117  	s1 := newGFp2(pool).Mul(a.y, t, pool)
   118  
   119  	t.Mul(a.z, z1z1, pool)
   120  	s2 := newGFp2(pool).Mul(b.y, t, pool)
   121  
   122  	h := newGFp2(pool).Sub(u2, u1)
   123  	xEqual := h.IsZero()
   124  
   125  	t.Add(h, h)
   126  	i := newGFp2(pool).Square(t, pool)
   127  	j := newGFp2(pool).Mul(h, i, pool)
   128  
   129  	t.Sub(s2, s1)
   130  	yEqual := t.IsZero()
   131  	if xEqual && yEqual {
   132  		c.Double(a, pool)
   133  		return
   134  	}
   135  	r := newGFp2(pool).Add(t, t)
   136  
   137  	v := newGFp2(pool).Mul(u1, i, pool)
   138  
   139  	t4 := newGFp2(pool).Square(r, pool)
   140  	t.Add(v, v)
   141  	t6 := newGFp2(pool).Sub(t4, j)
   142  	c.x.Sub(t6, t)
   143  
   144  	t.Sub(v, c.x)       // t7
   145  	t4.Mul(s1, j, pool) // t8
   146  	t6.Add(t4, t4)      // t9
   147  	t4.Mul(r, t, pool)  // t10
   148  	c.y.Sub(t4, t6)
   149  
   150  	t.Add(a.z, b.z)    // t11
   151  	t4.Square(t, pool) // t12
   152  	t.Sub(t4, z1z1)    // t13
   153  	t4.Sub(t, z2z2)    // t14
   154  	c.z.Mul(t4, h, pool)
   155  
   156  	z1z1.Put(pool)
   157  	z2z2.Put(pool)
   158  	u1.Put(pool)
   159  	u2.Put(pool)
   160  	t.Put(pool)
   161  	s1.Put(pool)
   162  	s2.Put(pool)
   163  	h.Put(pool)
   164  	i.Put(pool)
   165  	j.Put(pool)
   166  	r.Put(pool)
   167  	v.Put(pool)
   168  	t4.Put(pool)
   169  	t6.Put(pool)
   170  }
   171  
   172  func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
   173  	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
   174  	A := newGFp2(pool).Square(a.x, pool)
   175  	B := newGFp2(pool).Square(a.y, pool)
   176  	C_ := newGFp2(pool).Square(B, pool)
   177  
   178  	t := newGFp2(pool).Add(a.x, B)
   179  	t2 := newGFp2(pool).Square(t, pool)
   180  	t.Sub(t2, A)
   181  	t2.Sub(t, C_)
   182  	d := newGFp2(pool).Add(t2, t2)
   183  	t.Add(A, A)
   184  	e := newGFp2(pool).Add(t, A)
   185  	f := newGFp2(pool).Square(e, pool)
   186  
   187  	t.Add(d, d)
   188  	c.x.Sub(f, t)
   189  
   190  	t.Add(C_, C_)
   191  	t2.Add(t, t)
   192  	t.Add(t2, t2)
   193  	c.y.Sub(d, c.x)
   194  	t2.Mul(e, c.y, pool)
   195  	c.y.Sub(t2, t)
   196  
   197  	t.Mul(a.y, a.z, pool)
   198  	c.z.Add(t, t)
   199  
   200  	A.Put(pool)
   201  	B.Put(pool)
   202  	C_.Put(pool)
   203  	t.Put(pool)
   204  	t2.Put(pool)
   205  	d.Put(pool)
   206  	e.Put(pool)
   207  	f.Put(pool)
   208  }
   209  
   210  func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
   211  	sum := newTwistPoint(pool)
   212  	sum.SetInfinity()
   213  	t := newTwistPoint(pool)
   214  
   215  	for i := scalar.BitLen(); i >= 0; i-- {
   216  		t.Double(sum, pool)
   217  		if scalar.Bit(i) != 0 {
   218  			sum.Add(t, a, pool)
   219  		} else {
   220  			sum.Set(t)
   221  		}
   222  	}
   223  
   224  	c.Set(sum)
   225  	sum.Put(pool)
   226  	t.Put(pool)
   227  	return c
   228  }
   229  
   230  // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
   231  // c to 0 : 1 : 0.
   232  func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
   233  	if c.z.IsOne() {
   234  		return c
   235  	}
   236  	if c.IsInfinity() {
   237  		c.x.SetZero()
   238  		c.y.SetOne()
   239  		c.z.SetZero()
   240  		c.t.SetZero()
   241  		return c
   242  	}
   243  	zInv := newGFp2(pool).Invert(c.z, pool)
   244  	t := newGFp2(pool).Mul(c.y, zInv, pool)
   245  	zInv2 := newGFp2(pool).Square(zInv, pool)
   246  	c.y.Mul(t, zInv2, pool)
   247  	t.Mul(c.x, zInv2, pool)
   248  	c.x.Set(t)
   249  	c.z.SetOne()
   250  	c.t.SetOne()
   251  
   252  	zInv.Put(pool)
   253  	t.Put(pool)
   254  	zInv2.Put(pool)
   255  
   256  	return c
   257  }
   258  
   259  func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
   260  	c.x.Set(a.x)
   261  	c.y.SetZero()
   262  	c.y.Sub(c.y, a.y)
   263  	c.z.Set(a.z)
   264  	c.t.SetZero()
   265  }