github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/google/gfp2.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  // For details of the algorithms used, see "Multiplication and Squaring on
    21  // Pairing-Friendly Fields, Devegili et al.
    22  // http://eprint.iacr.org/2006/471.pdf.
    23  
    24  import (
    25  	"math/big"
    26  )
    27  
    28  // gfP2 implements a field of size p² as a quadratic extension of the base
    29  // field where i²=-1.
    30  type gfP2 struct {
    31  	x, y *big.Int // value is xi+y.
    32  }
    33  
    34  func newGFp2(pool *bnPool) *gfP2 {
    35  	return &gfP2{pool.Get(), pool.Get()}
    36  }
    37  
    38  func (e *gfP2) String() string {
    39  	x := new(big.Int).Mod(e.x, P)
    40  	y := new(big.Int).Mod(e.y, P)
    41  	return "(" + x.String() + "," + y.String() + ")"
    42  }
    43  
    44  func (e *gfP2) Put(pool *bnPool) {
    45  	pool.Put(e.x)
    46  	pool.Put(e.y)
    47  }
    48  
    49  func (e *gfP2) Set(a *gfP2) *gfP2 {
    50  	e.x.Set(a.x)
    51  	e.y.Set(a.y)
    52  	return e
    53  }
    54  
    55  func (e *gfP2) SetZero() *gfP2 {
    56  	e.x.SetInt64(0)
    57  	e.y.SetInt64(0)
    58  	return e
    59  }
    60  
    61  func (e *gfP2) SetOne() *gfP2 {
    62  	e.x.SetInt64(0)
    63  	e.y.SetInt64(1)
    64  	return e
    65  }
    66  
    67  func (e *gfP2) Minimal() {
    68  	if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 {
    69  		e.x.Mod(e.x, P)
    70  	}
    71  	if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 {
    72  		e.y.Mod(e.y, P)
    73  	}
    74  }
    75  
    76  func (e *gfP2) IsZero() bool {
    77  	return e.x.Sign() == 0 && e.y.Sign() == 0
    78  }
    79  
    80  func (e *gfP2) IsOne() bool {
    81  	if e.x.Sign() != 0 {
    82  		return false
    83  	}
    84  	words := e.y.Bits()
    85  	return len(words) == 1 && words[0] == 1
    86  }
    87  
    88  func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
    89  	e.y.Set(a.y)
    90  	e.x.Neg(a.x)
    91  	return e
    92  }
    93  
    94  func (e *gfP2) Negative(a *gfP2) *gfP2 {
    95  	e.x.Neg(a.x)
    96  	e.y.Neg(a.y)
    97  	return e
    98  }
    99  
   100  func (e *gfP2) Add(a, b *gfP2) *gfP2 {
   101  	e.x.Add(a.x, b.x)
   102  	e.y.Add(a.y, b.y)
   103  	return e
   104  }
   105  
   106  func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
   107  	e.x.Sub(a.x, b.x)
   108  	e.y.Sub(a.y, b.y)
   109  	return e
   110  }
   111  
   112  func (e *gfP2) Double(a *gfP2) *gfP2 {
   113  	e.x.Lsh(a.x, 1)
   114  	e.y.Lsh(a.y, 1)
   115  	return e
   116  }
   117  
   118  func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
   119  	sum := newGFp2(pool)
   120  	sum.SetOne()
   121  	t := newGFp2(pool)
   122  
   123  	for i := power.BitLen() - 1; i >= 0; i-- {
   124  		t.Square(sum, pool)
   125  		if power.Bit(i) != 0 {
   126  			sum.Mul(t, a, pool)
   127  		} else {
   128  			sum.Set(t)
   129  		}
   130  	}
   131  
   132  	c.Set(sum)
   133  
   134  	sum.Put(pool)
   135  	t.Put(pool)
   136  
   137  	return c
   138  }
   139  
   140  // See "Multiplication and Squaring in Pairing-Friendly Fields",
   141  // http://eprint.iacr.org/2006/471.pdf
   142  func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
   143  	tx := pool.Get().Mul(a.x, b.y)
   144  	t := pool.Get().Mul(b.x, a.y)
   145  	tx.Add(tx, t)
   146  	tx.Mod(tx, P)
   147  
   148  	ty := pool.Get().Mul(a.y, b.y)
   149  	t.Mul(a.x, b.x)
   150  	ty.Sub(ty, t)
   151  	e.y.Mod(ty, P)
   152  	e.x.Set(tx)
   153  
   154  	pool.Put(tx)
   155  	pool.Put(ty)
   156  	pool.Put(t)
   157  
   158  	return e
   159  }
   160  
   161  func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
   162  	e.x.Mul(a.x, b)
   163  	e.y.Mul(a.y, b)
   164  	return e
   165  }
   166  
   167  // MulXi sets e=ξa where ξ=i+9 and then returns e.
   168  func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
   169  	// (xi+y)(i+3) = (9x+y)i+(9y-x)
   170  	tx := pool.Get().Lsh(a.x, 3)
   171  	tx.Add(tx, a.x)
   172  	tx.Add(tx, a.y)
   173  
   174  	ty := pool.Get().Lsh(a.y, 3)
   175  	ty.Add(ty, a.y)
   176  	ty.Sub(ty, a.x)
   177  
   178  	e.x.Set(tx)
   179  	e.y.Set(ty)
   180  
   181  	pool.Put(tx)
   182  	pool.Put(ty)
   183  
   184  	return e
   185  }
   186  
   187  func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
   188  	// Complex squaring algorithm:
   189  	// (xi+b)² = (x+y)(y-x) + 2*i*x*y
   190  	t1 := pool.Get().Sub(a.y, a.x)
   191  	t2 := pool.Get().Add(a.x, a.y)
   192  	ty := pool.Get().Mul(t1, t2)
   193  	ty.Mod(ty, P)
   194  
   195  	t1.Mul(a.x, a.y)
   196  	t1.Lsh(t1, 1)
   197  
   198  	e.x.Mod(t1, P)
   199  	e.y.Set(ty)
   200  
   201  	pool.Put(t1)
   202  	pool.Put(t2)
   203  	pool.Put(ty)
   204  
   205  	return e
   206  }
   207  
   208  func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
   209  	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
   210  	// ftp://136.206.11.249/pub/crypto/pairings.pdf
   211  	t := pool.Get()
   212  	t.Mul(a.y, a.y)
   213  	t2 := pool.Get()
   214  	t2.Mul(a.x, a.x)
   215  	t.Add(t, t2)
   216  
   217  	inv := pool.Get()
   218  	inv.ModInverse(t, P)
   219  
   220  	e.x.Neg(a.x)
   221  	e.x.Mul(e.x, inv)
   222  	e.x.Mod(e.x, P)
   223  
   224  	e.y.Mul(a.y, inv)
   225  	e.y.Mod(e.y, P)
   226  
   227  	pool.Put(t)
   228  	pool.Put(t2)
   229  	pool.Put(inv)
   230  
   231  	return e
   232  }
   233  
   234  func (e *gfP2) Real() *big.Int {
   235  	return e.x
   236  }
   237  
   238  func (e *gfP2) Imag() *big.Int {
   239  	return e.y
   240  }