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