github.com/nova-foundation/go-ethereum@v1.0.1/crypto/bls12381/fp2.go (about)

     1  // Copyright 2020 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package bls12381
    18  
    19  import (
    20  	"errors"
    21  	"math/big"
    22  )
    23  
    24  type fp2Temp struct {
    25  	t [4]*fe
    26  }
    27  
    28  type fp2 struct {
    29  	fp2Temp
    30  }
    31  
    32  func newFp2Temp() fp2Temp {
    33  	t := [4]*fe{}
    34  	for i := 0; i < len(t); i++ {
    35  		t[i] = &fe{}
    36  	}
    37  	return fp2Temp{t}
    38  }
    39  
    40  func newFp2() *fp2 {
    41  	t := newFp2Temp()
    42  	return &fp2{t}
    43  }
    44  
    45  func (e *fp2) fromBytes(in []byte) (*fe2, error) {
    46  	if len(in) != 96 {
    47  		return nil, errors.New("length of input string should be 96 bytes")
    48  	}
    49  	c1, err := fromBytes(in[:48])
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	c0, err := fromBytes(in[48:])
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	return &fe2{*c0, *c1}, nil
    58  }
    59  
    60  func (e *fp2) toBytes(a *fe2) []byte {
    61  	out := make([]byte, 96)
    62  	copy(out[:48], toBytes(&a[1]))
    63  	copy(out[48:], toBytes(&a[0]))
    64  	return out
    65  }
    66  
    67  func (e *fp2) new() *fe2 {
    68  	return new(fe2).zero()
    69  }
    70  
    71  func (e *fp2) zero() *fe2 {
    72  	return new(fe2).zero()
    73  }
    74  
    75  func (e *fp2) one() *fe2 {
    76  	return new(fe2).one()
    77  }
    78  
    79  func (e *fp2) add(c, a, b *fe2) {
    80  	add(&c[0], &a[0], &b[0])
    81  	add(&c[1], &a[1], &b[1])
    82  }
    83  
    84  func (e *fp2) addAssign(a, b *fe2) {
    85  	addAssign(&a[0], &b[0])
    86  	addAssign(&a[1], &b[1])
    87  }
    88  
    89  func (e *fp2) ladd(c, a, b *fe2) {
    90  	ladd(&c[0], &a[0], &b[0])
    91  	ladd(&c[1], &a[1], &b[1])
    92  }
    93  
    94  func (e *fp2) double(c, a *fe2) {
    95  	double(&c[0], &a[0])
    96  	double(&c[1], &a[1])
    97  }
    98  
    99  func (e *fp2) doubleAssign(a *fe2) {
   100  	doubleAssign(&a[0])
   101  	doubleAssign(&a[1])
   102  }
   103  
   104  func (e *fp2) ldouble(c, a *fe2) {
   105  	ldouble(&c[0], &a[0])
   106  	ldouble(&c[1], &a[1])
   107  }
   108  
   109  func (e *fp2) sub(c, a, b *fe2) {
   110  	sub(&c[0], &a[0], &b[0])
   111  	sub(&c[1], &a[1], &b[1])
   112  }
   113  
   114  func (e *fp2) subAssign(c, a *fe2) {
   115  	subAssign(&c[0], &a[0])
   116  	subAssign(&c[1], &a[1])
   117  }
   118  
   119  func (e *fp2) neg(c, a *fe2) {
   120  	neg(&c[0], &a[0])
   121  	neg(&c[1], &a[1])
   122  }
   123  
   124  func (e *fp2) mul(c, a, b *fe2) {
   125  	t := e.t
   126  	mul(t[1], &a[0], &b[0])
   127  	mul(t[2], &a[1], &b[1])
   128  	add(t[0], &a[0], &a[1])
   129  	add(t[3], &b[0], &b[1])
   130  	sub(&c[0], t[1], t[2])
   131  	addAssign(t[1], t[2])
   132  	mul(t[0], t[0], t[3])
   133  	sub(&c[1], t[0], t[1])
   134  }
   135  
   136  func (e *fp2) mulAssign(a, b *fe2) {
   137  	t := e.t
   138  	mul(t[1], &a[0], &b[0])
   139  	mul(t[2], &a[1], &b[1])
   140  	add(t[0], &a[0], &a[1])
   141  	add(t[3], &b[0], &b[1])
   142  	sub(&a[0], t[1], t[2])
   143  	addAssign(t[1], t[2])
   144  	mul(t[0], t[0], t[3])
   145  	sub(&a[1], t[0], t[1])
   146  }
   147  
   148  func (e *fp2) square(c, a *fe2) {
   149  	t := e.t
   150  	ladd(t[0], &a[0], &a[1])
   151  	sub(t[1], &a[0], &a[1])
   152  	ldouble(t[2], &a[0])
   153  	mul(&c[0], t[0], t[1])
   154  	mul(&c[1], t[2], &a[1])
   155  }
   156  
   157  func (e *fp2) squareAssign(a *fe2) {
   158  	t := e.t
   159  	ladd(t[0], &a[0], &a[1])
   160  	sub(t[1], &a[0], &a[1])
   161  	ldouble(t[2], &a[0])
   162  	mul(&a[0], t[0], t[1])
   163  	mul(&a[1], t[2], &a[1])
   164  }
   165  
   166  func (e *fp2) mulByNonResidue(c, a *fe2) {
   167  	t := e.t
   168  	sub(t[0], &a[0], &a[1])
   169  	add(&c[1], &a[0], &a[1])
   170  	c[0].set(t[0])
   171  }
   172  
   173  func (e *fp2) mulByB(c, a *fe2) {
   174  	t := e.t
   175  	double(t[0], &a[0])
   176  	double(t[1], &a[1])
   177  	doubleAssign(t[0])
   178  	doubleAssign(t[1])
   179  	sub(&c[0], t[0], t[1])
   180  	add(&c[1], t[0], t[1])
   181  }
   182  
   183  func (e *fp2) inverse(c, a *fe2) {
   184  	t := e.t
   185  	square(t[0], &a[0])
   186  	square(t[1], &a[1])
   187  	addAssign(t[0], t[1])
   188  	inverse(t[0], t[0])
   189  	mul(&c[0], &a[0], t[0])
   190  	mul(t[0], t[0], &a[1])
   191  	neg(&c[1], t[0])
   192  }
   193  
   194  func (e *fp2) mulByFq(c, a *fe2, b *fe) {
   195  	mul(&c[0], &a[0], b)
   196  	mul(&c[1], &a[1], b)
   197  }
   198  
   199  func (e *fp2) exp(c, a *fe2, s *big.Int) {
   200  	z := e.one()
   201  	for i := s.BitLen() - 1; i >= 0; i-- {
   202  		e.square(z, z)
   203  		if s.Bit(i) == 1 {
   204  			e.mul(z, z, a)
   205  		}
   206  	}
   207  	c.set(z)
   208  }
   209  
   210  func (e *fp2) frobeniusMap(c, a *fe2, power uint) {
   211  	c[0].set(&a[0])
   212  	if power%2 == 1 {
   213  		neg(&c[1], &a[1])
   214  		return
   215  	}
   216  	c[1].set(&a[1])
   217  }
   218  
   219  func (e *fp2) frobeniusMapAssign(a *fe2, power uint) {
   220  	if power%2 == 1 {
   221  		neg(&a[1], &a[1])
   222  		return
   223  	}
   224  }
   225  
   226  func (e *fp2) sqrt(c, a *fe2) bool {
   227  	u, x0, a1, alpha := &fe2{}, &fe2{}, &fe2{}, &fe2{}
   228  	u.set(a)
   229  	e.exp(a1, a, pMinus3Over4)
   230  	e.square(alpha, a1)
   231  	e.mul(alpha, alpha, a)
   232  	e.mul(x0, a1, a)
   233  	if alpha.equal(negativeOne2) {
   234  		neg(&c[0], &x0[1])
   235  		c[1].set(&x0[0])
   236  		return true
   237  	}
   238  	e.add(alpha, alpha, e.one())
   239  	e.exp(alpha, alpha, pMinus1Over2)
   240  	e.mul(c, alpha, x0)
   241  	e.square(alpha, c)
   242  	return alpha.equal(u)
   243  }
   244  
   245  func (e *fp2) isQuadraticNonResidue(a *fe2) bool {
   246  	// https://github.com/leovt/constructible/wiki/Taking-Square-Roots-in-quadratic-extension-Fields
   247  	c0, c1 := new(fe), new(fe)
   248  	square(c0, &a[0])
   249  	square(c1, &a[1])
   250  	add(c1, c1, c0)
   251  	return isQuadraticNonResidue(c1)
   252  }