github.com/cloudflare/circl@v1.5.0/ecc/fourq/fp.go (about)

     1  package fourq
     2  
     3  import (
     4  	"math/big"
     5  
     6  	"github.com/cloudflare/circl/internal/conv"
     7  )
     8  
     9  var modulusP = Fp{
    10  	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    11  	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
    12  }
    13  
    14  // SizeFp is the length in bytes to represent an element in the base field.
    15  const SizeFp = 16
    16  
    17  // Fp is an element (in littleEndian order) of prime field GF(2^127-1).
    18  type Fp [SizeFp]byte
    19  
    20  func (f *Fp) String() string       { return conv.BytesLe2Hex(f[:]) }
    21  func (f *Fp) isZero() bool         { fpMod(f); return *f == Fp{} }
    22  func (f *Fp) toBigInt() *big.Int   { fpMod(f); return conv.BytesLe2BigInt(f[:]) }
    23  func (f *Fp) setBigInt(b *big.Int) { conv.BigInt2BytesLe((*f)[:], b); fpMod(f) }
    24  func (f *Fp) toBytes(buf []byte) {
    25  	if len(buf) == SizeFp {
    26  		fpMod(f)
    27  		copy(buf, f[:])
    28  	}
    29  }
    30  
    31  func (f *Fp) fromBytes(buf []byte) bool {
    32  	if len(buf) == SizeFp {
    33  		if (buf[SizeFp-1] >> 7) == 0 {
    34  			copy(f[:], buf)
    35  			fpMod(f)
    36  			return true
    37  		}
    38  	}
    39  	return false
    40  }
    41  func fpNeg(c, a *Fp) { fpSub(c, &modulusP, a) }
    42  
    43  // fqSgn returns the sign of an element.
    44  //
    45  //	-1 if x >  (p+1)/2
    46  //	 0 if x == 0
    47  //	+1 if x >  (p+1)/2.
    48  func fpSgn(c *Fp) int {
    49  	s := 0
    50  	if !c.isZero() {
    51  		b := int(c[SizeFp-1]>>6) & 0x1
    52  		s = 1 - (b << 1)
    53  	}
    54  	return s
    55  }
    56  
    57  // fpTwo1251 sets c = a^(2^125-1).
    58  func fpTwo1251(c, a *Fp) {
    59  	t1, t2, t3, t4, t5 := &Fp{}, &Fp{}, &Fp{}, &Fp{}, &Fp{}
    60  
    61  	fpSqr(t2, a)
    62  	fpMul(t2, t2, a)
    63  	fpSqr(t3, t2)
    64  	fpSqr(t3, t3)
    65  	fpMul(t3, t3, t2)
    66  	fpSqr(t4, t3)
    67  	fpSqr(t4, t4)
    68  	fpSqr(t4, t4)
    69  	fpSqr(t4, t4)
    70  	fpMul(t4, t4, t3)
    71  	fpSqr(t5, t4)
    72  	for i := 0; i < 7; i++ {
    73  		fpSqr(t5, t5)
    74  	}
    75  	fpMul(t5, t5, t4)
    76  	fpSqr(t2, t5)
    77  	for i := 0; i < 15; i++ {
    78  		fpSqr(t2, t2)
    79  	}
    80  	fpMul(t2, t2, t5)
    81  	fpSqr(t1, t2)
    82  	for i := 0; i < 31; i++ {
    83  		fpSqr(t1, t1)
    84  	}
    85  	fpMul(t1, t1, t2)
    86  	for i := 0; i < 32; i++ {
    87  		fpSqr(t1, t1)
    88  	}
    89  	fpMul(t1, t2, t1)
    90  	for i := 0; i < 16; i++ {
    91  		fpSqr(t1, t1)
    92  	}
    93  	fpMul(t1, t1, t5)
    94  	for i := 0; i < 8; i++ {
    95  		fpSqr(t1, t1)
    96  	}
    97  	fpMul(t1, t1, t4)
    98  	for i := 0; i < 4; i++ {
    99  		fpSqr(t1, t1)
   100  	}
   101  	fpMul(t1, t1, t3)
   102  	fpSqr(t1, t1)
   103  	fpMul(c, a, t1)
   104  }
   105  
   106  // fpInv sets z to a^(-1) mod p.
   107  func fpInv(z, a *Fp) {
   108  	t := &Fp{}
   109  	fpTwo1251(t, a)
   110  	fpSqr(t, t)
   111  	fpSqr(t, t)
   112  	fpMul(z, t, a)
   113  }