github.com/cloudflare/circl@v1.5.0/math/fp448/fp_test.go (about) 1 package fp448 2 3 import ( 4 "crypto/rand" 5 "fmt" 6 "math/big" 7 "testing" 8 9 "github.com/cloudflare/circl/internal/conv" 10 "github.com/cloudflare/circl/internal/test" 11 ) 12 13 func testCmov(t *testing.T, f func(x, y *Elt, n uint)) { 14 const numTests = 1 << 9 15 var x, y Elt 16 for i := 0; i < numTests; i++ { 17 _, _ = rand.Read(x[:]) 18 _, _ = rand.Read(y[:]) 19 b := uint(y[0] & 0x1) 20 want := conv.BytesLe2BigInt(x[:]) 21 if b != 0 { 22 want = conv.BytesLe2BigInt(y[:]) 23 } 24 25 f(&x, &y, b) 26 got := conv.BytesLe2BigInt(x[:]) 27 28 if got.Cmp(want) != 0 { 29 test.ReportError(t, got, want, x, y, b) 30 } 31 } 32 } 33 34 func testCswap(t *testing.T, f func(x, y *Elt, n uint)) { 35 const numTests = 1 << 9 36 var x, y Elt 37 for i := 0; i < numTests; i++ { 38 _, _ = rand.Read(x[:]) 39 _, _ = rand.Read(y[:]) 40 b := uint(y[0] & 0x1) 41 want0 := conv.BytesLe2BigInt(x[:]) 42 want1 := conv.BytesLe2BigInt(y[:]) 43 if b != 0 { 44 want0 = conv.BytesLe2BigInt(y[:]) 45 want1 = conv.BytesLe2BigInt(x[:]) 46 } 47 48 f(&x, &y, b) 49 got0 := conv.BytesLe2BigInt(x[:]) 50 got1 := conv.BytesLe2BigInt(y[:]) 51 52 if got0.Cmp(want0) != 0 { 53 test.ReportError(t, got0, want0, x, y, b) 54 } 55 if got1.Cmp(want1) != 0 { 56 test.ReportError(t, got1, want1, x, y, b) 57 } 58 } 59 } 60 61 func testAdd(t *testing.T, f func(z, x, y *Elt)) { 62 const numTests = 1 << 9 63 var x, y, z Elt 64 prime := P() 65 p := conv.BytesLe2BigInt(prime[:]) 66 for i := 0; i < numTests; i++ { 67 _, _ = rand.Read(x[:]) 68 _, _ = rand.Read(y[:]) 69 f(&z, &x, &y) 70 Modp(&z) 71 got := conv.BytesLe2BigInt(z[:]) 72 73 xx, yy := conv.BytesLe2BigInt(x[:]), conv.BytesLe2BigInt(y[:]) 74 want := xx.Add(xx, yy).Mod(xx, p) 75 76 if got.Cmp(want) != 0 { 77 test.ReportError(t, got, want, x, y) 78 } 79 } 80 } 81 82 func testSub(t *testing.T, f func(z, x, y *Elt)) { 83 const numTests = 1 << 9 84 var x, y, z Elt 85 prime := P() 86 p := conv.BytesLe2BigInt(prime[:]) 87 for i := 0; i < numTests; i++ { 88 _, _ = rand.Read(x[:]) 89 _, _ = rand.Read(y[:]) 90 f(&z, &x, &y) 91 Modp(&z) 92 got := conv.BytesLe2BigInt(z[:]) 93 94 xx, yy := conv.BytesLe2BigInt(x[:]), conv.BytesLe2BigInt(y[:]) 95 want := xx.Sub(xx, yy).Mod(xx, p) 96 97 if got.Cmp(want) != 0 { 98 test.ReportError(t, got, want, x, y) 99 } 100 } 101 } 102 103 func testAddSub(t *testing.T, f func(x, y *Elt)) { 104 const numTests = 1 << 9 105 var x, y Elt 106 prime := P() 107 p := conv.BytesLe2BigInt(prime[:]) 108 want0, want1 := big.NewInt(0), big.NewInt(0) 109 for i := 0; i < numTests; i++ { 110 _, _ = rand.Read(x[:]) 111 _, _ = rand.Read(y[:]) 112 xx, yy := conv.BytesLe2BigInt(x[:]), conv.BytesLe2BigInt(y[:]) 113 want0.Add(xx, yy).Mod(want0, p) 114 want1.Sub(xx, yy).Mod(want1, p) 115 116 f(&x, &y) 117 Modp(&x) 118 Modp(&y) 119 got0 := conv.BytesLe2BigInt(x[:]) 120 got1 := conv.BytesLe2BigInt(y[:]) 121 122 if got0.Cmp(want0) != 0 { 123 test.ReportError(t, got0, want0, x, y) 124 } 125 if got1.Cmp(want1) != 0 { 126 test.ReportError(t, got1, want1, x, y) 127 } 128 } 129 } 130 131 func testMul(t *testing.T, f func(z, x, y *Elt)) { 132 const numTests = 1 << 9 133 var x, y, z Elt 134 prime := P() 135 p := conv.BytesLe2BigInt(prime[:]) 136 for i := 0; i < numTests; i++ { 137 _, _ = rand.Read(x[:]) 138 _, _ = rand.Read(y[:]) 139 f(&z, &x, &y) 140 Modp(&z) 141 got := conv.BytesLe2BigInt(z[:]) 142 143 xx, yy := conv.BytesLe2BigInt(x[:]), conv.BytesLe2BigInt(y[:]) 144 want := xx.Mul(xx, yy).Mod(xx, p) 145 146 if got.Cmp(want) != 0 { 147 test.ReportError(t, got, want, x, y) 148 } 149 } 150 } 151 152 func testSqr(t *testing.T, f func(z, x *Elt)) { 153 const numTests = 1 << 9 154 var x, z Elt 155 prime := P() 156 p := conv.BytesLe2BigInt(prime[:]) 157 for i := 0; i < numTests; i++ { 158 _, _ = rand.Read(x[:]) 159 f(&z, &x) 160 Modp(&z) 161 got := conv.BytesLe2BigInt(z[:]) 162 163 xx := conv.BytesLe2BigInt(x[:]) 164 want := xx.Mul(xx, xx).Mod(xx, p) 165 166 if got.Cmp(want) != 0 { 167 test.ReportError(t, got, want, x) 168 } 169 } 170 } 171 172 func TestModp(t *testing.T) { 173 const numTests = 1 << 9 174 var x Elt 175 prime := P() 176 p := conv.BytesLe2BigInt(prime[:]) 177 two256 := big.NewInt(1) 178 two256.Lsh(two256, 256) 179 want := new(big.Int) 180 for i := 0; i < numTests; i++ { 181 bigX, _ := rand.Int(rand.Reader, two256) 182 bigX.Add(bigX, p).Mod(bigX, two256) 183 conv.BigInt2BytesLe(x[:], bigX) 184 185 Modp(&x) 186 got := conv.BytesLe2BigInt(x[:]) 187 188 want.Mod(bigX, p) 189 190 if got.Cmp(want) != 0 { 191 test.ReportError(t, got, want, bigX) 192 } 193 } 194 } 195 196 func TestIsZero(t *testing.T) { 197 var x Elt 198 got := IsZero(&x) 199 want := true 200 if got != want { 201 test.ReportError(t, got, want, x) 202 } 203 204 SetOne(&x) 205 got = IsZero(&x) 206 want = false 207 if got != want { 208 test.ReportError(t, got, want, x) 209 } 210 211 x = P() 212 got = IsZero(&x) 213 want = true 214 if got != want { 215 test.ReportError(t, got, want, x) 216 } 217 } 218 219 func TestToBytes(t *testing.T) { 220 const numTests = 1 << 9 221 var x Elt 222 var got, want [Size]byte 223 for i := 0; i < numTests; i++ { 224 _, _ = rand.Read(x[:]) 225 err := ToBytes(got[:], &x) 226 conv.BigInt2BytesLe(want[:], conv.BytesLe2BigInt(x[:])) 227 228 if err != nil || got != want { 229 test.ReportError(t, got, want, x) 230 } 231 } 232 var largeSlice [Size + 1]byte 233 err := ToBytes(largeSlice[:], &x) 234 if err == nil { 235 test.ReportError(t, got, want, largeSlice) 236 } 237 } 238 239 func TestString(t *testing.T) { 240 const numTests = 1 << 9 241 var x Elt 242 var bigX big.Int 243 for i := 0; i < numTests; i++ { 244 _, _ = rand.Read(x[:]) 245 got, _ := bigX.SetString(fmt.Sprint(x), 0) 246 want := conv.BytesLe2BigInt(x[:]) 247 248 if got.Cmp(want) != 0 { 249 test.ReportError(t, got, want, x) 250 } 251 } 252 } 253 254 func TestNeg(t *testing.T) { 255 const numTests = 1 << 9 256 var x, z Elt 257 prime := P() 258 p := conv.BytesLe2BigInt(prime[:]) 259 for i := 0; i < numTests; i++ { 260 _, _ = rand.Read(x[:]) 261 Neg(&z, &x) 262 Modp(&z) 263 got := conv.BytesLe2BigInt(z[:]) 264 265 bigX := conv.BytesLe2BigInt(x[:]) 266 want := bigX.Neg(bigX).Mod(bigX, p) 267 268 if got.Cmp(want) != 0 { 269 test.ReportError(t, got, want, bigX) 270 } 271 } 272 } 273 274 func TestInv(t *testing.T) { 275 const numTests = 1 << 9 276 var x, z Elt 277 prime := P() 278 p := conv.BytesLe2BigInt(prime[:]) 279 for i := 0; i < numTests; i++ { 280 _, _ = rand.Read(x[:]) 281 Inv(&z, &x) 282 Modp(&z) 283 got := conv.BytesLe2BigInt(z[:]) 284 285 xx := conv.BytesLe2BigInt(x[:]) 286 want := xx.ModInverse(xx, p) 287 288 if got.Cmp(want) != 0 { 289 test.ReportError(t, got, want, x) 290 } 291 } 292 } 293 294 func TestInvSqrt(t *testing.T) { 295 const numTests = 1 << 9 296 var x, y, z Elt 297 prime := P() 298 p := conv.BytesLe2BigInt(prime[:]) 299 exp := big.NewInt(1) 300 exp.Add(p, exp).Rsh(exp, 2) 301 var frac, root, sqRoot big.Int 302 var wantQR bool 303 var want *big.Int 304 for i := 0; i < numTests; i++ { 305 _, _ = rand.Read(x[:]) 306 _, _ = rand.Read(y[:]) 307 308 gotQR := InvSqrt(&z, &x, &y) 309 Modp(&z) 310 got := conv.BytesLe2BigInt(z[:]) 311 312 xx := conv.BytesLe2BigInt(x[:]) 313 yy := conv.BytesLe2BigInt(y[:]) 314 frac.ModInverse(yy, p).Mul(&frac, xx).Mod(&frac, p) 315 root.Exp(&frac, exp, p) 316 sqRoot.Mul(&root, &root).Mod(&sqRoot, p) 317 318 if sqRoot.Cmp(&frac) == 0 { 319 want = &root 320 wantQR = true 321 } else { 322 want = big.NewInt(0) 323 wantQR = false 324 } 325 326 if wantQR { 327 if gotQR != wantQR || got.Cmp(want) != 0 { 328 test.ReportError(t, got, want, x, y) 329 } 330 } else { 331 if gotQR != wantQR { 332 test.ReportError(t, gotQR, wantQR, x, y) 333 } 334 } 335 } 336 } 337 338 func TestGeneric(t *testing.T) { 339 t.Run("Cmov", func(t *testing.T) { testCmov(t, cmovGeneric) }) 340 t.Run("Cswap", func(t *testing.T) { testCswap(t, cswapGeneric) }) 341 t.Run("Add", func(t *testing.T) { testAdd(t, addGeneric) }) 342 t.Run("Sub", func(t *testing.T) { testSub(t, subGeneric) }) 343 t.Run("AddSub", func(t *testing.T) { testAddSub(t, addsubGeneric) }) 344 t.Run("Mul", func(t *testing.T) { testMul(t, mulGeneric) }) 345 t.Run("Sqr", func(t *testing.T) { testSqr(t, sqrGeneric) }) 346 } 347 348 func TestNative(t *testing.T) { 349 t.Run("Cmov", func(t *testing.T) { testCmov(t, Cmov) }) 350 t.Run("Cswap", func(t *testing.T) { testCswap(t, Cswap) }) 351 t.Run("Add", func(t *testing.T) { testAdd(t, Add) }) 352 t.Run("Sub", func(t *testing.T) { testSub(t, Sub) }) 353 t.Run("AddSub", func(t *testing.T) { testAddSub(t, AddSub) }) 354 t.Run("Mul", func(t *testing.T) { testMul(t, Mul) }) 355 t.Run("Sqr", func(t *testing.T) { testSqr(t, Sqr) }) 356 } 357 358 func BenchmarkFp(b *testing.B) { 359 var x, y, z Elt 360 _, _ = rand.Read(x[:]) 361 _, _ = rand.Read(y[:]) 362 _, _ = rand.Read(z[:]) 363 b.Run("Add", func(b *testing.B) { 364 for i := 0; i < b.N; i++ { 365 Add(&x, &y, &z) 366 } 367 }) 368 b.Run("Sub", func(b *testing.B) { 369 for i := 0; i < b.N; i++ { 370 Sub(&x, &y, &z) 371 } 372 }) 373 b.Run("Mul", func(b *testing.B) { 374 for i := 0; i < b.N; i++ { 375 Mul(&x, &y, &z) 376 } 377 }) 378 b.Run("Sqr", func(b *testing.B) { 379 for i := 0; i < b.N; i++ { 380 Sqr(&x, &y) 381 } 382 }) 383 b.Run("Inv", func(b *testing.B) { 384 for i := 0; i < b.N; i++ { 385 Inv(&x, &y) 386 } 387 }) 388 b.Run("InvSqrt", func(b *testing.B) { 389 for i := 0; i < b.N; i++ { 390 _ = InvSqrt(&z, &x, &y) 391 } 392 }) 393 }