1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ed25519
6
7import (
8	"bufio"
9	"bytes"
10	"compress/gzip"
11	"crypto"
12	"crypto/ed25519/internal/edwards25519"
13	"crypto/rand"
14	"encoding/hex"
15	"os"
16	"strings"
17	"testing"
18)
19
20type zeroReader struct{}
21
22func (zeroReader) Read(buf []byte) (int, error) {
23	for i := range buf {
24		buf[i] = 0
25	}
26	return len(buf), nil
27}
28
29func TestUnmarshalMarshal(t *testing.T) {
30	pub, _, _ := GenerateKey(rand.Reader)
31
32	var A edwards25519.ExtendedGroupElement
33	var pubBytes [32]byte
34	copy(pubBytes[:], pub)
35	if !A.FromBytes(&pubBytes) {
36		t.Fatalf("ExtendedGroupElement.FromBytes failed")
37	}
38
39	var pub2 [32]byte
40	A.ToBytes(&pub2)
41
42	if pubBytes != pub2 {
43		t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
44	}
45}
46
47func TestSignVerify(t *testing.T) {
48	var zero zeroReader
49	public, private, _ := GenerateKey(zero)
50
51	message := []byte("test message")
52	sig := Sign(private, message)
53	if !Verify(public, message, sig) {
54		t.Errorf("valid signature rejected")
55	}
56
57	wrongMessage := []byte("wrong message")
58	if Verify(public, wrongMessage, sig) {
59		t.Errorf("signature of different message accepted")
60	}
61}
62
63func TestCryptoSigner(t *testing.T) {
64	var zero zeroReader
65	public, private, _ := GenerateKey(zero)
66
67	signer := crypto.Signer(private)
68
69	publicInterface := signer.Public()
70	public2, ok := publicInterface.(PublicKey)
71	if !ok {
72		t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
73	}
74
75	if !bytes.Equal(public, public2) {
76		t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
77	}
78
79	message := []byte("message")
80	var noHash crypto.Hash
81	signature, err := signer.Sign(zero, message, noHash)
82	if err != nil {
83		t.Fatalf("error from Sign(): %s", err)
84	}
85
86	if !Verify(public, message, signature) {
87		t.Errorf("Verify failed on signature from Sign()")
88	}
89}
90
91func TestEqual(t *testing.T) {
92	public, private, _ := GenerateKey(rand.Reader)
93
94	if !public.Equal(public) {
95		t.Errorf("public key is not equal to itself: %q", public)
96	}
97	if !public.Equal(crypto.Signer(private).Public()) {
98		t.Errorf("private.Public() is not Equal to public: %q", public)
99	}
100	if !private.Equal(private) {
101		t.Errorf("private key is not equal to itself: %q", private)
102	}
103
104	otherPub, otherPriv, _ := GenerateKey(rand.Reader)
105	if public.Equal(otherPub) {
106		t.Errorf("different public keys are Equal")
107	}
108	if private.Equal(otherPriv) {
109		t.Errorf("different private keys are Equal")
110	}
111}
112
113func TestGolden(t *testing.T) {
114	// sign.input.gz is a selection of test cases from
115	// https://ed25519.cr.yp.to/python/sign.input
116	testDataZ, err := os.Open("testdata/sign.input.gz")
117	if err != nil {
118		t.Fatal(err)
119	}
120	defer testDataZ.Close()
121	testData, err := gzip.NewReader(testDataZ)
122	if err != nil {
123		t.Fatal(err)
124	}
125	defer testData.Close()
126
127	scanner := bufio.NewScanner(testData)
128	lineNo := 0
129
130	for scanner.Scan() {
131		lineNo++
132
133		line := scanner.Text()
134		parts := strings.Split(line, ":")
135		if len(parts) != 5 {
136			t.Fatalf("bad number of parts on line %d", lineNo)
137		}
138
139		privBytes, _ := hex.DecodeString(parts[0])
140		pubKey, _ := hex.DecodeString(parts[1])
141		msg, _ := hex.DecodeString(parts[2])
142		sig, _ := hex.DecodeString(parts[3])
143		// The signatures in the test vectors also include the message
144		// at the end, but we just want R and S.
145		sig = sig[:SignatureSize]
146
147		if l := len(pubKey); l != PublicKeySize {
148			t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
149		}
150
151		var priv [PrivateKeySize]byte
152		copy(priv[:], privBytes)
153		copy(priv[32:], pubKey)
154
155		sig2 := Sign(priv[:], msg)
156		if !bytes.Equal(sig, sig2[:]) {
157			t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
158		}
159
160		if !Verify(pubKey, msg, sig2) {
161			t.Errorf("signature failed to verify on line %d", lineNo)
162		}
163
164		priv2 := NewKeyFromSeed(priv[:32])
165		if !bytes.Equal(priv[:], priv2) {
166			t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2)
167		}
168
169		if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) {
170			t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2)
171		}
172
173		if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) {
174			t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed)
175		}
176	}
177
178	if err := scanner.Err(); err != nil {
179		t.Fatalf("error reading test data: %s", err)
180	}
181}
182
183func TestMalleability(t *testing.T) {
184	// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
185	// that s be in [0, order). This prevents someone from adding a multiple of
186	// order to s and obtaining a second valid signature for the same message.
187	msg := []byte{0x54, 0x65, 0x73, 0x74}
188	sig := []byte{
189		0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
190		0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
191		0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
192		0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
193		0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
194		0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
195	}
196	publicKey := []byte{
197		0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
198		0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
199		0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
200	}
201
202	if Verify(publicKey, msg, sig) {
203		t.Fatal("non-canonical signature accepted")
204	}
205}
206
207func BenchmarkKeyGeneration(b *testing.B) {
208	var zero zeroReader
209	for i := 0; i < b.N; i++ {
210		if _, _, err := GenerateKey(zero); err != nil {
211			b.Fatal(err)
212		}
213	}
214}
215
216func BenchmarkNewKeyFromSeed(b *testing.B) {
217	seed := make([]byte, SeedSize)
218	b.ReportAllocs()
219	for i := 0; i < b.N; i++ {
220		_ = NewKeyFromSeed(seed)
221	}
222}
223
224func BenchmarkSigning(b *testing.B) {
225	var zero zeroReader
226	_, priv, err := GenerateKey(zero)
227	if err != nil {
228		b.Fatal(err)
229	}
230	message := []byte("Hello, world!")
231	b.ReportAllocs()
232	b.ResetTimer()
233	for i := 0; i < b.N; i++ {
234		Sign(priv, message)
235	}
236}
237
238func BenchmarkVerification(b *testing.B) {
239	var zero zeroReader
240	pub, priv, err := GenerateKey(zero)
241	if err != nil {
242		b.Fatal(err)
243	}
244	message := []byte("Hello, world!")
245	signature := Sign(priv, message)
246	b.ResetTimer()
247	for i := 0; i < b.N; i++ {
248		Verify(pub, message, signature)
249	}
250}
251