github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/google/gfp12.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  // gfP12 implements the field of size p¹² as a quadratic extension of gfP6
    29  // where ω²=τ.
    30  type gfP12 struct {
    31  	x, y *gfP6 // value is xω + y
    32  }
    33  
    34  func newGFp12(pool *bnPool) *gfP12 {
    35  	return &gfP12{newGFp6(pool), newGFp6(pool)}
    36  }
    37  
    38  func (e *gfP12) String() string {
    39  	return "(" + e.x.String() + "," + e.y.String() + ")"
    40  }
    41  
    42  func (e *gfP12) Put(pool *bnPool) {
    43  	e.x.Put(pool)
    44  	e.y.Put(pool)
    45  }
    46  
    47  func (e *gfP12) Set(a *gfP12) *gfP12 {
    48  	e.x.Set(a.x)
    49  	e.y.Set(a.y)
    50  	return e
    51  }
    52  
    53  func (e *gfP12) SetZero() *gfP12 {
    54  	e.x.SetZero()
    55  	e.y.SetZero()
    56  	return e
    57  }
    58  
    59  func (e *gfP12) SetOne() *gfP12 {
    60  	e.x.SetZero()
    61  	e.y.SetOne()
    62  	return e
    63  }
    64  
    65  func (e *gfP12) Minimal() {
    66  	e.x.Minimal()
    67  	e.y.Minimal()
    68  }
    69  
    70  func (e *gfP12) IsZero() bool {
    71  	e.Minimal()
    72  	return e.x.IsZero() && e.y.IsZero()
    73  }
    74  
    75  func (e *gfP12) IsOne() bool {
    76  	e.Minimal()
    77  	return e.x.IsZero() && e.y.IsOne()
    78  }
    79  
    80  func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
    81  	e.x.Negative(a.x)
    82  	e.y.Set(a.y)
    83  	return a
    84  }
    85  
    86  func (e *gfP12) Negative(a *gfP12) *gfP12 {
    87  	e.x.Negative(a.x)
    88  	e.y.Negative(a.y)
    89  	return e
    90  }
    91  
    92  // Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
    93  func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
    94  	e.x.Frobenius(a.x, pool)
    95  	e.y.Frobenius(a.y, pool)
    96  	e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
    97  	return e
    98  }
    99  
   100  // FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
   101  func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
   102  	e.x.FrobeniusP2(a.x)
   103  	e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
   104  	e.y.FrobeniusP2(a.y)
   105  	return e
   106  }
   107  
   108  func (e *gfP12) Add(a, b *gfP12) *gfP12 {
   109  	e.x.Add(a.x, b.x)
   110  	e.y.Add(a.y, b.y)
   111  	return e
   112  }
   113  
   114  func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
   115  	e.x.Sub(a.x, b.x)
   116  	e.y.Sub(a.y, b.y)
   117  	return e
   118  }
   119  
   120  func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
   121  	tx := newGFp6(pool)
   122  	tx.Mul(a.x, b.y, pool)
   123  	t := newGFp6(pool)
   124  	t.Mul(b.x, a.y, pool)
   125  	tx.Add(tx, t)
   126  
   127  	ty := newGFp6(pool)
   128  	ty.Mul(a.y, b.y, pool)
   129  	t.Mul(a.x, b.x, pool)
   130  	t.MulTau(t, pool)
   131  	e.y.Add(ty, t)
   132  	e.x.Set(tx)
   133  
   134  	tx.Put(pool)
   135  	ty.Put(pool)
   136  	t.Put(pool)
   137  	return e
   138  }
   139  
   140  func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
   141  	e.x.Mul(e.x, b, pool)
   142  	e.y.Mul(e.y, b, pool)
   143  	return e
   144  }
   145  
   146  func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
   147  	sum := newGFp12(pool)
   148  	sum.SetOne()
   149  	t := newGFp12(pool)
   150  
   151  	for i := power.BitLen() - 1; i >= 0; i-- {
   152  		t.Square(sum, pool)
   153  		if power.Bit(i) != 0 {
   154  			sum.Mul(t, a, pool)
   155  		} else {
   156  			sum.Set(t)
   157  		}
   158  	}
   159  
   160  	c.Set(sum)
   161  
   162  	sum.Put(pool)
   163  	t.Put(pool)
   164  
   165  	return c
   166  }
   167  
   168  func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
   169  	// Complex squaring algorithm
   170  	v0 := newGFp6(pool)
   171  	v0.Mul(a.x, a.y, pool)
   172  
   173  	t := newGFp6(pool)
   174  	t.MulTau(a.x, pool)
   175  	t.Add(a.y, t)
   176  	ty := newGFp6(pool)
   177  	ty.Add(a.x, a.y)
   178  	ty.Mul(ty, t, pool)
   179  	ty.Sub(ty, v0)
   180  	t.MulTau(v0, pool)
   181  	ty.Sub(ty, t)
   182  
   183  	e.y.Set(ty)
   184  	e.x.Double(v0)
   185  
   186  	v0.Put(pool)
   187  	t.Put(pool)
   188  	ty.Put(pool)
   189  
   190  	return e
   191  }
   192  
   193  func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
   194  	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
   195  	// ftp://136.206.11.249/pub/crypto/pairings.pdf
   196  	t1 := newGFp6(pool)
   197  	t2 := newGFp6(pool)
   198  
   199  	t1.Square(a.x, pool)
   200  	t2.Square(a.y, pool)
   201  	t1.MulTau(t1, pool)
   202  	t1.Sub(t2, t1)
   203  	t2.Invert(t1, pool)
   204  
   205  	e.x.Negative(a.x)
   206  	e.y.Set(a.y)
   207  	e.MulScalar(e, t2, pool)
   208  
   209  	t1.Put(pool)
   210  	t2.Put(pool)
   211  
   212  	return e
   213  }