github.com/cloudflare/circl@v1.5.0/math/fp25519/fp.go (about)

     1  // Package fp25519 provides prime field arithmetic over GF(2^255-19).
     2  package fp25519
     3  
     4  import (
     5  	"errors"
     6  
     7  	"github.com/cloudflare/circl/internal/conv"
     8  )
     9  
    10  // Size in bytes of an element.
    11  const Size = 32
    12  
    13  // Elt is a prime field element.
    14  type Elt [Size]byte
    15  
    16  func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) }
    17  
    18  // p is the prime modulus 2^255-19.
    19  var p = Elt{
    20  	0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    21  	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    22  	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    23  	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
    24  }
    25  
    26  // P returns the prime modulus 2^255-19.
    27  func P() Elt { return p }
    28  
    29  // ToBytes stores in b the little-endian byte representation of x.
    30  func ToBytes(b []byte, x *Elt) error {
    31  	if len(b) != Size {
    32  		return errors.New("wrong size")
    33  	}
    34  	Modp(x)
    35  	copy(b, x[:])
    36  	return nil
    37  }
    38  
    39  // IsZero returns true if x is equal to 0.
    40  func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} }
    41  
    42  // SetOne assigns x=1.
    43  func SetOne(x *Elt) { *x = Elt{}; x[0] = 1 }
    44  
    45  // Neg calculates z = -x.
    46  func Neg(z, x *Elt) { Sub(z, &p, x) }
    47  
    48  // InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue, which is
    49  // indicated by returning isQR = true. Otherwise, when x/y is a quadratic
    50  // non-residue, z will have an undetermined value and isQR = false.
    51  func InvSqrt(z, x, y *Elt) (isQR bool) {
    52  	sqrtMinusOne := &Elt{
    53  		0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
    54  		0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
    55  		0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b,
    56  		0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b,
    57  	}
    58  	t0, t1, t2, t3 := &Elt{}, &Elt{}, &Elt{}, &Elt{}
    59  
    60  	Mul(t0, x, y)   // t0 = u*v
    61  	Sqr(t1, y)      // t1 = v^2
    62  	Mul(t2, t0, t1) // t2 = u*v^3
    63  	Sqr(t0, t1)     // t0 = v^4
    64  	Mul(t1, t0, t2) // t1 = u*v^7
    65  
    66  	var Tab [4]*Elt
    67  	Tab[0] = &Elt{}
    68  	Tab[1] = &Elt{}
    69  	Tab[2] = t3
    70  	Tab[3] = t1
    71  
    72  	*Tab[0] = *t1
    73  	Sqr(Tab[0], Tab[0])
    74  	Sqr(Tab[1], Tab[0])
    75  	Sqr(Tab[1], Tab[1])
    76  	Mul(Tab[1], Tab[1], Tab[3])
    77  	Mul(Tab[0], Tab[0], Tab[1])
    78  	Sqr(Tab[0], Tab[0])
    79  	Mul(Tab[0], Tab[0], Tab[1])
    80  	Sqr(Tab[1], Tab[0])
    81  	for i := 0; i < 4; i++ {
    82  		Sqr(Tab[1], Tab[1])
    83  	}
    84  	Mul(Tab[1], Tab[1], Tab[0])
    85  	Sqr(Tab[2], Tab[1])
    86  	for i := 0; i < 4; i++ {
    87  		Sqr(Tab[2], Tab[2])
    88  	}
    89  	Mul(Tab[2], Tab[2], Tab[0])
    90  	Sqr(Tab[1], Tab[2])
    91  	for i := 0; i < 14; i++ {
    92  		Sqr(Tab[1], Tab[1])
    93  	}
    94  	Mul(Tab[1], Tab[1], Tab[2])
    95  	Sqr(Tab[2], Tab[1])
    96  	for i := 0; i < 29; i++ {
    97  		Sqr(Tab[2], Tab[2])
    98  	}
    99  	Mul(Tab[2], Tab[2], Tab[1])
   100  	Sqr(Tab[1], Tab[2])
   101  	for i := 0; i < 59; i++ {
   102  		Sqr(Tab[1], Tab[1])
   103  	}
   104  	Mul(Tab[1], Tab[1], Tab[2])
   105  	for i := 0; i < 5; i++ {
   106  		Sqr(Tab[1], Tab[1])
   107  	}
   108  	Mul(Tab[1], Tab[1], Tab[0])
   109  	Sqr(Tab[2], Tab[1])
   110  	for i := 0; i < 124; i++ {
   111  		Sqr(Tab[2], Tab[2])
   112  	}
   113  	Mul(Tab[2], Tab[2], Tab[1])
   114  	Sqr(Tab[2], Tab[2])
   115  	Sqr(Tab[2], Tab[2])
   116  	Mul(Tab[2], Tab[2], Tab[3])
   117  
   118  	Mul(z, t3, t2) // z = xy^(p+3)/8 = xy^3*(xy^7)^(p-5)/8
   119  	// Checking whether y z^2 == x
   120  	Sqr(t0, z)     // t0 = z^2
   121  	Mul(t0, t0, y) // t0 = yz^2
   122  	Sub(t1, t0, x) // t1 = t0-u
   123  	Add(t2, t0, x) // t2 = t0+u
   124  	if IsZero(t1) {
   125  		return true
   126  	} else if IsZero(t2) {
   127  		Mul(z, z, sqrtMinusOne) // z = z*sqrt(-1)
   128  		return true
   129  	} else {
   130  		return false
   131  	}
   132  }
   133  
   134  // Inv calculates z = 1/x mod p.
   135  func Inv(z, x *Elt) {
   136  	x0, x1, x2 := &Elt{}, &Elt{}, &Elt{}
   137  	Sqr(x1, x)
   138  	Sqr(x0, x1)
   139  	Sqr(x0, x0)
   140  	Mul(x0, x0, x)
   141  	Mul(z, x0, x1)
   142  	Sqr(x1, z)
   143  	Mul(x0, x0, x1)
   144  	Sqr(x1, x0)
   145  	for i := 0; i < 4; i++ {
   146  		Sqr(x1, x1)
   147  	}
   148  	Mul(x0, x0, x1)
   149  	Sqr(x1, x0)
   150  	for i := 0; i < 9; i++ {
   151  		Sqr(x1, x1)
   152  	}
   153  	Mul(x1, x1, x0)
   154  	Sqr(x2, x1)
   155  	for i := 0; i < 19; i++ {
   156  		Sqr(x2, x2)
   157  	}
   158  	Mul(x2, x2, x1)
   159  	for i := 0; i < 10; i++ {
   160  		Sqr(x2, x2)
   161  	}
   162  	Mul(x2, x2, x0)
   163  	Sqr(x0, x2)
   164  	for i := 0; i < 49; i++ {
   165  		Sqr(x0, x0)
   166  	}
   167  	Mul(x0, x0, x2)
   168  	Sqr(x1, x0)
   169  	for i := 0; i < 99; i++ {
   170  		Sqr(x1, x1)
   171  	}
   172  	Mul(x1, x1, x0)
   173  	for i := 0; i < 50; i++ {
   174  		Sqr(x1, x1)
   175  	}
   176  	Mul(x1, x1, x2)
   177  	for i := 0; i < 5; i++ {
   178  		Sqr(x1, x1)
   179  	}
   180  	Mul(z, z, x1)
   181  }
   182  
   183  // Cmov assigns y to x if n is 1.
   184  func Cmov(x, y *Elt, n uint) { cmov(x, y, n) }
   185  
   186  // Cswap interchanges x and y if n is 1.
   187  func Cswap(x, y *Elt, n uint) { cswap(x, y, n) }
   188  
   189  // Add calculates z = x+y mod p.
   190  func Add(z, x, y *Elt) { add(z, x, y) }
   191  
   192  // Sub calculates z = x-y mod p.
   193  func Sub(z, x, y *Elt) { sub(z, x, y) }
   194  
   195  // AddSub calculates (x,y) = (x+y mod p, x-y mod p).
   196  func AddSub(x, y *Elt) { addsub(x, y) }
   197  
   198  // Mul calculates z = x*y mod p.
   199  func Mul(z, x, y *Elt) { mul(z, x, y) }
   200  
   201  // Sqr calculates z = x^2 mod p.
   202  func Sqr(z, x *Elt) { sqr(z, x) }
   203  
   204  // Modp ensures that z is between [0,p-1].
   205  func Modp(z *Elt) { modp(z) }