github.com/cloudflare/circl@v1.5.0/math/fp448/fp.go (about) 1 // Package fp448 provides prime field arithmetic over GF(2^448-2^224-1). 2 package fp448 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 = 56 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^448-2^224-1. 19 var p = Elt{ 20 0xff, 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, 0xfe, 0xff, 0xff, 0xff, 24 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 27 } 28 29 // P returns the prime modulus 2^448-2^224-1. 30 func P() Elt { return p } 31 32 // ToBytes stores in b the little-endian byte representation of x. 33 func ToBytes(b []byte, x *Elt) error { 34 if len(b) != Size { 35 return errors.New("wrong size") 36 } 37 Modp(x) 38 copy(b, x[:]) 39 return nil 40 } 41 42 // IsZero returns true if x is equal to 0. 43 func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} } 44 45 // IsOne returns true if x is equal to 1. 46 func IsOne(x *Elt) bool { Modp(x); return *x == Elt{1} } 47 48 // SetOne assigns x=1. 49 func SetOne(x *Elt) { *x = Elt{1} } 50 51 // One returns the 1 element. 52 func One() (x Elt) { x = Elt{1}; return } 53 54 // Neg calculates z = -x. 55 func Neg(z, x *Elt) { Sub(z, &p, x) } 56 57 // Modp ensures that z is between [0,p-1]. 58 func Modp(z *Elt) { Sub(z, z, &p) } 59 60 // InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue. If so, 61 // isQR = true; otherwise, isQR = false, since x/y is a quadratic non-residue, 62 // and z = sqrt(-x/y). 63 func InvSqrt(z, x, y *Elt) (isQR bool) { 64 // First note that x^(2(k+1)) = x^(p-1)/2 * x = legendre(x) * x 65 // so that's x if x is a quadratic residue and -x otherwise. 66 // Next, y^(6k+3) = y^(4k+2) * y^(2k+1) = y^(p-1) * y^((p-1)/2) = legendre(y). 67 // So the z we compute satisfies z^2 y = x^(2(k+1)) y^(6k+3) = legendre(x)*legendre(y). 68 // Thus if x and y are quadratic residues, then z is indeed sqrt(x/y). 69 t0, t1 := &Elt{}, &Elt{} 70 Mul(t0, x, y) // x*y 71 Sqr(t1, y) // y^2 72 Mul(t1, t0, t1) // x*y^3 73 powPminus3div4(z, t1) // (x*y^3)^k 74 Mul(z, z, t0) // z = x*y*(x*y^3)^k = x^(k+1) * y^(3k+1) 75 76 // Check if x/y is a quadratic residue 77 Sqr(t0, z) // z^2 78 Mul(t0, t0, y) // y*z^2 79 Sub(t0, t0, x) // y*z^2-x 80 return IsZero(t0) 81 } 82 83 // Inv calculates z = 1/x mod p. 84 func Inv(z, x *Elt) { 85 // Calculates z = x^(4k+1) = x^(p-3+1) = x^(p-2) = x^-1, where k = (p-3)/4. 86 t := &Elt{} 87 powPminus3div4(t, x) // t = x^k 88 Sqr(t, t) // t = x^2k 89 Sqr(t, t) // t = x^4k 90 Mul(z, t, x) // z = x^(4k+1) 91 } 92 93 // powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. 94 func powPminus3div4(z, x *Elt) { 95 x0, x1 := &Elt{}, &Elt{} 96 Sqr(z, x) 97 Mul(z, z, x) 98 Sqr(x0, z) 99 Mul(x0, x0, x) 100 Sqr(z, x0) 101 Sqr(z, z) 102 Sqr(z, z) 103 Mul(z, z, x0) 104 Sqr(x1, z) 105 for i := 0; i < 5; i++ { 106 Sqr(x1, x1) 107 } 108 Mul(x1, x1, z) 109 Sqr(z, x1) 110 for i := 0; i < 11; i++ { 111 Sqr(z, z) 112 } 113 Mul(z, z, x1) 114 Sqr(z, z) 115 Sqr(z, z) 116 Sqr(z, z) 117 Mul(z, z, x0) 118 Sqr(x1, z) 119 for i := 0; i < 26; i++ { 120 Sqr(x1, x1) 121 } 122 Mul(x1, x1, z) 123 Sqr(z, x1) 124 for i := 0; i < 53; i++ { 125 Sqr(z, z) 126 } 127 Mul(z, z, x1) 128 Sqr(z, z) 129 Sqr(z, z) 130 Sqr(z, z) 131 Mul(z, z, x0) 132 Sqr(x1, z) 133 for i := 0; i < 110; i++ { 134 Sqr(x1, x1) 135 } 136 Mul(x1, x1, z) 137 Sqr(z, x1) 138 Mul(z, z, x) 139 for i := 0; i < 223; i++ { 140 Sqr(z, z) 141 } 142 Mul(z, z, x1) 143 } 144 145 // Cmov assigns y to x if n is 1. 146 func Cmov(x, y *Elt, n uint) { cmov(x, y, n) } 147 148 // Cswap interchanges x and y if n is 1. 149 func Cswap(x, y *Elt, n uint) { cswap(x, y, n) } 150 151 // Add calculates z = x+y mod p. 152 func Add(z, x, y *Elt) { add(z, x, y) } 153 154 // Sub calculates z = x-y mod p. 155 func Sub(z, x, y *Elt) { sub(z, x, y) } 156 157 // AddSub calculates (x,y) = (x+y mod p, x-y mod p). 158 func AddSub(x, y *Elt) { addsub(x, y) } 159 160 // Mul calculates z = x*y mod p. 161 func Mul(z, x, y *Elt) { mul(z, x, y) } 162 163 // Sqr calculates z = x^2 mod p. 164 func Sqr(z, x *Elt) { sqr(z, x) }