github.com/cloudflare/circl@v1.5.0/ecc/fourq/fp_test.go (about) 1 package fourq 2 3 import ( 4 "crypto/rand" 5 "math/big" 6 "testing" 7 8 "github.com/cloudflare/circl/internal/test" 9 ) 10 11 type ( 12 tFpAdd = func(z, x, y *Fp) 13 tFpSub = func(z, x, y *Fp) 14 tFpMul = func(z, x, y *Fp) 15 tFpSqr = func(z, x *Fp) 16 tFpHlf = func(z, x *Fp) 17 tFpModp = func(z *Fp) 18 ) 19 20 func getModulus() *big.Int { 21 p := big.NewInt(1) 22 return p.Lsh(p, 127).Sub(p, big.NewInt(1)) 23 } 24 25 func TestFpSign(t *testing.T) { 26 const testTimes = 1 << 9 27 P := getModulus() 28 x := &Fp{} 29 var P1div2 big.Int 30 P1div2.Add(P, big.NewInt(1)).Rsh(&P1div2, 1) // (p+1)/2 31 32 // Verifying Sign(0) = 0 33 x.setBigInt(big.NewInt(0)) 34 got := fpSgn(x) 35 want := 0 36 if got != want { 37 test.ReportError(t, got, want, x) 38 } 39 40 // Verifying Sign(P) = 0 41 x.setBigInt(P) 42 got = fpSgn(x) 43 want = 0 44 if got != want { 45 test.ReportError(t, got, want, x) 46 } 47 48 // Verifying Sign( (p+1)/2 ) = -1 49 x.setBigInt(&P1div2) 50 got = fpSgn(x) 51 want = -1 52 if got != want { 53 test.ReportError(t, got, want, x) 54 } 55 56 // Verifying x be a non-zero positive 57 for i := 0; i < testTimes; i++ { 58 bigX, _ := rand.Int(rand.Reader, &P1div2) 59 x.setBigInt(bigX) 60 got = fpSgn(x) 61 want = 1 62 if got != want { 63 test.ReportError(t, got, want, x) 64 } 65 } 66 // Verifying x be a non-zero negative 67 for i := 0; i < testTimes; i++ { 68 bigX, _ := rand.Int(rand.Reader, &P1div2) 69 bigX.Add(bigX, &P1div2) 70 x.setBigInt(bigX) 71 got = fpSgn(x) 72 want = -1 73 if got != want { 74 test.ReportError(t, got, want, x) 75 } 76 } 77 } 78 79 func TestFpIsZero(t *testing.T) { 80 P := getModulus() 81 x := &Fp{} 82 // Verifying x=0 83 x.setBigInt(big.NewInt(0)) 84 got := x.isZero() 85 want := true 86 if got != want { 87 test.ReportError(t, got, want, x) 88 } 89 90 // Verifying x=P goes to 0 91 x.setBigInt(P) 92 got = x.isZero() 93 want = true 94 if got != want { 95 test.ReportError(t, got, want, x) 96 } 97 98 // Verifying x!=0 99 _, _ = rand.Read(x[:]) 100 got = x.isZero() 101 want = false 102 if got != want { 103 test.ReportError(t, got, want, x) 104 } 105 } 106 107 func testFpModp(t *testing.T, f tFpModp) { 108 const testTimes = 1 << 9 109 P := getModulus() 110 x := &Fp{} 111 var bigX big.Int 112 // Verifying x=P goes to 0 113 bigX.Set(P) 114 x.setBigInt(&bigX) 115 f(x) 116 got := x.toBigInt() 117 want := big.NewInt(0) 118 if got.Cmp(want) != 0 { 119 test.ReportError(t, got, want, x) 120 } 121 122 // Verifying x=P+1 goes to 1 123 bigX.Add(P, big.NewInt(1)) 124 x.setBigInt(&bigX) 125 f(x) 126 got = x.toBigInt() 127 want = big.NewInt(1) 128 if got.Cmp(want) != 0 { 129 test.ReportError(t, got, want, x) 130 } 131 132 for i := 0; i < testTimes; i++ { 133 _, _ = rand.Read(x[:]) 134 135 bigX := x.toBigInt() 136 137 fpMod(x) 138 got := x.toBigInt() 139 140 want := bigX.Mod(bigX, P) 141 if got.Cmp(want) != 0 { 142 test.ReportError(t, got, want, x) 143 } 144 } 145 } 146 147 func TestFpNeg(t *testing.T) { 148 const testTimes = 1 << 9 149 P := getModulus() 150 x, z := &Fp{}, &Fp{} 151 for i := 0; i < testTimes; i++ { 152 bigX, _ := rand.Int(rand.Reader, P) 153 154 x.setBigInt(bigX) 155 fpNeg(z, x) 156 got := z.toBigInt() 157 158 want := bigX.Neg(bigX) 159 want = want.Mod(want, P) 160 if got.Cmp(want) != 0 { 161 test.ReportError(t, got, want, x) 162 } 163 } 164 } 165 166 func testFpHlf(t *testing.T, f tFpHlf) { 167 const testTimes = 1 << 9 168 P := getModulus() 169 x, z := &Fp{}, &Fp{} 170 invTwo := big.NewInt(2) 171 invTwo.ModInverse(invTwo, P) 172 for i := 0; i < testTimes; i++ { 173 bigX, _ := rand.Int(rand.Reader, P) 174 175 x.setBigInt(bigX) 176 f(z, x) 177 got := z.toBigInt() 178 179 want := bigX.Mul(bigX, invTwo) 180 want = want.Mod(want, P) 181 if got.Cmp(want) != 0 { 182 test.ReportError(t, got, want, x) 183 } 184 } 185 } 186 187 func testFpAdd(t *testing.T, f tFpAdd) { 188 const testTimes = 1 << 9 189 P := getModulus() 190 x, y, z := &Fp{}, &Fp{}, &Fp{} 191 for i := 0; i < testTimes; i++ { 192 bigX, _ := rand.Int(rand.Reader, P) 193 bigY, _ := rand.Int(rand.Reader, P) 194 195 x.setBigInt(bigX) 196 y.setBigInt(bigY) 197 f(z, x, y) 198 got := z.toBigInt() 199 200 want := bigX.Add(bigX, bigY) 201 want = want.Mod(want, P) 202 if got.Cmp(want) != 0 { 203 test.ReportError(t, got, want, x, y) 204 } 205 } 206 } 207 208 func testFpSub(t *testing.T, f tFpSub) { 209 const testTimes = 1 << 9 210 P := getModulus() 211 x, y, z := &Fp{}, &Fp{}, &Fp{} 212 for i := 0; i < testTimes; i++ { 213 bigX, _ := rand.Int(rand.Reader, P) 214 bigY, _ := rand.Int(rand.Reader, P) 215 216 x.setBigInt(bigX) 217 y.setBigInt(bigY) 218 f(z, x, y) 219 got := z.toBigInt() 220 221 want := bigX.Sub(bigX, bigY) 222 want = want.Mod(want, P) 223 if got.Cmp(want) != 0 { 224 test.ReportError(t, got, want, x, y) 225 } 226 } 227 } 228 229 func testFpMul(t *testing.T, f tFpMul) { 230 const testTimes = 1 << 9 231 P := getModulus() 232 x, y, z := &Fp{}, &Fp{}, &Fp{} 233 for i := 0; i < testTimes; i++ { 234 bigX, _ := rand.Int(rand.Reader, P) 235 bigY, _ := rand.Int(rand.Reader, P) 236 237 x.setBigInt(bigX) 238 y.setBigInt(bigY) 239 f(z, x, y) 240 got := z.toBigInt() 241 242 want := bigX.Mul(bigX, bigY) 243 want = want.Mod(want, P) 244 if got.Cmp(want) != 0 { 245 test.ReportError(t, got, want, x, y) 246 } 247 } 248 } 249 250 func testFpSqr(t *testing.T, f tFpSqr) { 251 const testTimes = 1 << 9 252 P := getModulus() 253 x, z := &Fp{}, &Fp{} 254 for i := 0; i < testTimes; i++ { 255 bigX, _ := rand.Int(rand.Reader, P) 256 257 x.setBigInt(bigX) 258 f(z, x) 259 got := z.toBigInt() 260 261 want := bigX.Mul(bigX, bigX) 262 want = want.Mod(want, P) 263 264 if got.Cmp(want) != 0 { 265 test.ReportError(t, got, want, x) 266 } 267 } 268 } 269 270 func TestFpInv(t *testing.T) { 271 const testTimes = 1 << 9 272 P := getModulus() 273 x, z := &Fp{}, &Fp{} 274 for i := 0; i < testTimes; i++ { 275 bigX, _ := rand.Int(rand.Reader, P) 276 277 x.setBigInt(bigX) 278 fpInv(z, x) 279 got := z.toBigInt() 280 281 want := bigX.ModInverse(bigX, P) 282 if got.Cmp(want) != 0 { 283 test.ReportError(t, got, want, x) 284 } 285 } 286 } 287 288 func TestFpGeneric(t *testing.T) { 289 t.Run("Add", func(t *testing.T) { testFpAdd(t, fpAddGeneric) }) 290 t.Run("Sub", func(t *testing.T) { testFpSub(t, fpSubGeneric) }) 291 t.Run("Mul", func(t *testing.T) { testFpMul(t, fpMulGeneric) }) 292 t.Run("Sqr", func(t *testing.T) { testFpSqr(t, fpSqrGeneric) }) 293 t.Run("Hlf", func(t *testing.T) { testFpHlf(t, fpHlfGeneric) }) 294 t.Run("Modp", func(t *testing.T) { testFpModp(t, fpModGeneric) }) 295 } 296 297 func TestFpNative(t *testing.T) { 298 t.Run("Add", func(t *testing.T) { testFpAdd(t, fpAdd) }) 299 t.Run("Sub", func(t *testing.T) { testFpSub(t, fpSub) }) 300 t.Run("Mul", func(t *testing.T) { testFpMul(t, fpMul) }) 301 t.Run("Sqr", func(t *testing.T) { testFpSqr(t, fpSqr) }) 302 t.Run("Hlf", func(t *testing.T) { testFpHlf(t, fpHlf) }) 303 t.Run("Modp", func(t *testing.T) { testFpModp(t, fpMod) }) 304 } 305 306 func BenchmarkFp(b *testing.B) { 307 x, y, z := &Fp{}, &Fp{}, &Fp{} 308 p := getModulus() 309 n, _ := rand.Int(rand.Reader, p) 310 x.setBigInt(n) 311 n, _ = rand.Int(rand.Reader, p) 312 y.setBigInt(n) 313 314 b.Run("Add", func(b *testing.B) { 315 for i := 0; i < b.N; i++ { 316 fpAdd(z, x, y) 317 } 318 }) 319 b.Run("Sub", func(b *testing.B) { 320 for i := 0; i < b.N; i++ { 321 fpSub(z, x, y) 322 } 323 }) 324 b.Run("Mul", func(b *testing.B) { 325 for i := 0; i < b.N; i++ { 326 fpMul(z, x, y) 327 } 328 }) 329 b.Run("Sqr", func(b *testing.B) { 330 for i := 0; i < b.N; i++ { 331 fpSqr(z, x) 332 } 333 }) 334 b.Run("Inv", func(b *testing.B) { 335 for i := 0; i < b.N; i++ { 336 fpInv(z, x) 337 } 338 }) 339 }