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) }