github.com/snowblossomcoin/go-ethereum@v1.9.25/crypto/bls12381/fp12.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 fp12 struct {
    25  	fp12temp
    26  	fp6 *fp6
    27  }
    28  
    29  type fp12temp struct {
    30  	t2  [9]*fe2
    31  	t6  [5]*fe6
    32  	t12 *fe12
    33  }
    34  
    35  func newFp12Temp() fp12temp {
    36  	t2 := [9]*fe2{}
    37  	t6 := [5]*fe6{}
    38  	for i := 0; i < len(t2); i++ {
    39  		t2[i] = &fe2{}
    40  	}
    41  	for i := 0; i < len(t6); i++ {
    42  		t6[i] = &fe6{}
    43  	}
    44  	return fp12temp{t2, t6, &fe12{}}
    45  }
    46  
    47  func newFp12(fp6 *fp6) *fp12 {
    48  	t := newFp12Temp()
    49  	if fp6 == nil {
    50  		return &fp12{t, newFp6(nil)}
    51  	}
    52  	return &fp12{t, fp6}
    53  }
    54  
    55  func (e *fp12) fp2() *fp2 {
    56  	return e.fp6.fp2
    57  }
    58  
    59  func (e *fp12) fromBytes(in []byte) (*fe12, error) {
    60  	if len(in) != 576 {
    61  		return nil, errors.New("input string should be larger than 96 bytes")
    62  	}
    63  	fp6 := e.fp6
    64  	c1, err := fp6.fromBytes(in[:288])
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	c0, err := fp6.fromBytes(in[288:])
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	return &fe12{*c0, *c1}, nil
    73  }
    74  
    75  func (e *fp12) toBytes(a *fe12) []byte {
    76  	fp6 := e.fp6
    77  	out := make([]byte, 576)
    78  	copy(out[:288], fp6.toBytes(&a[1]))
    79  	copy(out[288:], fp6.toBytes(&a[0]))
    80  	return out
    81  }
    82  
    83  func (e *fp12) new() *fe12 {
    84  	return new(fe12)
    85  }
    86  
    87  func (e *fp12) zero() *fe12 {
    88  	return new(fe12)
    89  }
    90  
    91  func (e *fp12) one() *fe12 {
    92  	return new(fe12).one()
    93  }
    94  
    95  func (e *fp12) add(c, a, b *fe12) {
    96  	fp6 := e.fp6
    97  	fp6.add(&c[0], &a[0], &b[0])
    98  	fp6.add(&c[1], &a[1], &b[1])
    99  
   100  }
   101  
   102  func (e *fp12) double(c, a *fe12) {
   103  	fp6 := e.fp6
   104  	fp6.double(&c[0], &a[0])
   105  	fp6.double(&c[1], &a[1])
   106  }
   107  
   108  func (e *fp12) sub(c, a, b *fe12) {
   109  	fp6 := e.fp6
   110  	fp6.sub(&c[0], &a[0], &b[0])
   111  	fp6.sub(&c[1], &a[1], &b[1])
   112  
   113  }
   114  
   115  func (e *fp12) neg(c, a *fe12) {
   116  	fp6 := e.fp6
   117  	fp6.neg(&c[0], &a[0])
   118  	fp6.neg(&c[1], &a[1])
   119  }
   120  
   121  func (e *fp12) conjugate(c, a *fe12) {
   122  	fp6 := e.fp6
   123  	c[0].set(&a[0])
   124  	fp6.neg(&c[1], &a[1])
   125  }
   126  
   127  func (e *fp12) square(c, a *fe12) {
   128  	fp6, t := e.fp6, e.t6
   129  	fp6.add(t[0], &a[0], &a[1])
   130  	fp6.mul(t[2], &a[0], &a[1])
   131  	fp6.mulByNonResidue(t[1], &a[1])
   132  	fp6.addAssign(t[1], &a[0])
   133  	fp6.mulByNonResidue(t[3], t[2])
   134  	fp6.mulAssign(t[0], t[1])
   135  	fp6.subAssign(t[0], t[2])
   136  	fp6.sub(&c[0], t[0], t[3])
   137  	fp6.double(&c[1], t[2])
   138  }
   139  
   140  func (e *fp12) cyclotomicSquare(c, a *fe12) {
   141  	t, fp2 := e.t2, e.fp2()
   142  	e.fp4Square(t[3], t[4], &a[0][0], &a[1][1])
   143  	fp2.sub(t[2], t[3], &a[0][0])
   144  	fp2.doubleAssign(t[2])
   145  	fp2.add(&c[0][0], t[2], t[3])
   146  	fp2.add(t[2], t[4], &a[1][1])
   147  	fp2.doubleAssign(t[2])
   148  	fp2.add(&c[1][1], t[2], t[4])
   149  	e.fp4Square(t[3], t[4], &a[1][0], &a[0][2])
   150  	e.fp4Square(t[5], t[6], &a[0][1], &a[1][2])
   151  	fp2.sub(t[2], t[3], &a[0][1])
   152  	fp2.doubleAssign(t[2])
   153  	fp2.add(&c[0][1], t[2], t[3])
   154  	fp2.add(t[2], t[4], &a[1][2])
   155  	fp2.doubleAssign(t[2])
   156  	fp2.add(&c[1][2], t[2], t[4])
   157  	fp2.mulByNonResidue(t[3], t[6])
   158  	fp2.add(t[2], t[3], &a[1][0])
   159  	fp2.doubleAssign(t[2])
   160  	fp2.add(&c[1][0], t[2], t[3])
   161  	fp2.sub(t[2], t[5], &a[0][2])
   162  	fp2.doubleAssign(t[2])
   163  	fp2.add(&c[0][2], t[2], t[5])
   164  }
   165  
   166  func (e *fp12) mul(c, a, b *fe12) {
   167  	t, fp6 := e.t6, e.fp6
   168  	fp6.mul(t[1], &a[0], &b[0])
   169  	fp6.mul(t[2], &a[1], &b[1])
   170  	fp6.add(t[0], t[1], t[2])
   171  	fp6.mulByNonResidue(t[2], t[2])
   172  	fp6.add(t[3], t[1], t[2])
   173  	fp6.add(t[1], &a[0], &a[1])
   174  	fp6.add(t[2], &b[0], &b[1])
   175  	fp6.mulAssign(t[1], t[2])
   176  	c[0].set(t[3])
   177  	fp6.sub(&c[1], t[1], t[0])
   178  }
   179  
   180  func (e *fp12) mulAssign(a, b *fe12) {
   181  	t, fp6 := e.t6, e.fp6
   182  	fp6.mul(t[1], &a[0], &b[0])
   183  	fp6.mul(t[2], &a[1], &b[1])
   184  	fp6.add(t[0], t[1], t[2])
   185  	fp6.mulByNonResidue(t[2], t[2])
   186  	fp6.add(t[3], t[1], t[2])
   187  	fp6.add(t[1], &a[0], &a[1])
   188  	fp6.add(t[2], &b[0], &b[1])
   189  	fp6.mulAssign(t[1], t[2])
   190  	a[0].set(t[3])
   191  	fp6.sub(&a[1], t[1], t[0])
   192  }
   193  
   194  func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) {
   195  	t, fp2 := e.t2, e.fp2()
   196  	fp2.square(t[0], a0)
   197  	fp2.square(t[1], a1)
   198  	fp2.mulByNonResidue(t[2], t[1])
   199  	fp2.add(c0, t[2], t[0])
   200  	fp2.add(t[2], a0, a1)
   201  	fp2.squareAssign(t[2])
   202  	fp2.subAssign(t[2], t[0])
   203  	fp2.sub(c1, t[2], t[1])
   204  }
   205  
   206  func (e *fp12) inverse(c, a *fe12) {
   207  	fp6, t := e.fp6, e.t6
   208  	fp6.square(t[0], &a[0])
   209  	fp6.square(t[1], &a[1])
   210  	fp6.mulByNonResidue(t[1], t[1])
   211  	fp6.sub(t[1], t[0], t[1])
   212  	fp6.inverse(t[0], t[1])
   213  	fp6.mul(&c[0], &a[0], t[0])
   214  	fp6.mulAssign(t[0], &a[1])
   215  	fp6.neg(&c[1], t[0])
   216  }
   217  
   218  func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) {
   219  	fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0]
   220  	fp6.mulBy01(t[0], &a[0], c0, c1)
   221  	fp6.mulBy1(t[1], &a[1], c4)
   222  	fp2.add(t2, c1, c4)
   223  	fp6.add(t[2], &a[1], &a[0])
   224  	fp6.mulBy01Assign(t[2], c0, t2)
   225  	fp6.subAssign(t[2], t[0])
   226  	fp6.sub(&a[1], t[2], t[1])
   227  	fp6.mulByNonResidue(t[1], t[1])
   228  	fp6.add(&a[0], t[1], t[0])
   229  }
   230  
   231  func (e *fp12) exp(c, a *fe12, s *big.Int) {
   232  	z := e.one()
   233  	for i := s.BitLen() - 1; i >= 0; i-- {
   234  		e.square(z, z)
   235  		if s.Bit(i) == 1 {
   236  			e.mul(z, z, a)
   237  		}
   238  	}
   239  	c.set(z)
   240  }
   241  
   242  func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) {
   243  	z := e.one()
   244  	for i := s.BitLen() - 1; i >= 0; i-- {
   245  		e.cyclotomicSquare(z, z)
   246  		if s.Bit(i) == 1 {
   247  			e.mul(z, z, a)
   248  		}
   249  	}
   250  	c.set(z)
   251  }
   252  
   253  func (e *fp12) frobeniusMap(c, a *fe12, power uint) {
   254  	fp6 := e.fp6
   255  	fp6.frobeniusMap(&c[0], &a[0], power)
   256  	fp6.frobeniusMap(&c[1], &a[1], power)
   257  	switch power {
   258  	case 0:
   259  		return
   260  	case 6:
   261  		fp6.neg(&c[1], &c[1])
   262  	default:
   263  		fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power])
   264  	}
   265  }
   266  
   267  func (e *fp12) frobeniusMapAssign(a *fe12, power uint) {
   268  	fp6 := e.fp6
   269  	fp6.frobeniusMapAssign(&a[0], power)
   270  	fp6.frobeniusMapAssign(&a[1], power)
   271  	switch power {
   272  	case 0:
   273  		return
   274  	case 6:
   275  		fp6.neg(&a[1], &a[1])
   276  	default:
   277  		fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power])
   278  	}
   279  }