1 package ed448_test
2
3 import (
4 "bytes"
5 "crypto"
6 "crypto/rand"
7 "errors"
8 "fmt"
9 "testing"
10
11 "github.com/cloudflare/circl/internal/test"
12 "github.com/cloudflare/circl/sign/ed448"
13 )
14
15 type zeroReader struct{}
16
17 func (zeroReader) Read(buf []byte) (int, error) {
18 for i := range buf {
19 buf[i] = 0
20 }
21 return len(buf), nil
22 }
23
24 func TestEqual(t *testing.T) {
25 public, private, _ := ed448.GenerateKey(rand.Reader)
26
27 if !public.Equal(public) {
28 t.Errorf("public key is not equal to itself: %q", public)
29 }
30 if !public.Equal(crypto.Signer(private).Public()) {
31 t.Errorf("private.Public() is not Equal to public: %q", public)
32 }
33 if !private.Equal(private) {
34 t.Errorf("private key is not equal to itself: %q", private)
35 }
36
37 otherPub, otherPriv, _ := ed448.GenerateKey(rand.Reader)
38 if public.Equal(otherPub) {
39 t.Errorf("different public keys are Equal")
40 }
41 if private.Equal(otherPriv) {
42 t.Errorf("different private keys are Equal")
43 }
44 }
45
46 func TestWrongPublicKey(t *testing.T) {
47 wrongPublicKeys := [...][ed448.PublicKeySize]byte{
48 {
49 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
52 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
56 },
57 {
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
62 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65 },
66 {
67 0xa4, 0x8b, 0xae, 0x31, 0x1b, 0x3a, 0xe5, 0x62,
68 0x3d, 0x6f, 0x2d, 0xbe, 0x8b, 0xb4, 0xd3, 0x21,
69 0x0f, 0x04, 0x0a, 0x7e, 0xf2, 0x25, 0x87, 0xc3,
70 0xc0, 0x1e, 0xe1, 0xf4, 0x6d, 0xc7, 0x28, 0x8f,
71 0x8b, 0xb9, 0x9f, 0x3d, 0x02, 0xb0, 0xc0, 0xa8,
72 0xe7, 0xe3, 0x4f, 0xb2, 0x82, 0x64, 0x98, 0x4a,
73 0x84, 0x73, 0xd7, 0x57, 0x6a, 0x39, 0x90, 0xa3,
74 },
75 {
76 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
83 },
84 {
85 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
87 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
88 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
89 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
90 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
91 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
92 },
93 }
94 sig := (&[ed448.SignatureSize]byte{})[:]
95 for _, public := range wrongPublicKeys {
96 got := ed448.Verify(public[:], []byte(""), sig, "")
97 want := false
98 if got != want {
99 test.ReportError(t, got, want, public)
100 }
101 }
102 }
103
104 func TestSigner(t *testing.T) {
105 seed := (&[ed448.SeedSize]byte{})[:]
106 _, _ = rand.Read(seed)
107 key := ed448.NewKeyFromSeed(seed)
108
109 priv := key.Seed()
110 if !bytes.Equal(seed, priv) {
111 got := priv
112 want := seed
113 test.ReportError(t, got, want)
114 }
115
116 signer := crypto.Signer(key)
117 ops := crypto.Hash(0)
118 msg := make([]byte, 16)
119 _, _ = rand.Read(msg)
120 sig, err := signer.Sign(nil, msg, ops)
121 if err != nil {
122 got := err
123 var want error
124 test.ReportError(t, got, want)
125 }
126 if len(sig) != ed448.SignatureSize {
127 got := len(sig)
128 want := ed448.SignatureSize
129 test.ReportError(t, got, want)
130 }
131
132 for _, o := range []ed448.SignerOptions{
133 {Scheme: ed448.ED448, Hash: crypto.Hash(0), Context: ""},
134 {Scheme: ed448.ED448, Hash: crypto.Hash(0), Context: "non-empty"},
135 {Scheme: ed448.ED448Ph, Hash: crypto.Hash(0), Context: ""},
136 {Scheme: ed448.ED448Ph, Hash: crypto.Hash(0), Context: "non-empty"},
137 } {
138 testSigner(t, key, o)
139 }
140 }
141
142 func testSigner(t *testing.T, signer crypto.Signer, ops ed448.SignerOptions) {
143 msg := make([]byte, 64)
144 _, _ = rand.Read(msg)
145
146 sig, err := signer.Sign(nil, msg, ops)
147 if err != nil {
148 got := err
149 var want error
150 test.ReportError(t, got, want, ops)
151 }
152
153 if len(sig) != ed448.SignatureSize {
154 got := len(sig)
155 want := ed448.SignatureSize
156 test.ReportError(t, got, want, ops)
157 }
158
159 pubSigner, ok := signer.Public().(ed448.PublicKey)
160 if !ok {
161 got := ok
162 want := true
163 test.ReportError(t, got, want, ops)
164 }
165
166 got := ed448.VerifyAny(pubSigner, msg, sig, ops)
167 want := true
168 if got != want {
169 test.ReportError(t, got, want, ops)
170 }
171 }
172
173 type badReader struct{}
174
175 func (badReader) Read([]byte) (n int, err error) { return 0, errors.New("cannot read") }
176
177 func TestErrors(t *testing.T) {
178 t.Run("badHash", func(t *testing.T) {
179 var msg [16]byte
180 ops := crypto.SHA224
181 _, priv, _ := ed448.GenerateKey(nil)
182 _, got := priv.Sign(nil, msg[:], ops)
183 want := errors.New("ed448: bad hash algorithm")
184 if got.Error() != want.Error() {
185 test.ReportError(t, got, want)
186 }
187 })
188 t.Run("badReader", func(t *testing.T) {
189 _, _, got := ed448.GenerateKey(badReader{})
190 want := errors.New("cannot read")
191 if got.Error() != want.Error() {
192 test.ReportError(t, got, want)
193 }
194 })
195 t.Run("wrongSeedSize", func(t *testing.T) {
196 var seed [256]byte
197 var want error
198 got := test.CheckPanic(func() { ed448.NewKeyFromSeed(seed[:]) })
199 if got != want {
200 test.ReportError(t, got, want)
201 }
202 })
203 t.Run("bigContext", func(t *testing.T) {
204 var msg [16]byte
205 var ctx [256]byte
206 var want error
207 _, priv, _ := ed448.GenerateKey(nil)
208 got := test.CheckPanic(func() { ed448.Sign(priv, msg[:], string(ctx[:])) })
209 if got != want {
210 test.ReportError(t, got, want)
211 }
212 })
213 }
214
215 func BenchmarkKeyGeneration(b *testing.B) {
216 var zero zeroReader
217 for i := 0; i < b.N; i++ {
218 if _, _, err := ed448.GenerateKey(zero); err != nil {
219 b.Fatal(err)
220 }
221 }
222 }
223
224 func BenchmarkNewKeyFromSeed(b *testing.B) {
225 seed := make([]byte, ed448.SeedSize)
226 b.ReportAllocs()
227 for i := 0; i < b.N; i++ {
228 _ = ed448.NewKeyFromSeed(seed)
229 }
230 }
231
232 func BenchmarkSigning(b *testing.B) {
233 var zero zeroReader
234 _, priv, err := ed448.GenerateKey(zero)
235 if err != nil {
236 b.Fatal(err)
237 }
238 message := []byte("Hello, world!")
239 ctx := "a context string"
240 b.ReportAllocs()
241 b.ResetTimer()
242 for i := 0; i < b.N; i++ {
243 ed448.Sign(priv, message, ctx)
244 }
245 }
246
247 func BenchmarkVerification(b *testing.B) {
248 var zero zeroReader
249 pub, priv, err := ed448.GenerateKey(zero)
250 if err != nil {
251 b.Fatal(err)
252 }
253 message := []byte("Hello, world!")
254 ctx := "a context string"
255 signature := ed448.Sign(priv, message, ctx)
256 b.ResetTimer()
257 for i := 0; i < b.N; i++ {
258 ed448.Verify(pub, message, signature, ctx)
259 }
260 }
261
262 func BenchmarkEd448Ph(b *testing.B) {
263 msg := make([]byte, 128)
264 _, _ = rand.Read(msg)
265
266 b.Run("Sign", func(b *testing.B) {
267 _, key, _ := ed448.GenerateKey(rand.Reader)
268 ctx := ""
269 b.ResetTimer()
270 for i := 0; i < b.N; i++ {
271 _ = ed448.SignPh(key, msg, ctx)
272 }
273 })
274 b.Run("Verify", func(b *testing.B) {
275 pub, priv, _ := ed448.GenerateKey(rand.Reader)
276 ctx := ""
277 sig := ed448.SignPh(priv, msg, ctx)
278 b.ResetTimer()
279 for i := 0; i < b.N; i++ {
280 ed448.VerifyPh(pub, msg, sig, ctx)
281 }
282 })
283 }
284
285 func Example_ed448() {
286
287
288
289
290 pub, priv, err := ed448.GenerateKey(rand.Reader)
291 if err != nil {
292 panic("error on generating keys")
293 }
294
295
296 message := []byte("A message to be signed")
297 ctx := "This is a context string"
298 signature := ed448.Sign(priv, message, ctx)
299
300
301 ok := ed448.Verify(pub, message, signature, ctx)
302 fmt.Println(ok)
303
304 }
305
306 func ExampleSignPh() {
307
308
309
310
311 pub, priv, err := ed448.GenerateKey(rand.Reader)
312 if err != nil {
313 panic("error on generating keys")
314 }
315
316
317 message := []byte("A message to be signed")
318 ctx := "This is a context string"
319 signature := ed448.SignPh(priv, message, ctx)
320
321
322 ok := ed448.VerifyPh(pub, message, signature, ctx)
323 fmt.Println(ok)
324
325 }
326
View as plain text