1
2
3
4
5 package ed25519
6
7 import (
8 "bufio"
9 "bytes"
10 "compress/gzip"
11 "crypto"
12 "crypto/internal/cryptotest"
13 "crypto/rand"
14 "crypto/sha512"
15 "encoding/hex"
16 "log"
17 "os"
18 "strings"
19 "testing"
20 )
21
22 func Example_ed25519ctx() {
23 pub, priv, err := GenerateKey(nil)
24 if err != nil {
25 log.Fatal(err)
26 }
27
28 msg := []byte("The quick brown fox jumps over the lazy dog")
29
30 sig, err := priv.Sign(nil, msg, &Options{
31 Context: "Example_ed25519ctx",
32 })
33 if err != nil {
34 log.Fatal(err)
35 }
36
37 if err := VerifyWithOptions(pub, msg, sig, &Options{
38 Context: "Example_ed25519ctx",
39 }); err != nil {
40 log.Fatal("invalid signature")
41 }
42 }
43
44 func TestGenerateKey(t *testing.T) {
45
46 public, private, err := GenerateKey(nil)
47 if err != nil {
48 t.Fatal(err)
49 }
50
51 if len(public) != PublicKeySize {
52 t.Errorf("public key has the wrong size: %d", len(public))
53 }
54 if len(private) != PrivateKeySize {
55 t.Errorf("private key has the wrong size: %d", len(private))
56 }
57 if !bytes.Equal(private.Public().(PublicKey), public) {
58 t.Errorf("public key doesn't match private key")
59 }
60 fromSeed := NewKeyFromSeed(private.Seed())
61 if !bytes.Equal(private, fromSeed) {
62 t.Errorf("recreating key pair from seed gave different private key")
63 }
64
65 _, k2, err := GenerateKey(nil)
66 if err != nil {
67 t.Fatal(err)
68 }
69 if bytes.Equal(private, k2) {
70 t.Errorf("GenerateKey returned the same private key twice")
71 }
72
73 _, k3, err := GenerateKey(rand.Reader)
74 if err != nil {
75 t.Fatal(err)
76 }
77 if bytes.Equal(private, k3) {
78 t.Errorf("GenerateKey returned the same private key twice")
79 }
80
81
82 seed := make([]byte, SeedSize)
83 rand.Read(seed)
84 _, k4, err := GenerateKey(bytes.NewReader(seed))
85 if err != nil {
86 t.Fatal(err)
87 }
88 k4n := NewKeyFromSeed(seed)
89 if !bytes.Equal(k4, k4n) {
90 t.Errorf("GenerateKey with seed gave different private key")
91 }
92 }
93
94 type zeroReader struct{}
95
96 func (zeroReader) Read(buf []byte) (int, error) {
97 clear(buf)
98 return len(buf), nil
99 }
100
101 func TestSignVerify(t *testing.T) {
102 var zero zeroReader
103 public, private, _ := GenerateKey(zero)
104
105 message := []byte("test message")
106 sig := Sign(private, message)
107 if !Verify(public, message, sig) {
108 t.Errorf("valid signature rejected")
109 }
110
111 wrongMessage := []byte("wrong message")
112 if Verify(public, wrongMessage, sig) {
113 t.Errorf("signature of different message accepted")
114 }
115 }
116
117 func TestSignVerifyHashed(t *testing.T) {
118
119 key, _ := hex.DecodeString("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf")
120 expectedSig, _ := hex.DecodeString("98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406")
121 message, _ := hex.DecodeString("616263")
122
123 private := PrivateKey(key)
124 public := private.Public().(PublicKey)
125 hash := sha512.Sum512(message)
126 sig, err := private.Sign(nil, hash[:], crypto.SHA512)
127 if err != nil {
128 t.Fatal(err)
129 }
130 if !bytes.Equal(sig, expectedSig) {
131 t.Error("signature doesn't match test vector")
132 }
133 sig, err = private.Sign(nil, hash[:], &Options{Hash: crypto.SHA512})
134 if err != nil {
135 t.Fatal(err)
136 }
137 if !bytes.Equal(sig, expectedSig) {
138 t.Error("signature doesn't match test vector")
139 }
140 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512}); err != nil {
141 t.Errorf("valid signature rejected: %v", err)
142 }
143
144 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA256}); err == nil {
145 t.Errorf("expected error for wrong hash")
146 }
147
148 wrongHash := sha512.Sum512([]byte("wrong message"))
149 if VerifyWithOptions(public, wrongHash[:], sig, &Options{Hash: crypto.SHA512}) == nil {
150 t.Errorf("signature of different message accepted")
151 }
152
153 sig[0] ^= 0xff
154 if VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512}) == nil {
155 t.Errorf("invalid signature accepted")
156 }
157 sig[0] ^= 0xff
158 sig[SignatureSize-1] ^= 0xff
159 if VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512}) == nil {
160 t.Errorf("invalid signature accepted")
161 }
162
163
164
165 sig, err = private.Sign(nil, hash[:], &Options{Hash: crypto.SHA512, Context: "123"})
166 if err != nil {
167 t.Fatal(err)
168 }
169 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512, Context: "123"}); err != nil {
170 t.Errorf("valid signature rejected: %v", err)
171 }
172 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512, Context: "321"}); err == nil {
173 t.Errorf("expected error for wrong context")
174 }
175 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA256, Context: "123"}); err == nil {
176 t.Errorf("expected error for wrong hash")
177 }
178 }
179
180 func TestSignVerifyContext(t *testing.T) {
181
182 key, _ := hex.DecodeString("0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292")
183 expectedSig, _ := hex.DecodeString("55a4cc2f70a54e04288c5f4cd1e45a7bb520b36292911876cada7323198dd87a8b36950b95130022907a7fb7c4e9b2d5f6cca685a587b4b21f4b888e4e7edb0d")
184 message, _ := hex.DecodeString("f726936d19c800494e3fdaff20b276a8")
185 context := "foo"
186
187 private := PrivateKey(key)
188 public := private.Public().(PublicKey)
189 sig, err := private.Sign(nil, message, &Options{Context: context})
190 if err != nil {
191 t.Fatal(err)
192 }
193 if !bytes.Equal(sig, expectedSig) {
194 t.Error("signature doesn't match test vector")
195 }
196 if err := VerifyWithOptions(public, message, sig, &Options{Context: context}); err != nil {
197 t.Errorf("valid signature rejected: %v", err)
198 }
199
200 if VerifyWithOptions(public, []byte("bar"), sig, &Options{Context: context}) == nil {
201 t.Errorf("signature of different message accepted")
202 }
203 if VerifyWithOptions(public, message, sig, &Options{Context: "bar"}) == nil {
204 t.Errorf("signature with different context accepted")
205 }
206
207 sig[0] ^= 0xff
208 if VerifyWithOptions(public, message, sig, &Options{Context: context}) == nil {
209 t.Errorf("invalid signature accepted")
210 }
211 sig[0] ^= 0xff
212 sig[SignatureSize-1] ^= 0xff
213 if VerifyWithOptions(public, message, sig, &Options{Context: context}) == nil {
214 t.Errorf("invalid signature accepted")
215 }
216 }
217
218 func TestCryptoSigner(t *testing.T) {
219 var zero zeroReader
220 public, private, _ := GenerateKey(zero)
221
222 signer := crypto.Signer(private)
223
224 publicInterface := signer.Public()
225 public2, ok := publicInterface.(PublicKey)
226 if !ok {
227 t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
228 }
229
230 if !bytes.Equal(public, public2) {
231 t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
232 }
233
234 message := []byte("message")
235 var noHash crypto.Hash
236 signature, err := signer.Sign(zero, message, noHash)
237 if err != nil {
238 t.Fatalf("error from Sign(): %s", err)
239 }
240
241 signature2, err := signer.Sign(zero, message, &Options{Hash: noHash})
242 if err != nil {
243 t.Fatalf("error from Sign(): %s", err)
244 }
245 if !bytes.Equal(signature, signature2) {
246 t.Errorf("signatures keys do not match")
247 }
248
249 if !Verify(public, message, signature) {
250 t.Errorf("Verify failed on signature from Sign()")
251 }
252 }
253
254 func TestEqual(t *testing.T) {
255 public, private, _ := GenerateKey(rand.Reader)
256
257 if !public.Equal(public) {
258 t.Errorf("public key is not equal to itself: %q", public)
259 }
260 if !public.Equal(crypto.Signer(private).Public()) {
261 t.Errorf("private.Public() is not Equal to public: %q", public)
262 }
263 if !private.Equal(private) {
264 t.Errorf("private key is not equal to itself: %q", private)
265 }
266
267 otherPub, otherPriv, _ := GenerateKey(rand.Reader)
268 if public.Equal(otherPub) {
269 t.Errorf("different public keys are Equal")
270 }
271 if private.Equal(otherPriv) {
272 t.Errorf("different private keys are Equal")
273 }
274 }
275
276 func TestGolden(t *testing.T) {
277
278
279 testDataZ, err := os.Open("testdata/sign.input.gz")
280 if err != nil {
281 t.Fatal(err)
282 }
283 defer testDataZ.Close()
284 testData, err := gzip.NewReader(testDataZ)
285 if err != nil {
286 t.Fatal(err)
287 }
288 defer testData.Close()
289
290 scanner := bufio.NewScanner(testData)
291 lineNo := 0
292
293 for scanner.Scan() {
294 lineNo++
295
296 line := scanner.Text()
297 parts := strings.Split(line, ":")
298 if len(parts) != 5 {
299 t.Fatalf("bad number of parts on line %d", lineNo)
300 }
301
302 privBytes, _ := hex.DecodeString(parts[0])
303 pubKey, _ := hex.DecodeString(parts[1])
304 msg, _ := hex.DecodeString(parts[2])
305 sig, _ := hex.DecodeString(parts[3])
306
307
308 sig = sig[:SignatureSize]
309
310 if l := len(pubKey); l != PublicKeySize {
311 t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
312 }
313
314 var priv [PrivateKeySize]byte
315 copy(priv[:], privBytes)
316 copy(priv[32:], pubKey)
317
318 sig2 := Sign(priv[:], msg)
319 if !bytes.Equal(sig, sig2[:]) {
320 t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
321 }
322
323 if !Verify(pubKey, msg, sig2) {
324 t.Errorf("signature failed to verify on line %d", lineNo)
325 }
326
327 priv2 := NewKeyFromSeed(priv[:32])
328 if !bytes.Equal(priv[:], priv2) {
329 t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2)
330 }
331
332 if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) {
333 t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2)
334 }
335
336 if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) {
337 t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed)
338 }
339 }
340
341 if err := scanner.Err(); err != nil {
342 t.Fatalf("error reading test data: %s", err)
343 }
344 }
345
346 func TestMalleability(t *testing.T) {
347
348
349
350 msg := []byte{0x54, 0x65, 0x73, 0x74}
351 sig := []byte{
352 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
353 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
354 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
355 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
356 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
357 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
358 }
359 publicKey := []byte{
360 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
361 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
362 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
363 }
364
365 if Verify(publicKey, msg, sig) {
366 t.Fatal("non-canonical signature accepted")
367 }
368 }
369
370 func TestAllocations(t *testing.T) {
371 cryptotest.SkipTestAllocations(t)
372 if allocs := testing.AllocsPerRun(100, func() {
373 seed := make([]byte, SeedSize)
374 message := []byte("Hello, world!")
375 priv := NewKeyFromSeed(seed)
376 pub := priv.Public().(PublicKey)
377 signature := Sign(priv, message)
378 if !Verify(pub, message, signature) {
379 t.Fatal("signature didn't verify")
380 }
381 }); allocs > 0 {
382 t.Errorf("expected zero allocations, got %0.1f", allocs)
383 }
384 }
385
386 func BenchmarkKeyGeneration(b *testing.B) {
387 var zero zeroReader
388 for i := 0; i < b.N; i++ {
389 if _, _, err := GenerateKey(zero); err != nil {
390 b.Fatal(err)
391 }
392 }
393 }
394
395 func BenchmarkNewKeyFromSeed(b *testing.B) {
396 seed := make([]byte, SeedSize)
397 for i := 0; i < b.N; i++ {
398 _ = NewKeyFromSeed(seed)
399 }
400 }
401
402 func BenchmarkSigning(b *testing.B) {
403 var zero zeroReader
404 _, priv, err := GenerateKey(zero)
405 if err != nil {
406 b.Fatal(err)
407 }
408 message := []byte("Hello, world!")
409 b.ResetTimer()
410 for i := 0; i < b.N; i++ {
411 Sign(priv, message)
412 }
413 }
414
415 func BenchmarkVerification(b *testing.B) {
416 var zero zeroReader
417 pub, priv, err := GenerateKey(zero)
418 if err != nil {
419 b.Fatal(err)
420 }
421 message := []byte("Hello, world!")
422 signature := Sign(priv, message)
423 b.ResetTimer()
424 for i := 0; i < b.N; i++ {
425 Verify(pub, message, signature)
426 }
427 }
428
View as plain text