1 package x448
2
3 import (
4 "crypto/rand"
5 "encoding/hex"
6 "encoding/json"
7 "flag"
8 "fmt"
9 "io"
10 "os"
11 "testing"
12
13 "github.com/cloudflare/circl/internal/test"
14 )
15
16 func hexStr2Key(k *Key, s string) {
17 b, err := hex.DecodeString(s)
18 if err != nil {
19 panic("Can't convert string to key")
20 }
21 copy(k[:], b)
22 }
23
24
25 var runLongTest = flag.Bool("long", false, "runs longer tests")
26
27 type katVector struct {
28 Public string `json:"input"`
29 Shared string `json:"output"`
30 Private string `json:"scalar"`
31 }
32
33 func TestRFC7748Kat(t *testing.T) {
34 const nameFile = "testdata/rfc7748_kat_test.json"
35 var kat []katVector
36
37 jsonFile, err := os.Open(nameFile)
38 if err != nil {
39 t.Fatalf("File %v can not be opened. Error: %v", nameFile, err)
40 }
41 defer jsonFile.Close()
42 input, err := io.ReadAll(jsonFile)
43 if err != nil {
44 t.Fatalf("File %v can not be read. Error: %v", nameFile, err)
45 }
46
47 err = json.Unmarshal(input, &kat)
48 if err != nil {
49 t.Fatalf("File %v can not be loaded. Error: %v", nameFile, err)
50 }
51 var priv, pub, got, want Key
52 for _, v := range kat {
53 hexStr2Key(&pub, v.Public)
54 hexStr2Key(&priv, v.Private)
55 Shared(&got, &priv, &pub)
56 hexStr2Key(&want, v.Shared)
57 if got != want {
58 test.ReportError(t, got, want, v)
59 }
60 }
61 }
62
63 type katTimes struct {
64 Times uint32 `json:"times"`
65 Key string `json:"key"`
66 }
67
68 func TestRFC7748Times(t *testing.T) {
69 const nameFile = "testdata/rfc7748_times_test.json"
70 jsonFile, err := os.Open(nameFile)
71 if err != nil {
72 t.Fatalf("File %v can not be opened. Error: %v", nameFile, err)
73 }
74 defer jsonFile.Close()
75 input, err := io.ReadAll(jsonFile)
76 if err != nil {
77 t.Fatalf("File %v can not be read. Error: %v", nameFile, err)
78 }
79
80 var kat []katTimes
81 err = json.Unmarshal(input, &kat)
82 if err != nil {
83 t.Fatalf("File %v can not be loaded. Error: %v", nameFile, err)
84 }
85 var got, want Key
86 for _, v := range kat {
87 if !*runLongTest && v.Times == uint32(1000000) {
88 t.Log("Skipped one long test, add -long flag to run longer tests")
89 continue
90 }
91 u := Key{5}
92 k := u
93 r := u
94 for i := uint32(0); i < v.Times; i++ {
95 Shared(&r, &k, &u)
96 u = k
97 k = r
98 }
99 got = k
100 hexStr2Key(&want, v.Key)
101
102 if got != want {
103 test.ReportError(t, got, want, v.Times)
104 }
105 }
106 }
107
108 func TestBase(t *testing.T) {
109 testTimes := 1 << 10
110 var got, want, secret Key
111 gen := Key{5}
112 for i := 0; i < testTimes; i++ {
113 _, _ = io.ReadFull(rand.Reader, secret[:])
114 KeyGen(&got, &secret)
115 Shared(&want, &secret, &gen)
116 if got != want {
117 test.ReportError(t, got, want, secret)
118 }
119 }
120 }
121
122 func BenchmarkX448(b *testing.B) {
123 var x, y, z Key
124 _, _ = io.ReadFull(rand.Reader, x[:])
125 _, _ = io.ReadFull(rand.Reader, y[:])
126 _, _ = io.ReadFull(rand.Reader, z[:])
127
128 b.Run("KeyGen", func(b *testing.B) {
129 for i := 0; i < b.N; i++ {
130 KeyGen(&x, &y)
131 }
132 })
133 b.Run("Shared", func(b *testing.B) {
134 for i := 0; i < b.N; i++ {
135 Shared(&z, &x, &y)
136 }
137 })
138 }
139
140 func Example_x448() {
141 var AliceSecret, BobSecret,
142 AlicePublic, BobPublic,
143 AliceShared, BobShared Key
144
145
146 _, _ = io.ReadFull(rand.Reader, AliceSecret[:])
147 KeyGen(&AlicePublic, &AliceSecret)
148
149
150 _, _ = io.ReadFull(rand.Reader, BobSecret[:])
151 KeyGen(&BobPublic, &BobSecret)
152
153
154 okA := Shared(&AliceShared, &AliceSecret, &BobPublic)
155
156
157 okB := Shared(&BobShared, &BobSecret, &AlicePublic)
158
159 fmt.Println(AliceShared == BobShared && okA && okB)
160
161 }
162
View as plain text