github.com/cloudflare/circl@v1.5.0/dh/sidh/internal/p503/fp2_test.go (about) 1 // Code generated by go generate; DO NOT EDIT. 2 // This file was generated by robots. 3 4 package p503 5 6 import ( 7 "math/rand" 8 "reflect" 9 "testing" 10 "testing/quick" 11 12 "github.com/cloudflare/circl/dh/sidh/internal/common" 13 ) 14 15 type testParams struct { 16 Point common.ProjectivePoint 17 Cparam common.ProjectiveCurveParameters 18 ExtElem common.Fp2 19 } 20 21 // Returns true if lhs = rhs. Takes variable time. 22 func vartimeEqFp2(lhs, rhs *common.Fp2) bool { 23 a := *lhs 24 b := *rhs 25 26 modP503(&a.A) 27 modP503(&a.B) 28 modP503(&b.A) 29 modP503(&b.B) 30 31 eq := true 32 for i := 0; i < FpWords && eq; i++ { 33 eq = eq && (a.A[i] == b.A[i]) 34 eq = eq && (a.B[i] == b.B[i]) 35 } 36 return eq 37 } 38 39 func (testParams) generateFp2(rand *rand.Rand) common.Fp2 { 40 // Generation strategy: low limbs taken from [0,2^64); high limb 41 // taken from smaller range 42 // 43 // Size hint is ignored since all elements are fixed size. 44 // 45 // Field elements taken in range [0,2p). Emulate this by capping 46 // the high limb by the top digit of 2*p-1: 47 // 48 // sage: (2*p-1).digits(2^64)[-1] 49 // 50 // This still allows generating values >= 2p, but hopefully that 51 // excess is OK (and if it's not, we'll find out, because it's for 52 // testing...) 53 highLimb := rand.Uint64() % P503x2[FpWords-1] 54 fpElementGen := func() (fp common.Fp) { 55 for i := 0; i < (FpWords - 1); i++ { 56 fp[i] = rand.Uint64() 57 } 58 fp[FpWords-1] = highLimb 59 return fp 60 } 61 return common.Fp2{A: fpElementGen(), B: fpElementGen()} 62 } 63 64 func (c testParams) Generate(rand *rand.Rand, size int) reflect.Value { 65 return reflect.ValueOf( 66 testParams{ 67 common.ProjectivePoint{ 68 X: c.generateFp2(rand), 69 Z: c.generateFp2(rand), 70 }, 71 common.ProjectiveCurveParameters{ 72 A: c.generateFp2(rand), 73 C: c.generateFp2(rand), 74 }, 75 c.generateFp2(rand), 76 }) 77 } 78 79 func TestOne(t *testing.T) { 80 var tmp common.Fp2 81 82 mul(&tmp, ¶ms.OneFp2, ¶ms.A.AffineP) 83 if !vartimeEqFp2(&tmp, ¶ms.A.AffineP) { 84 t.Error("Not equal 1") 85 } 86 } 87 88 func TestFp2ToBytesRoundTrip(t *testing.T) { 89 roundTrips := func(x testParams) bool { 90 xBytes := make([]byte, 2*params.Bytelen) 91 var xPrime common.Fp2 92 93 common.Fp2ToBytes(xBytes[:], &x.ExtElem, params.Bytelen) 94 common.BytesToFp2(&xPrime, xBytes[:], params.Bytelen) 95 return vartimeEqFp2(&xPrime, &x.ExtElem) 96 } 97 98 if err := quick.Check(roundTrips, quickCheckConfig); err != nil { 99 t.Error(err) 100 } 101 } 102 103 func TestFp2MulDistributesOverAdd(t *testing.T) { 104 mulDistributesOverAdd := func(x, y, z testParams) bool { 105 // Compute t1 = (x+y)*z 106 t1 := new(common.Fp2) 107 add(t1, &x.ExtElem, &y.ExtElem) 108 mul(t1, t1, &z.ExtElem) 109 110 // Compute t2 = x*z + y*z 111 t2 := new(common.Fp2) 112 t3 := new(common.Fp2) 113 mul(t2, &x.ExtElem, &z.ExtElem) 114 mul(t3, &y.ExtElem, &z.ExtElem) 115 add(t2, t2, t3) 116 117 return vartimeEqFp2(t1, t2) 118 } 119 120 if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil { 121 t.Error(err) 122 } 123 } 124 125 func TestFp2MulIsAssociative(t *testing.T) { 126 isAssociative := func(x, y, z testParams) bool { 127 // Compute t1 = (x*y)*z 128 t1 := new(common.Fp2) 129 mul(t1, &x.ExtElem, &y.ExtElem) 130 mul(t1, t1, &z.ExtElem) 131 132 // Compute t2 = (y*z)*x 133 t2 := new(common.Fp2) 134 mul(t2, &y.ExtElem, &z.ExtElem) 135 mul(t2, t2, &x.ExtElem) 136 137 return vartimeEqFp2(t1, t2) 138 } 139 140 if err := quick.Check(isAssociative, quickCheckConfig); err != nil { 141 t.Error(err) 142 } 143 } 144 145 func TestFp2SquareMatchesMul(t *testing.T) { 146 sqrMatchesMul := func(x testParams) bool { 147 // Compute t1 = (x*x) 148 t1 := new(common.Fp2) 149 mul(t1, &x.ExtElem, &x.ExtElem) 150 151 // Compute t2 = x^2 152 t2 := new(common.Fp2) 153 sqr(t2, &x.ExtElem) 154 155 return vartimeEqFp2(t1, t2) 156 } 157 158 if err := quick.Check(sqrMatchesMul, quickCheckConfig); err != nil { 159 t.Error(err) 160 } 161 } 162 163 func TestFp2Inv(t *testing.T) { 164 inverseIsCorrect := func(x testParams) bool { 165 z := new(common.Fp2) 166 inv(z, &x.ExtElem) 167 168 // Now z = (1/x), so (z * x) * x == x 169 mul(z, z, &x.ExtElem) 170 mul(z, z, &x.ExtElem) 171 172 return vartimeEqFp2(z, &x.ExtElem) 173 } 174 175 // This is more expensive; run fewer tests 176 fasterCheckConfig := &quick.Config{MaxCount: (1 << 11)} 177 if err := quick.Check(inverseIsCorrect, fasterCheckConfig); err != nil { 178 t.Error(err) 179 } 180 } 181 182 func TestFp2Batch3Inv(t *testing.T) { 183 batchInverseIsCorrect := func(x1, x2, x3 testParams) bool { 184 var x1Inv, x2Inv, x3Inv common.Fp2 185 inv(&x1Inv, &x1.ExtElem) 186 inv(&x2Inv, &x2.ExtElem) 187 inv(&x3Inv, &x3.ExtElem) 188 189 var y1, y2, y3 common.Fp2 190 Fp2Batch3Inv(&x1.ExtElem, &x2.ExtElem, &x3.ExtElem, &y1, &y2, &y3) 191 192 return (vartimeEqFp2(&x1Inv, &y1) && vartimeEqFp2(&x2Inv, &y2) && vartimeEqFp2(&x3Inv, &y3)) 193 } 194 195 // This is more expensive; run fewer tests 196 fasterCheckConfig := &quick.Config{MaxCount: (1 << 8)} 197 if err := quick.Check(batchInverseIsCorrect, fasterCheckConfig); err != nil { 198 t.Error(err) 199 } 200 } 201 202 func BenchmarkFp2Mul(b *testing.B) { 203 z := &common.Fp2{A: bench_x, B: bench_y} 204 w := new(common.Fp2) 205 206 for n := 0; n < b.N; n++ { 207 mul(w, z, z) 208 } 209 } 210 211 func BenchmarkFp2Inv(b *testing.B) { 212 z := &common.Fp2{A: bench_x, B: bench_y} 213 w := new(common.Fp2) 214 215 for n := 0; n < b.N; n++ { 216 inv(w, z) 217 } 218 } 219 220 func BenchmarkFp2Square(b *testing.B) { 221 z := &common.Fp2{A: bench_x, B: bench_y} 222 w := new(common.Fp2) 223 224 for n := 0; n < b.N; n++ { 225 sqr(w, z) 226 } 227 } 228 229 func BenchmarkFp2Add(b *testing.B) { 230 z := &common.Fp2{A: bench_x, B: bench_y} 231 w := new(common.Fp2) 232 233 for n := 0; n < b.N; n++ { 234 add(w, z, z) 235 } 236 } 237 238 func BenchmarkFp2Sub(b *testing.B) { 239 z := &common.Fp2{A: bench_x, B: bench_y} 240 w := new(common.Fp2) 241 242 for n := 0; n < b.N; n++ { 243 sub(w, z, z) 244 } 245 }