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