github.com/klaytn/klaytn@v1.12.1/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  func (e *fp12) double(c, a *fe12) {
   102  	fp6 := e.fp6
   103  	fp6.double(&c[0], &a[0])
   104  	fp6.double(&c[1], &a[1])
   105  }
   106  
   107  func (e *fp12) sub(c, a, b *fe12) {
   108  	fp6 := e.fp6
   109  	fp6.sub(&c[0], &a[0], &b[0])
   110  	fp6.sub(&c[1], &a[1], &b[1])
   111  }
   112  
   113  func (e *fp12) neg(c, a *fe12) {
   114  	fp6 := e.fp6
   115  	fp6.neg(&c[0], &a[0])
   116  	fp6.neg(&c[1], &a[1])
   117  }
   118  
   119  func (e *fp12) conjugate(c, a *fe12) {
   120  	fp6 := e.fp6
   121  	c[0].set(&a[0])
   122  	fp6.neg(&c[1], &a[1])
   123  }
   124  
   125  func (e *fp12) square(c, a *fe12) {
   126  	fp6, t := e.fp6, e.t6
   127  	fp6.add(t[0], &a[0], &a[1])
   128  	fp6.mul(t[2], &a[0], &a[1])
   129  	fp6.mulByNonResidue(t[1], &a[1])
   130  	fp6.addAssign(t[1], &a[0])
   131  	fp6.mulByNonResidue(t[3], t[2])
   132  	fp6.mulAssign(t[0], t[1])
   133  	fp6.subAssign(t[0], t[2])
   134  	fp6.sub(&c[0], t[0], t[3])
   135  	fp6.double(&c[1], t[2])
   136  }
   137  
   138  func (e *fp12) cyclotomicSquare(c, a *fe12) {
   139  	t, fp2 := e.t2, e.fp2()
   140  	e.fp4Square(t[3], t[4], &a[0][0], &a[1][1])
   141  	fp2.sub(t[2], t[3], &a[0][0])
   142  	fp2.doubleAssign(t[2])
   143  	fp2.add(&c[0][0], t[2], t[3])
   144  	fp2.add(t[2], t[4], &a[1][1])
   145  	fp2.doubleAssign(t[2])
   146  	fp2.add(&c[1][1], t[2], t[4])
   147  	e.fp4Square(t[3], t[4], &a[1][0], &a[0][2])
   148  	e.fp4Square(t[5], t[6], &a[0][1], &a[1][2])
   149  	fp2.sub(t[2], t[3], &a[0][1])
   150  	fp2.doubleAssign(t[2])
   151  	fp2.add(&c[0][1], t[2], t[3])
   152  	fp2.add(t[2], t[4], &a[1][2])
   153  	fp2.doubleAssign(t[2])
   154  	fp2.add(&c[1][2], t[2], t[4])
   155  	fp2.mulByNonResidue(t[3], t[6])
   156  	fp2.add(t[2], t[3], &a[1][0])
   157  	fp2.doubleAssign(t[2])
   158  	fp2.add(&c[1][0], t[2], t[3])
   159  	fp2.sub(t[2], t[5], &a[0][2])
   160  	fp2.doubleAssign(t[2])
   161  	fp2.add(&c[0][2], t[2], t[5])
   162  }
   163  
   164  func (e *fp12) mul(c, a, b *fe12) {
   165  	t, fp6 := e.t6, e.fp6
   166  	fp6.mul(t[1], &a[0], &b[0])
   167  	fp6.mul(t[2], &a[1], &b[1])
   168  	fp6.add(t[0], t[1], t[2])
   169  	fp6.mulByNonResidue(t[2], t[2])
   170  	fp6.add(t[3], t[1], t[2])
   171  	fp6.add(t[1], &a[0], &a[1])
   172  	fp6.add(t[2], &b[0], &b[1])
   173  	fp6.mulAssign(t[1], t[2])
   174  	c[0].set(t[3])
   175  	fp6.sub(&c[1], t[1], t[0])
   176  }
   177  
   178  func (e *fp12) mulAssign(a, b *fe12) {
   179  	t, fp6 := e.t6, e.fp6
   180  	fp6.mul(t[1], &a[0], &b[0])
   181  	fp6.mul(t[2], &a[1], &b[1])
   182  	fp6.add(t[0], t[1], t[2])
   183  	fp6.mulByNonResidue(t[2], t[2])
   184  	fp6.add(t[3], t[1], t[2])
   185  	fp6.add(t[1], &a[0], &a[1])
   186  	fp6.add(t[2], &b[0], &b[1])
   187  	fp6.mulAssign(t[1], t[2])
   188  	a[0].set(t[3])
   189  	fp6.sub(&a[1], t[1], t[0])
   190  }
   191  
   192  func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) {
   193  	t, fp2 := e.t2, e.fp2()
   194  	fp2.square(t[0], a0)
   195  	fp2.square(t[1], a1)
   196  	fp2.mulByNonResidue(t[2], t[1])
   197  	fp2.add(c0, t[2], t[0])
   198  	fp2.add(t[2], a0, a1)
   199  	fp2.squareAssign(t[2])
   200  	fp2.subAssign(t[2], t[0])
   201  	fp2.sub(c1, t[2], t[1])
   202  }
   203  
   204  func (e *fp12) inverse(c, a *fe12) {
   205  	fp6, t := e.fp6, e.t6
   206  	fp6.square(t[0], &a[0])
   207  	fp6.square(t[1], &a[1])
   208  	fp6.mulByNonResidue(t[1], t[1])
   209  	fp6.sub(t[1], t[0], t[1])
   210  	fp6.inverse(t[0], t[1])
   211  	fp6.mul(&c[0], &a[0], t[0])
   212  	fp6.mulAssign(t[0], &a[1])
   213  	fp6.neg(&c[1], t[0])
   214  }
   215  
   216  func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) {
   217  	fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0]
   218  	fp6.mulBy01(t[0], &a[0], c0, c1)
   219  	fp6.mulBy1(t[1], &a[1], c4)
   220  	fp2.add(t2, c1, c4)
   221  	fp6.add(t[2], &a[1], &a[0])
   222  	fp6.mulBy01Assign(t[2], c0, t2)
   223  	fp6.subAssign(t[2], t[0])
   224  	fp6.sub(&a[1], t[2], t[1])
   225  	fp6.mulByNonResidue(t[1], t[1])
   226  	fp6.add(&a[0], t[1], t[0])
   227  }
   228  
   229  func (e *fp12) exp(c, a *fe12, s *big.Int) {
   230  	z := e.one()
   231  	for i := s.BitLen() - 1; i >= 0; i-- {
   232  		e.square(z, z)
   233  		if s.Bit(i) == 1 {
   234  			e.mul(z, z, a)
   235  		}
   236  	}
   237  	c.set(z)
   238  }
   239  
   240  func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) {
   241  	z := e.one()
   242  	for i := s.BitLen() - 1; i >= 0; i-- {
   243  		e.cyclotomicSquare(z, z)
   244  		if s.Bit(i) == 1 {
   245  			e.mul(z, z, a)
   246  		}
   247  	}
   248  	c.set(z)
   249  }
   250  
   251  func (e *fp12) frobeniusMap(c, a *fe12, power uint) {
   252  	fp6 := e.fp6
   253  	fp6.frobeniusMap(&c[0], &a[0], power)
   254  	fp6.frobeniusMap(&c[1], &a[1], power)
   255  	switch power {
   256  	case 0:
   257  		return
   258  	case 6:
   259  		fp6.neg(&c[1], &c[1])
   260  	default:
   261  		fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power])
   262  	}
   263  }
   264  
   265  func (e *fp12) frobeniusMapAssign(a *fe12, power uint) {
   266  	fp6 := e.fp6
   267  	fp6.frobeniusMapAssign(&a[0], power)
   268  	fp6.frobeniusMapAssign(&a[1], power)
   269  	switch power {
   270  	case 0:
   271  		return
   272  	case 6:
   273  		fp6.neg(&a[1], &a[1])
   274  	default:
   275  		fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power])
   276  	}
   277  }