1 package csidh
2
3 import (
4 "bytes"
5 "crypto/rand"
6 "encoding/binary"
7 "encoding/hex"
8 "encoding/json"
9 "os"
10 "testing"
11
12 . "github.com/cloudflare/circl/internal/test"
13 )
14
15
16 const (
17 Valid = iota
18 ValidPublicKey2
19 InvalidSharedSecret
20 InvalidPublicKey1
21 InvalidPublicKey2
22 )
23
24 var StatusValues = map[int]string{
25 Valid: "valid",
26 ValidPublicKey2: "valid_public_key2",
27 InvalidSharedSecret: "invalid_shared_secret",
28 InvalidPublicKey1: "invalid_public_key1",
29 InvalidPublicKey2: "invalid_public_key2",
30 }
31
32 var rng = rand.Reader
33
34 type TestVector struct {
35 ID int `json:"Id"`
36 Pk1 string `json:"Pk1"`
37 Pr1 string `json:"Pr1"`
38 Pk2 string `json:"Pk2"`
39 Ss string `json:"Ss"`
40 Status string `json:"status"`
41 }
42
43 type TestVectors struct {
44 Vectors []TestVector `json:"Vectors"`
45 }
46
47 func TestCompare64(t *testing.T) {
48 const s uint64 = 0xFFFFFFFFFFFFFFFF
49 val1 := fp{0, 2, 3, 4, 5, 6, 7, 8}
50 val2 := fp{s, s, s, s, s, s, s, s}
51 var zero fp
52
53 if !zero.isZero() {
54 t.Errorf("isZero returned true, where it should be false")
55 }
56 if val1.isZero() {
57 t.Errorf("isZero returned false, where it should be true")
58 }
59 if val2.isZero() {
60 t.Errorf("isZero returned false, where it should be true")
61 }
62 }
63
64 func TestEphemeralKeyExchange(t *testing.T) {
65 var ss1, ss2 [64]byte
66 var prv1, prv2 PrivateKey
67 var pub1, pub2 PublicKey
68
69 prvBytes1 := []byte{0xaa, 0x54, 0xe4, 0xd4, 0xd0, 0xbd, 0xee, 0xcb, 0xf4, 0xd0, 0xc2, 0xbc, 0x52, 0x44, 0x11, 0xee, 0xe1, 0x14, 0xd2, 0x24, 0xe5, 0x0, 0xcc, 0xf5, 0xc0, 0xe1, 0x1e, 0xb3, 0x43, 0x52, 0x45, 0xbe, 0xfb, 0x54, 0xc0, 0x55, 0xb2}
70 prv1.Import(prvBytes1)
71 GeneratePublicKey(&pub1, &prv1, rng)
72
73 CheckNoErr(t, GeneratePrivateKey(&prv2, rng), "PrivateKey generation failed")
74 GeneratePublicKey(&pub2, &prv2, rng)
75
76 CheckOk(
77 DeriveSecret(&ss1, &pub1, &prv2, rng),
78 "Derivation failed", t)
79 CheckOk(
80 DeriveSecret(&ss2, &pub2, &prv1, rng),
81 "Derivation failed", t)
82
83 if !bytes.Equal(ss1[:], ss2[:]) {
84 t.Error("ss1 != ss2")
85 }
86 }
87
88 func TestPrivateKeyExportImport(t *testing.T) {
89 var buf [37]byte
90 for i := 0; i < numIter; i++ {
91 var prv1, prv2 PrivateKey
92 CheckNoErr(t, GeneratePrivateKey(&prv1, rng), "PrivateKey generation failed")
93 prv1.Export(buf[:])
94 prv2.Import(buf[:])
95
96 for i := 0; i < len(prv1.e); i++ {
97 if prv1.e[i] != prv2.e[i] {
98 t.Error("Error occurred when public key export/import")
99 }
100 }
101 }
102 }
103
104 func TestValidateNegative(t *testing.T) {
105 pk := PublicKey{a: p}
106 pk.a[0]++
107 if Validate(&pk, rng) {
108 t.Error("Public key > p has been validated")
109 }
110
111 pk = PublicKey{a: p}
112 if Validate(&pk, rng) {
113 t.Error("Public key == p has been validated")
114 }
115
116 pk = PublicKey{a: two}
117 if Validate(&pk, rng) {
118 t.Error("Public key == 2 has been validated")
119 }
120
121 pk = PublicKey{a: twoNeg}
122 if Validate(&pk, rng) {
123 t.Error("Public key == -2 has been validated")
124 }
125 }
126
127 func TestPublicKeyExportImport(t *testing.T) {
128 var buf [64]byte
129 eq64 := func(x, y []uint64) bool {
130 for i := range x {
131 if x[i] != y[i] {
132 return false
133 }
134 }
135 return true
136 }
137
138 for i := 0; i < numIter; i++ {
139 var prv PrivateKey
140 var pub1, pub2 PublicKey
141 CheckNoErr(t, GeneratePrivateKey(&prv, rng), "PrivateKey generation failed")
142 GeneratePublicKey(&pub1, &prv, rng)
143
144 pub1.Export(buf[:])
145 pub2.Import(buf[:])
146
147 if !eq64(pub1.a[:], pub2.a[:]) {
148 t.Error("Error occurred when public key export/import")
149 }
150 }
151 }
152
153
154 func TestKAT(t *testing.T) {
155 var tests TestVectors
156
157 checkExpr := func(e bool, vec *TestVector, t *testing.T, msg string) {
158 t.Helper()
159 if !e {
160 t.Errorf("[Test ID=%d] "+msg, vec.ID)
161 }
162 }
163
164
165
166
167 checkSharedSecret := func(vec *TestVector, t *testing.T, status int) {
168 var prv1 PrivateKey
169 var pub1, pub2 PublicKey
170 var ss [SharedSecretSize]byte
171
172 prBuf, err := hex.DecodeString(vec.Pr1)
173 if err != nil {
174 t.Fatal(err)
175 }
176 checkExpr(prv1.Import(prBuf[:]), vec, t, "PrivateKey wrong")
177 pkBuf, err := hex.DecodeString(vec.Pk1)
178 if err != nil {
179 t.Fatal(err)
180 }
181 checkExpr(pub1.Import(pkBuf[:]), vec, t, "PublicKey 1 wrong")
182 pkBuf, err = hex.DecodeString(vec.Pk2)
183 if err != nil {
184 t.Fatal(err)
185 }
186 checkExpr(pub2.Import(pkBuf[:]), vec, t, "PublicKey 2 wrong")
187 checkExpr(DeriveSecret(&ss, &pub2, &prv1, rng), vec, t, "Error when deriving key")
188 ssExp, err := hex.DecodeString(vec.Ss)
189 if err != nil {
190 t.Fatal(err)
191 }
192 checkExpr(bytes.Equal(ss[:], ssExp) == (status == Valid), vec, t, "Unexpected value of shared secret")
193 }
194
195
196
197
198 checkPublicKey1 := func(vec *TestVector, t *testing.T) {
199 var prv PrivateKey
200 var pub PublicKey
201 var pubBytesGot [PublicKeySize]byte
202
203 prBuf, err := hex.DecodeString(vec.Pr1)
204 if err != nil {
205 t.Fatal(err)
206 }
207
208 pubBytesExp, err := hex.DecodeString(vec.Pk1)
209 if err != nil {
210 t.Fatal(err)
211 }
212
213 checkExpr(
214 prv.Import(prBuf[:]),
215 vec, t, "PrivateKey wrong")
216
217
218 CheckNoErr(t, GeneratePrivateKey(&prv, rng), "PrivateKey generation failed")
219 pub.Export(pubBytesGot[:])
220
221
222 checkExpr(
223 !bytes.Equal(pubBytesGot[:], pubBytesExp),
224 vec, t, "Public key generated is the same as public key from the test vector")
225 }
226
227
228
229 checkPublicKey2 := func(vec *TestVector, t *testing.T, status int) {
230 var pub PublicKey
231 pubBytesExp, err := hex.DecodeString(vec.Pk2)
232 if err != nil {
233 t.Fatal(err)
234 }
235
236 pub.Import(pubBytesExp[:])
237 checkExpr(
238 Validate(&pub, rng) == (status == Valid || status == ValidPublicKey2),
239 vec, t, "PublicKey has been validated correctly")
240 }
241
242 file, err := os.Open(katFile)
243 if err != nil {
244 t.Fatal(err.Error())
245 }
246 err = json.NewDecoder(file).Decode(&tests)
247 if err != nil {
248 t.Fatal(err.Error())
249 }
250
251
252 N := len(tests.Vectors)
253 var buf [2]byte
254 for i := 0; i < numIter; i++ {
255 _, _ = rand.Read(buf[:])
256 idx := binary.LittleEndian.Uint16(buf[:]) % uint16(N)
257 test := tests.Vectors[idx]
258 switch test.Status {
259 case StatusValues[Valid]:
260 checkSharedSecret(&test, t, Valid)
261 checkPublicKey2(&test, t, Valid)
262 case StatusValues[InvalidSharedSecret]:
263 checkSharedSecret(&test, t, InvalidSharedSecret)
264 case StatusValues[InvalidPublicKey1]:
265 checkPublicKey1(&test, t)
266 case StatusValues[InvalidPublicKey2]:
267 checkPublicKey2(&test, t, InvalidPublicKey2)
268 case StatusValues[InvalidPublicKey2]:
269 checkPublicKey2(&test, t, InvalidPublicKey2)
270 case StatusValues[ValidPublicKey2]:
271 checkPublicKey2(&test, t, ValidPublicKey2)
272 }
273 }
274 }
275
276 var (
277 prv1, prv2 PrivateKey
278 pub1, pub2 PublicKey
279 )
280
281
282 func BenchmarkGeneratePrivate(b *testing.B) {
283 for n := 0; n < b.N; n++ {
284 _ = GeneratePrivateKey(&prv1, rng)
285 }
286 }
287
288
289 func BenchmarkGenerateKeyPair(b *testing.B) {
290 for n := 0; n < b.N; n++ {
291 var pub PublicKey
292 _ = GeneratePrivateKey(&prv1, rng)
293 GeneratePublicKey(&pub, &prv1, rng)
294 }
295 }
296
297
298 func BenchmarkValidate(b *testing.B) {
299 prvBytes := []byte{0xaa, 0x54, 0xe4, 0xd4, 0xd0, 0xbd, 0xee, 0xcb, 0xf4, 0xd0, 0xc2, 0xbc, 0x52, 0x44, 0x11, 0xee, 0xe1, 0x14, 0xd2, 0x24, 0xe5, 0x0, 0xcc, 0xf5, 0xc0, 0xe1, 0x1e, 0xb3, 0x43, 0x52, 0x45, 0xbe, 0xfb, 0x54, 0xc0, 0x55, 0xb2}
300 prv1.Import(prvBytes)
301
302 var pub PublicKey
303 GeneratePublicKey(&pub, &prv1, rng)
304
305 for n := 0; n < b.N; n++ {
306 Validate(&pub, rng)
307 }
308 }
309
310
311 func BenchmarkValidateRandom(b *testing.B) {
312 var tmp [64]byte
313 var pub PublicKey
314
315
316 for n := 0; n < b.N; n++ {
317 if _, err := rng.Read(tmp[:]); err != nil {
318 b.FailNow()
319 }
320 pub.Import(tmp[:])
321 }
322 }
323
324
325 func BenchmarkValidateGenerated(b *testing.B) {
326 for n := 0; n < b.N; n++ {
327 _ = GeneratePrivateKey(&prv1, rng)
328 GeneratePublicKey(&pub1, &prv1, rng)
329 Validate(&pub1, rng)
330 }
331 }
332
333
334 func BenchmarkDerive(b *testing.B) {
335 var ss [64]byte
336
337 _ = GeneratePrivateKey(&prv1, rng)
338 GeneratePublicKey(&pub1, &prv1, rng)
339
340 _ = GeneratePrivateKey(&prv2, rng)
341 GeneratePublicKey(&pub2, &prv2, rng)
342
343 b.ResetTimer()
344 for n := 0; n < b.N; n++ {
345 DeriveSecret(&ss, &pub2, &prv1, rng)
346 }
347 }
348
349
350 func BenchmarkDeriveGenerated(b *testing.B) {
351 var ss [64]byte
352
353 for n := 0; n < b.N; n++ {
354 _ = GeneratePrivateKey(&prv1, rng)
355 GeneratePublicKey(&pub1, &prv1, rng)
356
357 _ = GeneratePrivateKey(&prv2, rng)
358 GeneratePublicKey(&pub2, &prv2, rng)
359
360 DeriveSecret(&ss, &pub2, &prv1, rng)
361 }
362 }
363
View as plain text