github.com/nova-foundation/go-ethereum@v1.0.1/crypto/bls12381/fp.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  func fromBytes(in []byte) (*fe, error) {
    25  	fe := &fe{}
    26  	if len(in) != 48 {
    27  		return nil, errors.New("input string should be equal 48 bytes")
    28  	}
    29  	fe.setBytes(in)
    30  	if !fe.isValid() {
    31  		return nil, errors.New("must be less than modulus")
    32  	}
    33  	toMont(fe, fe)
    34  	return fe, nil
    35  }
    36  
    37  func fromBig(in *big.Int) (*fe, error) {
    38  	fe := new(fe).setBig(in)
    39  	if !fe.isValid() {
    40  		return nil, errors.New("invalid input string")
    41  	}
    42  	toMont(fe, fe)
    43  	return fe, nil
    44  }
    45  
    46  func fromString(in string) (*fe, error) {
    47  	fe, err := new(fe).setString(in)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	if !fe.isValid() {
    52  		return nil, errors.New("invalid input string")
    53  	}
    54  	toMont(fe, fe)
    55  	return fe, nil
    56  }
    57  
    58  func toBytes(e *fe) []byte {
    59  	e2 := new(fe)
    60  	fromMont(e2, e)
    61  	return e2.bytes()
    62  }
    63  
    64  func toBig(e *fe) *big.Int {
    65  	e2 := new(fe)
    66  	fromMont(e2, e)
    67  	return e2.big()
    68  }
    69  
    70  func toString(e *fe) (s string) {
    71  	e2 := new(fe)
    72  	fromMont(e2, e)
    73  	return e2.string()
    74  }
    75  
    76  func toMont(c, a *fe) {
    77  	mul(c, a, r2)
    78  }
    79  
    80  func fromMont(c, a *fe) {
    81  	mul(c, a, &fe{1})
    82  }
    83  
    84  func exp(c, a *fe, e *big.Int) {
    85  	z := new(fe).set(r1)
    86  	for i := e.BitLen(); i >= 0; i-- {
    87  		mul(z, z, z)
    88  		if e.Bit(i) == 1 {
    89  			mul(z, z, a)
    90  		}
    91  	}
    92  	c.set(z)
    93  }
    94  
    95  func inverse(inv, e *fe) {
    96  	if e.isZero() {
    97  		inv.zero()
    98  		return
    99  	}
   100  	u := new(fe).set(&modulus)
   101  	v := new(fe).set(e)
   102  	s := &fe{1}
   103  	r := &fe{0}
   104  	var k int
   105  	var z uint64
   106  	var found = false
   107  	// Phase 1
   108  	for i := 0; i < 768; i++ {
   109  		if v.isZero() {
   110  			found = true
   111  			break
   112  		}
   113  		if u.isEven() {
   114  			u.div2(0)
   115  			s.mul2()
   116  		} else if v.isEven() {
   117  			v.div2(0)
   118  			z += r.mul2()
   119  		} else if u.cmp(v) == 1 {
   120  			lsubAssign(u, v)
   121  			u.div2(0)
   122  			laddAssign(r, s)
   123  			s.mul2()
   124  		} else {
   125  			lsubAssign(v, u)
   126  			v.div2(0)
   127  			laddAssign(s, r)
   128  			z += r.mul2()
   129  		}
   130  		k += 1
   131  	}
   132  
   133  	if !found {
   134  		inv.zero()
   135  		return
   136  	}
   137  
   138  	if k < 381 || k > 381+384 {
   139  		inv.zero()
   140  		return
   141  	}
   142  
   143  	if r.cmp(&modulus) != -1 || z > 0 {
   144  		lsubAssign(r, &modulus)
   145  	}
   146  	u.set(&modulus)
   147  	lsubAssign(u, r)
   148  
   149  	// Phase 2
   150  	for i := k; i < 384*2; i++ {
   151  		double(u, u)
   152  	}
   153  	inv.set(u)
   154  }
   155  
   156  func sqrt(c, a *fe) bool {
   157  	u, v := new(fe).set(a), new(fe)
   158  	exp(c, a, pPlus1Over4)
   159  	square(v, c)
   160  	return u.equal(v)
   161  }
   162  
   163  func isQuadraticNonResidue(elem *fe) bool {
   164  	result := new(fe)
   165  	exp(result, elem, pMinus1Over2)
   166  	return !result.isOne()
   167  }