github.com/cloudflare/circl@v1.5.0/ecc/fourq/point_test.go (about) 1 package fourq 2 3 import ( 4 "crypto/rand" 5 "math/big" 6 "testing" 7 8 "github.com/cloudflare/circl/internal/conv" 9 "github.com/cloudflare/circl/internal/test" 10 ) 11 12 func (P *pointR1) random() { 13 var k [Size]byte 14 _, _ = rand.Read(k[:]) 15 P.ScalarBaseMult(&k) 16 } 17 18 func TestPointAddition(t *testing.T) { 19 const testTimes = 1 << 10 20 var P, Q pointR1 21 _16P := &pointR1{} 22 S := &pointR2{} 23 for i := 0; i < testTimes; i++ { 24 P.random() 25 _16P.copy(&P) 26 S.FromR1(&P) 27 // 16P = 2^4P 28 for j := 0; j < 4; j++ { 29 _16P.double() 30 } 31 // 16P = P+P...+P 32 Q.SetIdentity() 33 for j := 0; j < 16; j++ { 34 Q.add(S) 35 } 36 got := _16P.isEqual(&Q) 37 want := true 38 if got != want { 39 test.ReportError(t, got, want, P) 40 } 41 } 42 } 43 44 func TestOddMultiples(t *testing.T) { 45 const testTimes = 1 << 10 46 var P, Q, R pointR1 47 var Tab [8]pointR2 48 for i := 0; i < testTimes; i++ { 49 P.random() 50 // T = [1P, 3P, 5P, 7P, 9P, 11P, 13P, 15P] 51 P.oddMultiples(&Tab) 52 // Q = sum of all T[i] == 64P 53 Q.SetIdentity() 54 for j := range Tab { 55 Q.add(&Tab[j]) 56 } 57 // R = (2^6)P == 64P 58 for j := 0; j < 6; j++ { 59 R.double() 60 } 61 got := Q.isEqual(&R) 62 want := true 63 if got != want { 64 test.ReportError(t, got, want, P) 65 } 66 } 67 } 68 69 func TestScalarMult(t *testing.T) { 70 const testTimes = 1 << 10 71 var P, Q, G pointR1 72 var k [Size]byte 73 74 t.Run("0P=0", func(t *testing.T) { 75 for i := 0; i < testTimes; i++ { 76 P.random() 77 Q.ScalarMult(&k, &P) 78 got := Q.IsIdentity() 79 want := true 80 if got != want { 81 test.ReportError(t, got, want, P) 82 } 83 } 84 }) 85 t.Run("order*P=0", func(t *testing.T) { 86 conv.BigInt2BytesLe(k[:], conv.Uint64Le2BigInt(orderGenerator[:])) 87 for i := 0; i < testTimes; i++ { 88 P.random() 89 Q.ScalarMult(&k, &P) 90 got := Q.IsIdentity() 91 want := true 92 if got != want { 93 test.ReportError(t, got, want, P) 94 } 95 } 96 }) 97 t.Run("cofactor*P=clear(P)", func(t *testing.T) { 98 conv.BigInt2BytesLe(k[:], big.NewInt(392)) 99 for i := 0; i < testTimes; i++ { 100 P.random() 101 Q.ScalarMult(&k, &P) 102 P.ClearCofactor() 103 got := Q.isEqual(&P) 104 want := true 105 if got != want { 106 test.ReportError(t, got, want, P) 107 } 108 } 109 }) 110 t.Run("mult", func(t *testing.T) { 111 G.X = genX 112 G.Y = genY 113 for i := 0; i < testTimes; i++ { 114 _, _ = rand.Read(k[:]) 115 P.ScalarMult(&k, &G) 116 Q.ScalarBaseMult(&k) 117 got := Q.isEqual(&P) 118 want := true 119 if got != want { 120 test.ReportError(t, got, want, k) 121 } 122 } 123 }) 124 } 125 126 func TestScalar(t *testing.T) { 127 const testTimes = 1 << 12 128 var xx [5]uint64 129 two256 := big.NewInt(1) 130 two256.Lsh(two256, 256) 131 two64 := big.NewInt(1) 132 two64.Lsh(two64, 64) 133 bigOrder := conv.Uint64Le2BigInt(orderGenerator[:]) 134 135 t.Run("subYdiv16", func(t *testing.T) { 136 want := new(big.Int) 137 for i := 0; i < testTimes; i++ { 138 bigX, _ := rand.Int(rand.Reader, two256) 139 conv.BigInt2Uint64Le(xx[:], bigX) 140 x := xx 141 bigY, _ := rand.Int(rand.Reader, two64) 142 y := bigY.Int64() 143 bigY.SetInt64(y) 144 145 subYDiv16(&x, y) 146 got := conv.Uint64Le2BigInt(x[:]) 147 148 want.Sub(bigX, bigY).Rsh(want, 4) 149 150 if got.Cmp(want) != 0 { 151 test.ReportError(t, got, want, bigX, y) 152 } 153 } 154 }) 155 156 t.Run("div2subY", func(t *testing.T) { 157 want := new(big.Int) 158 for i := 0; i < testTimes; i++ { 159 bigX, _ := rand.Int(rand.Reader, two256) 160 conv.BigInt2Uint64Le(xx[:], bigX) 161 x := xx 162 bigY, _ := rand.Int(rand.Reader, two64) 163 y := bigY.Int64() 164 bigY.SetInt64(y) 165 166 div2subY(&x, y) 167 got := conv.Uint64Le2BigInt(x[:]) 168 169 want.Rsh(bigX, 1).Sub(want, bigY) 170 171 if got.Cmp(want) != 0 { 172 test.ReportError(t, got, want, bigX, y) 173 } 174 } 175 }) 176 177 t.Run("condAddOrderN", func(t *testing.T) { 178 for i := 0; i < testTimes; i++ { 179 bigX, _ := rand.Int(rand.Reader, two256) 180 conv.BigInt2Uint64Le(xx[:], bigX) 181 x := xx 182 183 condAddOrderN(&x) 184 got := conv.Uint64Le2BigInt(x[:]) 185 186 want := bigX 187 if want.Bit(0) == 0 { 188 want.Add(want, bigOrder) 189 } 190 191 if got.Cmp(want) != 0 { 192 test.ReportError(t, got, want, x) 193 } 194 } 195 }) 196 197 t.Run("recode", func(t *testing.T) { 198 var k [32]byte 199 var d [65]int8 200 got := new(big.Int) 201 for i := 0; i < testTimes; i++ { 202 _, _ = rand.Read(k[:]) 203 204 recodeScalar(&d, &k) 205 got.SetInt64(0) 206 for j := len(d) - 1; j >= 0; j-- { 207 got.Lsh(got, 4).Add(got, big.NewInt(int64(d[j]))) 208 } 209 210 want := conv.BytesLe2BigInt(k[:]) 211 if want.Bit(0) == 0 { 212 want.Add(want, bigOrder) 213 } 214 215 if got.Cmp(want) != 0 { 216 test.ReportError(t, got, want, k) 217 } 218 } 219 }) 220 } 221 222 func BenchmarkPoint(b *testing.B) { 223 var P, R pointR1 224 var Q pointR2 225 var k [Size]byte 226 227 _, _ = rand.Read(k[:]) 228 229 P.random() 230 R.random() 231 Q.FromR1(&R) 232 R.random() 233 234 b.Run("affine", func(b *testing.B) { 235 for i := 0; i < b.N; i++ { 236 P.ToAffine() 237 } 238 }) 239 b.Run("double", func(b *testing.B) { 240 for i := 0; i < b.N; i++ { 241 P.double() 242 } 243 }) 244 b.Run("add", func(b *testing.B) { 245 for i := 0; i < b.N; i++ { 246 P.add(&Q) 247 } 248 }) 249 b.Run("scmulBase", func(b *testing.B) { 250 for i := 0; i < b.N; i++ { 251 P.ScalarBaseMult(&k) 252 } 253 }) 254 b.Run("scmul", func(b *testing.B) { 255 for i := 0; i < b.N; i++ { 256 P.ScalarMult(&k, &R) 257 } 258 }) 259 }