github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/google/twist.go (about)

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