github.com/cloudflare/circl@v1.5.0/ecc/fourq/fq_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 tFqAdd = func(z, x, y *Fq) 13 tFqSub = func(z, x, y *Fq) 14 tFqMul = func(z, x, y *Fq) 15 tFqSqr = func(z, x *Fq) 16 ) 17 18 func TestFqOne(t *testing.T) { 19 x := &Fq{} 20 x.setOne() 21 got0, got1 := x.toBigInt() 22 want0, want1 := big.NewInt(1), big.NewInt(0) 23 if got0.Cmp(want0) != 0 { 24 test.ReportError(t, got0, want0, x) 25 } 26 if got1.Cmp(want1) != 0 { 27 test.ReportError(t, got1, want1, x) 28 } 29 } 30 31 func TestFqSign(t *testing.T) { 32 testTimes := 1 << 9 33 x := &Fq{} 34 P := getModulus() 35 var P1div2 big.Int 36 P1div2.Add(P, big.NewInt(1)).Rsh(&P1div2, 1) // (p+1)/2 37 38 // Verifying Sign(0) = 0 39 x.setBigInt(big.NewInt(0), big.NewInt(0)) 40 got := fqSgn(x) 41 want := 0 42 if got != want { 43 test.ReportError(t, got, want, x) 44 } 45 46 // Verifying Sign(P) = 0 47 x.setBigInt(P, P) 48 got = fqSgn(x) 49 want = 0 50 if got != want { 51 test.ReportError(t, got, want, x) 52 } 53 54 // Verifying Sign( (p+1)/2 ) = -1 55 x.setBigInt(&P1div2, &P1div2) 56 got = fqSgn(x) 57 want = -1 58 if got != want { 59 test.ReportError(t, got, want, x) 60 } 61 62 // Verifying x be a non-zero positive 63 for i := 0; i < testTimes; i++ { 64 bigX1, _ := rand.Int(rand.Reader, &P1div2) 65 x.setBigInt(P, bigX1) 66 got = fqSgn(x) 67 want = 1 68 if got != want { 69 test.ReportError(t, got, want, x) 70 } 71 } 72 // Verifying x be a non-zero positive 73 for i := 0; i < testTimes; i++ { 74 bigX0, _ := rand.Int(rand.Reader, &P1div2) 75 bigX1, _ := rand.Int(rand.Reader, &P1div2) 76 x.setBigInt(bigX0, bigX1) 77 got = fqSgn(x) 78 want = 1 79 if got != want { 80 test.ReportError(t, got, want, x) 81 } 82 } 83 // Verifying x be a non-zero negative 84 for i := 0; i < testTimes; i++ { 85 bigX1, _ := rand.Int(rand.Reader, &P1div2) 86 bigX1.Add(bigX1, &P1div2) 87 x.setBigInt(P, bigX1) 88 got = fqSgn(x) 89 want = -1 90 if got != want { 91 test.ReportError(t, got, want, x) 92 } 93 } 94 // Verifying x be a non-zero negative 95 for i := 0; i < testTimes; i++ { 96 bigX0, _ := rand.Int(rand.Reader, &P1div2) 97 bigX1, _ := rand.Int(rand.Reader, &P1div2) 98 bigX0.Add(bigX0, &P1div2) 99 bigX1.Add(bigX1, &P1div2) 100 x.setBigInt(bigX0, bigX1) 101 got = fqSgn(x) 102 want = -1 103 if got != want { 104 test.ReportError(t, got, want, x) 105 } 106 } 107 } 108 109 func TestFqIsZero(t *testing.T) { 110 x := &Fq{} 111 P := getModulus() 112 // Verifying x=0 113 x.setBigInt(big.NewInt(0), big.NewInt(0)) 114 got := x.isZero() 115 want := true 116 if got != want { 117 test.ReportError(t, got, want, x) 118 } 119 120 // Verifying x=P goes to 0 121 x.setBigInt(P, P) 122 got = x.isZero() 123 want = true 124 if got != want { 125 test.ReportError(t, got, want, x) 126 } 127 128 // Verifying x!=0 129 bigX0, _ := rand.Int(rand.Reader, P) 130 bigX1, _ := rand.Int(rand.Reader, P) 131 x.setBigInt(bigX0, bigX1) 132 got = x.isZero() 133 want = false 134 if got != want { 135 test.ReportError(t, got, want, x) 136 } 137 } 138 139 func TestFqNeg(t *testing.T) { 140 testTimes := 1 << 9 141 x, z := &Fq{}, &Fq{} 142 P := getModulus() 143 for i := 0; i < testTimes; i++ { 144 bigX0, _ := rand.Int(rand.Reader, P) 145 bigX1, _ := rand.Int(rand.Reader, P) 146 147 x.setBigInt(bigX0, bigX1) 148 fqNeg(z, x) 149 got0, got1 := z.toBigInt() 150 151 want0 := bigX0.Neg(bigX0) 152 want1 := bigX1.Neg(bigX1) 153 want0 = want0.Mod(want0, P) 154 want1 = want1.Mod(want1, P) 155 if got0.Cmp(want0) != 0 { 156 test.ReportError(t, got0, want0, x) 157 } 158 if got1.Cmp(want1) != 0 { 159 test.ReportError(t, got1, want1, x) 160 } 161 } 162 } 163 164 func testFqAdd(t *testing.T, f tFqAdd) { 165 testTimes := 1 << 9 166 x, y, z := &Fq{}, &Fq{}, &Fq{} 167 P := getModulus() 168 for i := 0; i < testTimes; i++ { 169 bigX0, _ := rand.Int(rand.Reader, P) 170 bigX1, _ := rand.Int(rand.Reader, P) 171 bigY0, _ := rand.Int(rand.Reader, P) 172 bigY1, _ := rand.Int(rand.Reader, P) 173 174 x.setBigInt(bigX0, bigX1) 175 y.setBigInt(bigY0, bigY1) 176 f(z, x, y) 177 got0, got1 := z.toBigInt() 178 179 want0 := bigX0.Add(bigX0, bigY0) 180 want1 := bigX1.Add(bigX1, bigY1) 181 want0 = want0.Mod(want0, P) 182 want1 = want1.Mod(want1, P) 183 184 if got0.Cmp(want0) != 0 { 185 test.ReportError(t, got0, want0, x, y) 186 } 187 if got1.Cmp(want1) != 0 { 188 test.ReportError(t, got1, want1, x, y) 189 } 190 } 191 } 192 193 func testFqSub(t *testing.T, f tFqSub) { 194 testTimes := 1 << 9 195 x, y, z := &Fq{}, &Fq{}, &Fq{} 196 P := getModulus() 197 for i := 0; i < testTimes; i++ { 198 bigX0, _ := rand.Int(rand.Reader, P) 199 bigX1, _ := rand.Int(rand.Reader, P) 200 bigY0, _ := rand.Int(rand.Reader, P) 201 bigY1, _ := rand.Int(rand.Reader, P) 202 203 x.setBigInt(bigX0, bigX1) 204 y.setBigInt(bigY0, bigY1) 205 f(z, x, y) 206 got0, got1 := z.toBigInt() 207 208 want0 := bigX0.Sub(bigX0, bigY0) 209 want1 := bigX1.Sub(bigX1, bigY1) 210 want0 = want0.Mod(want0, P) 211 want1 = want1.Mod(want1, P) 212 213 if got0.Cmp(want0) != 0 { 214 test.ReportError(t, got0, want0, x, y) 215 } 216 if got1.Cmp(want1) != 0 { 217 test.ReportError(t, got1, want1, x, y) 218 } 219 } 220 } 221 222 func testFqMul(t *testing.T, f tFqMul) { 223 testTimes := 1 << 9 224 x, y, z := &Fq{}, &Fq{}, &Fq{} 225 P := getModulus() 226 for i := 0; i < testTimes; i++ { 227 bigX0, _ := rand.Int(rand.Reader, P) 228 bigX1, _ := rand.Int(rand.Reader, P) 229 bigY0, _ := rand.Int(rand.Reader, P) 230 bigY1, _ := rand.Int(rand.Reader, P) 231 232 x.setBigInt(bigX0, bigX1) 233 y.setBigInt(bigY0, bigY1) 234 f(z, x, y) 235 got0, got1 := z.toBigInt() 236 237 x0y0 := new(big.Int).Mul(bigX0, bigY0) 238 x0y1 := new(big.Int).Mul(bigX0, bigY1) 239 x1y0 := new(big.Int).Mul(bigX1, bigY0) 240 x1y1 := new(big.Int).Mul(bigX1, bigY1) 241 want0 := x0y0.Sub(x0y0, x1y1) 242 want1 := x1y0.Add(x1y0, x0y1) 243 want0 = want0.Mod(want0, P) 244 want1 = want1.Mod(want1, P) 245 246 if got0.Cmp(want0) != 0 { 247 test.ReportError(t, got0, want0, x, y) 248 } 249 if got1.Cmp(want1) != 0 { 250 test.ReportError(t, got1, want1, x, y) 251 } 252 } 253 } 254 255 func testFqSqr(t *testing.T, f tFqSqr) { 256 testTimes := 1 << 9 257 x, z := &Fq{}, &Fq{} 258 P := getModulus() 259 for i := 0; i < testTimes; i++ { 260 bigX0, _ := rand.Int(rand.Reader, P) 261 bigX1, _ := rand.Int(rand.Reader, P) 262 263 x.setBigInt(bigX0, bigX1) 264 f(z, x) 265 got0, got1 := z.toBigInt() 266 267 x0x0 := new(big.Int).Mul(bigX0, bigX0) 268 x0x1 := new(big.Int).Mul(bigX0, bigX1) 269 x1x1 := new(big.Int).Mul(bigX1, bigX1) 270 want0 := x0x0.Sub(x0x0, x1x1) 271 want1 := x0x1.Lsh(x0x1, 1) 272 want0 = want0.Mod(want0, P) 273 want1 = want1.Mod(want1, P) 274 275 if got0.Cmp(want0) != 0 { 276 test.ReportError(t, got0, want0, x) 277 } 278 if got1.Cmp(want1) != 0 { 279 test.ReportError(t, got1, want1, x) 280 } 281 } 282 } 283 284 func TestFqInv(t *testing.T) { 285 testTimes := 1 << 9 286 x, z := &Fq{}, &Fq{} 287 P := getModulus() 288 for i := 0; i < testTimes; i++ { 289 bigX0, _ := rand.Int(rand.Reader, P) 290 bigX1, _ := rand.Int(rand.Reader, P) 291 292 x.setBigInt(bigX0, bigX1) 293 fqInv(z, x) 294 got0, got1 := z.toBigInt() 295 296 x0x0 := new(big.Int).Mul(bigX0, bigX0) 297 x1x1 := new(big.Int).Mul(bigX1, bigX1) 298 inv := x0x0.Add(x0x0, x1x1) 299 inv.ModInverse(inv, P) 300 want0 := bigX0.Mul(bigX0, inv) 301 want1 := bigX1.Mul(bigX1, inv).Neg(bigX1) 302 want0 = want0.Mod(want0, P) 303 want1 = want1.Mod(want1, P) 304 305 if got0.Cmp(want0) != 0 { 306 test.ReportError(t, got0, want0, x) 307 } 308 if got1.Cmp(want1) != 0 { 309 test.ReportError(t, got1, want1, x) 310 } 311 } 312 } 313 314 func TestFqGeneric(t *testing.T) { 315 t.Run("Add", func(t *testing.T) { testFqAdd(t, fqAddGeneric) }) 316 t.Run("Sub", func(t *testing.T) { testFqSub(t, fqSubGeneric) }) 317 t.Run("Mul", func(t *testing.T) { testFqMul(t, fqMulGeneric) }) 318 t.Run("Sqr", func(t *testing.T) { testFqSqr(t, fqSqrGeneric) }) 319 } 320 321 func TestFqNative(t *testing.T) { 322 t.Run("Add", func(t *testing.T) { testFqAdd(t, fqAdd) }) 323 t.Run("Sub", func(t *testing.T) { testFqSub(t, fqSub) }) 324 t.Run("Mul", func(t *testing.T) { testFqMul(t, fqMul) }) 325 t.Run("Sqr", func(t *testing.T) { testFqSqr(t, fqSqr) }) 326 } 327 328 func BenchmarkFq(b *testing.B) { 329 x, y, z := &Fq{}, &Fq{}, &Fq{} 330 331 b.Run("Add", func(b *testing.B) { 332 for i := 0; i < b.N; i++ { 333 fqAdd(z, x, y) 334 } 335 }) 336 b.Run("Sub", func(b *testing.B) { 337 for i := 0; i < b.N; i++ { 338 fqSub(z, x, y) 339 } 340 }) 341 b.Run("Mul", func(b *testing.B) { 342 for i := 0; i < b.N; i++ { 343 fqMul(z, x, y) 344 } 345 }) 346 b.Run("Sqr", func(b *testing.B) { 347 for i := 0; i < b.N; i++ { 348 fqSqr(z, x) 349 } 350 }) 351 b.Run("Inv", func(b *testing.B) { 352 for i := 0; i < b.N; i++ { 353 fqInv(z, x) 354 } 355 }) 356 b.Run("Sqrt", func(b *testing.B) { 357 for i := 0; i < b.N; i++ { 358 fqSqrt(z, x, y, 1) 359 } 360 }) 361 }