1
2
3
4
5 package note
6
7 import (
8 "crypto/ed25519"
9 "crypto/rand"
10 "errors"
11 "strings"
12 "testing"
13 "testing/iotest"
14 )
15
16 func TestNewVerifier(t *testing.T) {
17 vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
18 _, err := NewVerifier(vkey)
19 if err != nil {
20 t.Fatal(err)
21 }
22
23
24 badKey := func(k string) {
25 _, err := NewVerifier(k)
26 if err == nil {
27 t.Errorf("NewVerifier(%q) succeeded, should have failed", k)
28 }
29 }
30
31 b := []byte(vkey)
32 for i := 0; i <= len(b); i++ {
33 for j := i + 1; j <= len(b); j++ {
34 if i != 0 || j != len(b) {
35 badKey(string(b[i:j]))
36 }
37 }
38 }
39 for i := 0; i < len(b); i++ {
40 b[i]++
41 badKey(string(b))
42 b[i]--
43 }
44
45 badKey("PeterNeumann+cc469956+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TWBADKEY==")
46 badKey("PeterNeumann+173116ae+ZRpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW")
47 }
48
49 func TestNewSigner(t *testing.T) {
50 skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
51 _, err := NewSigner(skey)
52 if err != nil {
53 t.Fatal(err)
54 }
55
56
57 b := []byte(skey)
58 for i := 0; i <= len(b); i++ {
59 for j := i + 1; j <= len(b); j++ {
60 if i == 0 && j == len(b) {
61 continue
62 }
63 _, err := NewSigner(string(b[i:j]))
64 if err == nil {
65 t.Errorf("NewSigner(%q) succeeded, should have failed", b[i:j])
66 }
67 }
68 }
69 for i := 0; i < len(b); i++ {
70 b[i]++
71 _, err := NewSigner(string(b))
72 if err == nil {
73 t.Errorf("NewSigner(%q) succeeded, should have failed", b)
74 }
75 b[i]--
76 }
77 }
78
79 func testSignerAndVerifier(t *testing.T, Name string, signer Signer, verifier Verifier) {
80 if name := signer.Name(); name != Name {
81 t.Errorf("signer.Name() = %q, want %q", name, Name)
82 }
83 if name := verifier.Name(); name != Name {
84 t.Errorf("verifier.Name() = %q, want %q", name, Name)
85 }
86 shash := signer.KeyHash()
87 vhash := verifier.KeyHash()
88 if shash != vhash {
89 t.Errorf("signer.KeyHash() = %#08x != verifier.KeyHash() = %#08x", shash, vhash)
90 }
91
92 msg := []byte("hi")
93 sig, err := signer.Sign(msg)
94 if err != nil {
95 t.Fatalf("signer.Sign: %v", err)
96 }
97 if !verifier.Verify(msg, sig) {
98 t.Fatalf("verifier.Verify failed on signature returned by signer.Sign")
99 }
100 sig[0]++
101 if verifier.Verify(msg, sig) {
102 t.Fatalf("verifier.Verify succeeded on corrupt signature")
103 }
104 sig[0]--
105 msg[0]++
106 if verifier.Verify(msg, sig) {
107 t.Fatalf("verifier.Verify succeeded on corrupt message")
108 }
109 }
110
111 func TestGenerateKey(t *testing.T) {
112
113 const Name = "EnochRoot"
114
115 skey, vkey, err := GenerateKey(rand.Reader, Name)
116 if err != nil {
117 t.Fatalf("GenerateKey: %v", err)
118 }
119 signer, err := NewSigner(skey)
120 if err != nil {
121 t.Fatalf("NewSigner: %v", err)
122 }
123 verifier, err := NewVerifier(vkey)
124 if err != nil {
125 t.Fatalf("NewVerifier: %v", err)
126 }
127
128 testSignerAndVerifier(t, Name, signer, verifier)
129
130
131 _, _, err = GenerateKey(iotest.TimeoutReader(iotest.OneByteReader(rand.Reader)), Name)
132 if err == nil {
133 t.Fatalf("GenerateKey succeeded with error-returning rand reader")
134 }
135 }
136
137 func TestFromEd25519(t *testing.T) {
138 const Name = "EnochRoot"
139
140 pub, priv, err := ed25519.GenerateKey(rand.Reader)
141 if err != nil {
142 t.Fatalf("GenerateKey: %v", err)
143 }
144 signer, err := newSignerFromEd25519Seed(Name, priv.Seed())
145 if err != nil {
146 t.Fatalf("newSignerFromEd25519Seed: %v", err)
147 }
148 vkey, err := NewEd25519VerifierKey(Name, pub)
149 if err != nil {
150 t.Fatalf("NewEd25519VerifierKey: %v", err)
151 }
152 verifier, err := NewVerifier(vkey)
153 if err != nil {
154 t.Fatalf("NewVerifier: %v", err)
155 }
156
157 testSignerAndVerifier(t, Name, signer, verifier)
158
159
160 _, err = NewEd25519VerifierKey(Name, pub[:len(pub)-1])
161 if err == nil {
162 t.Errorf("NewEd25519VerifierKey succeeded with a seed of the wrong size")
163 }
164 }
165
166
167
168 func newSignerFromEd25519Seed(name string, seed []byte) (Signer, error) {
169 if len(seed) != ed25519.SeedSize {
170 return nil, errors.New("invalid seed size")
171 }
172 priv := ed25519.NewKeyFromSeed(seed)
173 pub := priv[32:]
174
175 pubkey := append([]byte{algEd25519}, pub...)
176 hash := keyHash(name, pubkey)
177
178 s := &signer{
179 name: name,
180 hash: hash,
181 sign: func(msg []byte) ([]byte, error) {
182 return ed25519.Sign(priv, msg), nil
183 },
184 }
185 return s, nil
186 }
187
188 func TestSign(t *testing.T) {
189 skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
190 text := "If you think cryptography is the answer to your problem,\n" +
191 "then you don't know what your problem is.\n"
192
193 signer, err := NewSigner(skey)
194 if err != nil {
195 t.Fatal(err)
196 }
197
198 msg, err := Sign(&Note{Text: text}, signer)
199 if err != nil {
200 t.Fatal(err)
201 }
202
203 want := `If you think cryptography is the answer to your problem,
204 then you don't know what your problem is.
205
206 — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
207 `
208 if string(msg) != want {
209 t.Errorf("Sign: wrong output\nhave:\n%s\nwant:\n%s", msg, want)
210 }
211
212
213 msg, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "PeterNeumann", Hash: 0xc74f20a3, Base64: "BADSIGN="}}}, signer)
214 if err != nil {
215 t.Fatal(err)
216 }
217 if string(msg) != want {
218 t.Errorf("Sign replacing signature: wrong output\nhave:\n%s\nwant:\n%s", msg, want)
219 }
220
221
222 _, err = Sign(&Note{Text: "abc"}, signer)
223 if err == nil || err.Error() != "malformed note" {
224 t.Fatalf("Sign with short text: %v, want malformed note error", err)
225 }
226
227 _, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "a+b", Base64: "ABCD"}}})
228 if err == nil || err.Error() != "malformed note" {
229 t.Fatalf("Sign with bad name: %v, want malformed note error", err)
230 }
231
232 _, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "PeterNeumann", Hash: 0xc74f20a3, Base64: "BADHASH="}}})
233 if err == nil || err.Error() != "malformed note" {
234 t.Fatalf("Sign with bad pre-filled signature: %v, want malformed note error", err)
235 }
236
237 _, err = Sign(&Note{Text: text}, &badSigner{signer})
238 if err == nil || err.Error() != "invalid signer" {
239 t.Fatalf("Sign with bad signer: %v, want invalid signer error", err)
240 }
241
242 _, err = Sign(&Note{Text: text}, &errSigner{signer})
243 if err != errSurprise {
244 t.Fatalf("Sign with failing signer: %v, want errSurprise", err)
245 }
246 }
247
248 func TestVerifierList(t *testing.T) {
249 peterKey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
250 peterVerifier, err := NewVerifier(peterKey)
251 if err != nil {
252 t.Fatal(err)
253 }
254
255 enochKey := "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop"
256 enochVerifier, err := NewVerifier(enochKey)
257 if err != nil {
258 t.Fatal(err)
259 }
260
261 list := VerifierList(peterVerifier, enochVerifier, enochVerifier)
262 v, err := list.Verifier("PeterNeumann", 0xc74f20a3)
263 if v != peterVerifier || err != nil {
264 t.Fatalf("list.Verifier(peter) = %v, %v, want %v, nil", v, err, peterVerifier)
265 }
266 v, err = list.Verifier("PeterNeumann", 0xc74f20a4)
267 if v != nil || err == nil || err.Error() != "unknown key PeterNeumann+c74f20a4" {
268 t.Fatalf("list.Verifier(peter bad hash) = %v, %v, want nil, unknown key error", v, err)
269 }
270
271 v, err = list.Verifier("PeterNeuman", 0xc74f20a3)
272 if v != nil || err == nil || err.Error() != "unknown key PeterNeuman+c74f20a3" {
273 t.Fatalf("list.Verifier(peter bad name) = %v, %v, want nil, unknown key error", v, err)
274 }
275 v, err = list.Verifier("EnochRoot", 0xaf0cfe78)
276 if v != nil || err == nil || err.Error() != "ambiguous key EnochRoot+af0cfe78" {
277 t.Fatalf("list.Verifier(enoch) = %v, %v, want nil, ambiguous key error", v, err)
278 }
279 }
280
281 type badSigner struct {
282 Signer
283 }
284
285 func (b *badSigner) Name() string {
286 return "bad name"
287 }
288
289 var errSurprise = errors.New("surprise!")
290
291 type errSigner struct {
292 Signer
293 }
294
295 func (e *errSigner) Sign([]byte) ([]byte, error) {
296 return nil, errSurprise
297 }
298
299 type fixedVerifier struct{ v Verifier }
300
301 func (v fixedVerifier) Verifier(name string, hash uint32) (Verifier, error) {
302 return v.v, nil
303 }
304
305 func TestOpen(t *testing.T) {
306 peterKey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
307 peterVerifier, err := NewVerifier(peterKey)
308 if err != nil {
309 t.Fatal(err)
310 }
311
312 enochKey := "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop"
313 enochVerifier, err := NewVerifier(enochKey)
314 if err != nil {
315 t.Fatal(err)
316 }
317
318 text := `If you think cryptography is the answer to your problem,
319 then you don't know what your problem is.
320 `
321 peterSig := "— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n"
322 enochSig := "— EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=\n"
323
324 peter := Signature{"PeterNeumann", 0xc74f20a3, "x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM="}
325 enoch := Signature{"EnochRoot", 0xaf0cfe78, "rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="}
326
327
328 n, err := Open([]byte(text+"\n"+peterSig+enochSig), VerifierList(peterVerifier))
329 if err != nil {
330 t.Fatal(err)
331 }
332 if n.Text != text {
333 t.Errorf("n.Text = %q, want %q", n.Text, text)
334 }
335 if len(n.Sigs) != 1 || n.Sigs[0] != peter {
336 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
337 }
338 if len(n.UnverifiedSigs) != 1 || n.UnverifiedSigs[0] != enoch {
339 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
340 }
341
342
343 n, err = Open([]byte(text+"\n"+peterSig+enochSig), VerifierList(peterVerifier, enochVerifier))
344 if err != nil {
345 t.Fatal(err)
346 }
347 if len(n.Sigs) != 2 || n.Sigs[0] != peter || n.Sigs[1] != enoch {
348 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter, enoch})
349 }
350 if len(n.UnverifiedSigs) != 0 {
351 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{})
352 }
353
354
355 n, err = Open([]byte(text+"\n"+peterSig+enochSig), VerifierList())
356 if n != nil || err == nil {
357 t.Fatalf("Open unverified = %v, %v, want nil, error", n, err)
358 }
359 e, ok := err.(*UnverifiedNoteError)
360 if !ok {
361 t.Fatalf("Open unverified: err is %T, want *UnverifiedNoteError", err)
362 }
363 if err.Error() != "note has no verifiable signatures" {
364 t.Fatalf("Open unverified: err.Error() = %q, want %q", err.Error(), "note has no verifiable signatures")
365 }
366
367 n = e.Note
368 if n == nil {
369 t.Fatalf("Open unverified: missing note in UnverifiedNoteError")
370 }
371 if len(n.Sigs) != 0 {
372 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{})
373 }
374 if len(n.UnverifiedSigs) != 2 || n.UnverifiedSigs[0] != peter || n.UnverifiedSigs[1] != enoch {
375 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter, enoch})
376 }
377
378
379 _, err = Open([]byte(text+"\n"+enochSig), VerifierList(enochVerifier, peterVerifier, enochVerifier))
380 if err == nil || err.Error() != "ambiguous key EnochRoot+af0cfe78" {
381 t.Fatalf("Open with duplicated verifier: err=%v, want ambiguous key", err)
382 }
383
384
385 _, err = Open([]byte(text+"\n"+peterSig), VerifierList(enochVerifier, peterVerifier, enochVerifier))
386 if err != nil {
387 t.Fatal(err)
388 }
389
390
391 n, err = Open([]byte(text+"\n"+strings.Repeat(peterSig, 101)), VerifierList(peterVerifier))
392 if n != nil || err == nil || err.Error() != "malformed note" {
393 t.Fatalf("Open too many verified signatures = %v, %v, want nil, malformed note error", n, err)
394 }
395 n, err = Open([]byte(text+"\n"+strings.Repeat(peterSig, 101)), VerifierList())
396 if n != nil || err == nil || err.Error() != "malformed note" {
397 t.Fatalf("Open too many verified signatures = %v, %v, want nil, malformed note error", n, err)
398 }
399
400
401 n, err = Open([]byte(text+"\n"+peterSig[:60]+"ABCD"+peterSig[60:]), VerifierList(peterVerifier))
402 if n != nil || err == nil || err.Error() != "invalid signature for key PeterNeumann+c74f20a3" {
403 t.Fatalf("Open too many verified signatures = %v, %v, want nil, invalid signature error", n, err)
404 }
405
406
407 enochABCD := Signature{"EnochRoot", 0xaf0cfe78, "rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n" + "ABCD" + "2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="}
408 n, err = Open([]byte(text+"\n"+peterSig+peterSig+enochSig+enochSig+enochSig[:60]+"ABCD"+enochSig[60:]), VerifierList(peterVerifier))
409 if err != nil {
410 t.Fatal(err)
411 }
412 if len(n.Sigs) != 1 || n.Sigs[0] != peter {
413 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
414 }
415 if len(n.UnverifiedSigs) != 2 || n.UnverifiedSigs[0] != enoch || n.UnverifiedSigs[1] != enochABCD {
416 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.UnverifiedSigs, []Signature{enoch, enochABCD})
417 }
418
419
420 badMsgs := []string{
421 text,
422 text + "\n",
423 text + "\n" + peterSig[:len(peterSig)-1],
424 "\x01" + text + "\n" + peterSig,
425 "\xff" + text + "\n" + peterSig,
426 text + "\n" + "— Bad Name x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=",
427 text + "\n" + peterSig + "Unexpected line.\n",
428 }
429 for _, msg := range badMsgs {
430 n, err := Open([]byte(msg), VerifierList(peterVerifier))
431 if n != nil || err == nil || err.Error() != "malformed note" {
432 t.Fatalf("Open bad msg = %v, %v, want nil, malformed note error\nmsg:\n%s", n, err, msg)
433 }
434 }
435
436
437 misnamedSig := strings.Replace(peterSig, "PeterNeumann", "CarmenSandiego", -1)
438 _, err = Open([]byte(text+"\n"+misnamedSig), fixedVerifier{peterVerifier})
439 if err != errMismatchedVerifier {
440 t.Fatalf("Open with wrong Verifier, err=%v, want errMismatchedVerifier", err)
441 }
442 wrongHash := strings.Replace(peterSig, "x08g", "xxxx", -1)
443 _, err = Open([]byte(text+"\n"+wrongHash), fixedVerifier{peterVerifier})
444 if err != errMismatchedVerifier {
445 t.Fatalf("Open with wrong Verifier, err=%v, want errMismatchedVerifier", err)
446 }
447 }
448
449 func BenchmarkOpen(b *testing.B) {
450 vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
451 msg := []byte("If you think cryptography is the answer to your problem,\n" +
452 "then you don't know what your problem is.\n" +
453 "\n" +
454 "— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n")
455
456 verifier, err := NewVerifier(vkey)
457 if err != nil {
458 b.Fatal(err)
459 }
460 verifiers := VerifierList(verifier)
461 verifiers0 := VerifierList()
462
463
464
465 b.Run("Sig0", func(b *testing.B) {
466 for i := 0; i < b.N; i++ {
467 _, err := Open(msg, verifiers0)
468 e, ok := err.(*UnverifiedNoteError)
469 if !ok {
470 b.Fatal("expected UnverifiedNoteError")
471 }
472 n := e.Note
473 if len(n.Sigs) != 0 || len(n.UnverifiedSigs) != 1 {
474 b.Fatal("wrong signature count")
475 }
476 }
477 })
478
479 b.Run("Sig1", func(b *testing.B) {
480 for i := 0; i < b.N; i++ {
481 n, err := Open(msg, verifiers)
482 if err != nil {
483 b.Fatal(err)
484 }
485 if len(n.Sigs) != 1 || len(n.UnverifiedSigs) != 0 {
486 b.Fatal("wrong signature count")
487 }
488 }
489 })
490 }
491
View as plain text