github.com/c2s/go-ethereum@v1.9.7/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 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  	cneg := newTwistPoint(pool)
    84  	cneg.Mul(c, Order, pool)
    85  	return cneg.z.IsZero()
    86  }
    87  
    88  func (c *twistPoint) SetInfinity() {
    89  	c.z.SetZero()
    90  }
    91  
    92  func (c *twistPoint) IsInfinity() bool {
    93  	return c.z.IsZero()
    94  }
    95  
    96  func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
    97  	// For additional comments, see the same function in curve.go.
    98  
    99  	if a.IsInfinity() {
   100  		c.Set(b)
   101  		return
   102  	}
   103  	if b.IsInfinity() {
   104  		c.Set(a)
   105  		return
   106  	}
   107  
   108  	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
   109  	z1z1 := newGFp2(pool).Square(a.z, pool)
   110  	z2z2 := newGFp2(pool).Square(b.z, pool)
   111  	u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
   112  	u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
   113  
   114  	t := newGFp2(pool).Mul(b.z, z2z2, pool)
   115  	s1 := newGFp2(pool).Mul(a.y, t, pool)
   116  
   117  	t.Mul(a.z, z1z1, pool)
   118  	s2 := newGFp2(pool).Mul(b.y, t, pool)
   119  
   120  	h := newGFp2(pool).Sub(u2, u1)
   121  	xEqual := h.IsZero()
   122  
   123  	t.Add(h, h)
   124  	i := newGFp2(pool).Square(t, pool)
   125  	j := newGFp2(pool).Mul(h, i, pool)
   126  
   127  	t.Sub(s2, s1)
   128  	yEqual := t.IsZero()
   129  	if xEqual && yEqual {
   130  		c.Double(a, pool)
   131  		return
   132  	}
   133  	r := newGFp2(pool).Add(t, t)
   134  
   135  	v := newGFp2(pool).Mul(u1, i, pool)
   136  
   137  	t4 := newGFp2(pool).Square(r, pool)
   138  	t.Add(v, v)
   139  	t6 := newGFp2(pool).Sub(t4, j)
   140  	c.x.Sub(t6, t)
   141  
   142  	t.Sub(v, c.x)       // t7
   143  	t4.Mul(s1, j, pool) // t8
   144  	t6.Add(t4, t4)      // t9
   145  	t4.Mul(r, t, pool)  // t10
   146  	c.y.Sub(t4, t6)
   147  
   148  	t.Add(a.z, b.z)    // t11
   149  	t4.Square(t, pool) // t12
   150  	t.Sub(t4, z1z1)    // t13
   151  	t4.Sub(t, z2z2)    // t14
   152  	c.z.Mul(t4, h, pool)
   153  
   154  	z1z1.Put(pool)
   155  	z2z2.Put(pool)
   156  	u1.Put(pool)
   157  	u2.Put(pool)
   158  	t.Put(pool)
   159  	s1.Put(pool)
   160  	s2.Put(pool)
   161  	h.Put(pool)
   162  	i.Put(pool)
   163  	j.Put(pool)
   164  	r.Put(pool)
   165  	v.Put(pool)
   166  	t4.Put(pool)
   167  	t6.Put(pool)
   168  }
   169  
   170  func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
   171  	// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
   172  	A := newGFp2(pool).Square(a.x, pool)
   173  	B := newGFp2(pool).Square(a.y, pool)
   174  	C_ := newGFp2(pool).Square(B, pool)
   175  
   176  	t := newGFp2(pool).Add(a.x, B)
   177  	t2 := newGFp2(pool).Square(t, pool)
   178  	t.Sub(t2, A)
   179  	t2.Sub(t, C_)
   180  	d := newGFp2(pool).Add(t2, t2)
   181  	t.Add(A, A)
   182  	e := newGFp2(pool).Add(t, A)
   183  	f := newGFp2(pool).Square(e, pool)
   184  
   185  	t.Add(d, d)
   186  	c.x.Sub(f, t)
   187  
   188  	t.Add(C_, C_)
   189  	t2.Add(t, t)
   190  	t.Add(t2, t2)
   191  	c.y.Sub(d, c.x)
   192  	t2.Mul(e, c.y, pool)
   193  	c.y.Sub(t2, t)
   194  
   195  	t.Mul(a.y, a.z, pool)
   196  	c.z.Add(t, t)
   197  
   198  	A.Put(pool)
   199  	B.Put(pool)
   200  	C_.Put(pool)
   201  	t.Put(pool)
   202  	t2.Put(pool)
   203  	d.Put(pool)
   204  	e.Put(pool)
   205  	f.Put(pool)
   206  }
   207  
   208  func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
   209  	sum := newTwistPoint(pool)
   210  	sum.SetInfinity()
   211  	t := newTwistPoint(pool)
   212  
   213  	for i := scalar.BitLen(); i >= 0; i-- {
   214  		t.Double(sum, pool)
   215  		if scalar.Bit(i) != 0 {
   216  			sum.Add(t, a, pool)
   217  		} else {
   218  			sum.Set(t)
   219  		}
   220  	}
   221  
   222  	c.Set(sum)
   223  	sum.Put(pool)
   224  	t.Put(pool)
   225  	return c
   226  }
   227  
   228  // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets
   229  // c to 0 : 1 : 0.
   230  func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
   231  	if c.z.IsOne() {
   232  		return c
   233  	}
   234  	if c.IsInfinity() {
   235  		c.x.SetZero()
   236  		c.y.SetOne()
   237  		c.z.SetZero()
   238  		c.t.SetZero()
   239  		return c
   240  	}
   241  	zInv := newGFp2(pool).Invert(c.z, pool)
   242  	t := newGFp2(pool).Mul(c.y, zInv, pool)
   243  	zInv2 := newGFp2(pool).Square(zInv, pool)
   244  	c.y.Mul(t, zInv2, pool)
   245  	t.Mul(c.x, zInv2, pool)
   246  	c.x.Set(t)
   247  	c.z.SetOne()
   248  	c.t.SetOne()
   249  
   250  	zInv.Put(pool)
   251  	t.Put(pool)
   252  	zInv2.Put(pool)
   253  
   254  	return c
   255  }
   256  
   257  func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
   258  	c.x.Set(a.x)
   259  	c.y.SetZero()
   260  	c.y.Sub(c.y, a.y)
   261  	c.z.Set(a.z)
   262  	c.t.SetZero()
   263  }