1 package ed25519_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/ed25519"
13 )
14
15 func TestWrongPublicKey(t *testing.T) {
16 wrongPublicKeys := [...][ed25519.PublicKeySize]byte{
17 {
18 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
19 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
20 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
21 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
22 },
23 {
24 0xed + 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
28 },
29 {
30 0x9a, 0x0a, 0xbe, 0xc6, 0x23, 0xcb, 0x5a, 0x23,
31 0x4e, 0x49, 0xd8, 0x92, 0xc2, 0x72, 0xd5, 0xa8,
32 0x27, 0xff, 0x42, 0x07, 0x7d, 0xe3, 0xf2, 0xb4,
33 0x74, 0x75, 0x9d, 0x04, 0x34, 0xed, 0xa6, 0x70,
34 },
35 {
36 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 0x80,
40 },
41 {
42 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f | 0x80,
46 },
47 }
48 sig := (&[ed25519.SignatureSize]byte{})[:]
49 for _, public := range wrongPublicKeys {
50 got := ed25519.Verify(public[:], []byte(""), sig)
51 want := false
52 if got != want {
53 test.ReportError(t, got, want, public)
54 }
55 }
56 }
57
58 func TestSigner(t *testing.T) {
59 seed := (&[ed25519.SeedSize]byte{})[:]
60 _, _ = rand.Read(seed)
61 key := ed25519.NewKeyFromSeed(seed)
62
63 priv := key.Seed()
64 if !bytes.Equal(seed, priv) {
65 got := priv
66 want := seed
67 test.ReportError(t, got, want)
68 }
69
70 for _, o := range []ed25519.SignerOptions{
71 {Scheme: ed25519.ED25519, Hash: crypto.Hash(0), Context: ""},
72 {Scheme: ed25519.ED25519Ph, Hash: crypto.SHA512, Context: ""},
73 {Scheme: ed25519.ED25519Ph, Hash: crypto.SHA512, Context: "non-empty"},
74 {Scheme: ed25519.ED25519Ctx, Hash: crypto.Hash(0), Context: "non-empty"},
75 } {
76 testSigner(t, key, o)
77 }
78 }
79
80 func testSigner(t *testing.T, signer crypto.Signer, ops ed25519.SignerOptions) {
81 msg := make([]byte, 64)
82 _, _ = rand.Read(msg)
83
84 sig, err := signer.Sign(nil, msg, ops)
85 if err != nil {
86 got := err
87 var want error
88 test.ReportError(t, got, want, ops)
89 }
90
91 if len(sig) != ed25519.SignatureSize {
92 got := len(sig)
93 want := ed25519.SignatureSize
94 test.ReportError(t, got, want, ops)
95 }
96
97 pubSigner, ok := signer.Public().(ed25519.PublicKey)
98 if !ok {
99 got := ok
100 want := true
101 test.ReportError(t, got, want, ops)
102 }
103
104 got := ed25519.VerifyAny(pubSigner, msg, sig, ops)
105 want := true
106 if got != want {
107 test.ReportError(t, got, want, ops)
108 }
109 }
110
111 type badReader struct{}
112
113 func (badReader) Read([]byte) (int, error) { return 0, errors.New("cannot read") }
114
115 func TestErrors(t *testing.T) {
116 t.Run("badHash", func(t *testing.T) {
117 var msg [16]byte
118 ops := crypto.SHA224
119 _, priv, _ := ed25519.GenerateKey(nil)
120 _, got := priv.Sign(nil, msg[:], ops)
121 want := errors.New("ed25519: bad hash algorithm")
122 if got.Error() != want.Error() {
123 test.ReportError(t, got, want)
124 }
125 })
126 t.Run("badReader", func(t *testing.T) {
127 _, _, got := ed25519.GenerateKey(badReader{})
128 want := errors.New("cannot read")
129 if got.Error() != want.Error() {
130 test.ReportError(t, got, want)
131 }
132 })
133 t.Run("wrongSeedSize", func(t *testing.T) {
134 var seed [256]byte
135 var want error
136 got := test.CheckPanic(func() { ed25519.NewKeyFromSeed(seed[:]) })
137 if got != want {
138 test.ReportError(t, got, want)
139 }
140 })
141 }
142
143 func BenchmarkEd25519Ph(b *testing.B) {
144 msg := make([]byte, 128)
145 _, _ = rand.Read(msg)
146
147 b.Run("Sign", func(b *testing.B) {
148 _, key, _ := ed25519.GenerateKey(rand.Reader)
149 ctx := ""
150 b.ResetTimer()
151 for i := 0; i < b.N; i++ {
152 _ = ed25519.SignPh(key, msg, ctx)
153 }
154 })
155 b.Run("Verify", func(b *testing.B) {
156 pub, priv, _ := ed25519.GenerateKey(rand.Reader)
157 ctx := ""
158 sig := ed25519.SignPh(priv, msg, ctx)
159 b.ResetTimer()
160 for i := 0; i < b.N; i++ {
161 ed25519.VerifyPh(pub, msg, sig, ctx)
162 }
163 })
164 }
165
166 func BenchmarkEd25519Ctx(b *testing.B) {
167 ctx := "a context"
168 msg := make([]byte, 128)
169 _, _ = rand.Read(msg)
170 b.Run("Sign", func(b *testing.B) {
171 _, priv, _ := ed25519.GenerateKey(rand.Reader)
172 b.ResetTimer()
173 for i := 0; i < b.N; i++ {
174 _ = ed25519.SignWithCtx(priv, msg, ctx)
175 }
176 })
177 b.Run("Verify", func(b *testing.B) {
178 pub, priv, _ := ed25519.GenerateKey(rand.Reader)
179 sig := ed25519.SignWithCtx(priv, msg, ctx)
180 b.ResetTimer()
181 for i := 0; i < b.N; i++ {
182 ed25519.VerifyWithCtx(pub, msg, sig, ctx)
183 }
184 })
185 }
186
187 func Example_ed25519() {
188
189
190
191
192 pub, priv, err := ed25519.GenerateKey(rand.Reader)
193 if err != nil {
194 panic("error on generating keys")
195 }
196
197
198 message := []byte("A message to be signed")
199 signature := ed25519.Sign(priv, message)
200
201
202 ok := ed25519.Verify(pub, message, signature)
203 fmt.Println(ok)
204
205 }
206
207 func ExampleSignPh() {
208
209
210
211
212 pub, priv, err := ed25519.GenerateKey(rand.Reader)
213 if err != nil {
214 panic("error on generating keys")
215 }
216
217
218 message := []byte("A message to be signed")
219 ctx := "an optional context string"
220
221 signature := ed25519.SignPh(priv, message, ctx)
222
223
224 ok := ed25519.VerifyPh(pub, message, signature, ctx)
225 fmt.Println(ok)
226
227 }
228
229 func ExampleSignWithCtx() {
230
231
232
233
234 pub, priv, err := ed25519.GenerateKey(rand.Reader)
235 if err != nil {
236 panic("error on generating keys")
237 }
238
239
240 message := []byte("A message to be signed")
241 ctx := "a non-empty context string"
242
243 signature := ed25519.SignWithCtx(priv, message, ctx)
244
245
246 ok := ed25519.VerifyWithCtx(pub, message, signature, ctx)
247 fmt.Println(ok)
248
249 }
250
View as plain text