1 // Copyright 2019 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.
14 "golang.org/x/crypto/ed25519"
17 func TestNewVerifier(t *testing.T) {
18 vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
19 _, err := NewVerifier(vkey)
24 // Check various manglings are not accepted.
25 badKey := func(k string) {
26 _, err := NewVerifier(k)
28 t.Errorf("NewVerifier(%q) succeeded, should have failed", k)
33 for i := 0; i <= len(b); i++ {
34 for j := i + 1; j <= len(b); j++ {
35 if i != 0 || j != len(b) {
36 badKey(string(b[i:j]))
40 for i := 0; i < len(b); i++ {
46 badKey("PeterNeumann+cc469956+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TWBADKEY==") // wrong length key, with adjusted key hash
47 badKey("PeterNeumann+173116ae+ZRpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW") // unknown algorithm, with adjusted key hash
50 func TestNewSigner(t *testing.T) {
51 skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
52 _, err := NewSigner(skey)
57 // Check various manglings are not accepted.
59 for i := 0; i <= len(b); i++ {
60 for j := i + 1; j <= len(b); j++ {
61 if i == 0 && j == len(b) {
64 _, err := NewSigner(string(b[i:j]))
66 t.Errorf("NewSigner(%q) succeeded, should have failed", b[i:j])
70 for i := 0; i < len(b); i++ {
72 _, err := NewSigner(string(b))
74 t.Errorf("NewSigner(%q) succeeded, should have failed", b)
80 func testSignerAndVerifier(t *testing.T, Name string, signer Signer, verifier Verifier) {
81 if name := signer.Name(); name != Name {
82 t.Errorf("signer.Name() = %q, want %q", name, Name)
84 if name := verifier.Name(); name != Name {
85 t.Errorf("verifier.Name() = %q, want %q", name, Name)
87 shash := signer.KeyHash()
88 vhash := verifier.KeyHash()
90 t.Errorf("signer.KeyHash() = %#08x != verifier.KeyHash() = %#08x", shash, vhash)
94 sig, err := signer.Sign(msg)
96 t.Fatalf("signer.Sign: %v", err)
98 if !verifier.Verify(msg, sig) {
99 t.Fatalf("verifier.Verify failed on signature returned by signer.Sign")
102 if verifier.Verify(msg, sig) {
103 t.Fatalf("verifier.Verify succceeded on corrupt signature")
107 if verifier.Verify(msg, sig) {
108 t.Fatalf("verifier.Verify succceeded on corrupt message")
112 func TestGenerateKey(t *testing.T) {
113 // Generate key pair, make sure it is all self-consistent.
114 const Name = "EnochRoot"
116 skey, vkey, err := GenerateKey(rand.Reader, Name)
118 t.Fatalf("GenerateKey: %v", err)
120 signer, err := NewSigner(skey)
122 t.Fatalf("NewSigner: %v", err)
124 verifier, err := NewVerifier(vkey)
126 t.Fatalf("NewVerifier: %v", err)
129 testSignerAndVerifier(t, Name, signer, verifier)
131 // Check that GenerateKey returns error from rand reader.
132 _, _, err = GenerateKey(iotest.TimeoutReader(iotest.OneByteReader(rand.Reader)), Name)
134 t.Fatalf("GenerateKey succeeded with error-returning rand reader")
138 func TestFromEd25519(t *testing.T) {
139 const Name = "EnochRoot"
141 pub, priv, err := ed25519.GenerateKey(rand.Reader)
143 t.Fatalf("GenerateKey: %v", err)
145 signer, err := newSignerFromEd25519Seed(Name, priv.Seed())
147 t.Fatalf("newSignerFromEd25519Seed: %v", err)
149 vkey, err := NewEd25519VerifierKey(Name, pub)
151 t.Fatalf("NewEd25519VerifierKey: %v", err)
153 verifier, err := NewVerifier(vkey)
155 t.Fatalf("NewVerifier: %v", err)
158 testSignerAndVerifier(t, Name, signer, verifier)
160 // Check that wrong key sizes return errors.
161 _, err = NewEd25519VerifierKey(Name, pub[:len(pub)-1])
163 t.Errorf("NewEd25519VerifierKey succeeded with a seed of the wrong size")
167 // newSignerFromEd25519Seed constructs a new signer from a verifier name and a
168 // golang.org/x/crypto/ed25519 private key seed.
169 func newSignerFromEd25519Seed(name string, seed []byte) (Signer, error) {
170 if len(seed) != ed25519.SeedSize {
171 return nil, errors.New("invalid seed size")
173 priv := ed25519.NewKeyFromSeed(seed)
176 pubkey := append([]byte{algEd25519}, pub...)
177 hash := keyHash(name, pubkey)
182 sign: func(msg []byte) ([]byte, error) {
183 return ed25519.Sign(priv, msg), nil
189 func TestSign(t *testing.T) {
190 skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
191 text := "If you think cryptography is the answer to your problem,\n" +
192 "then you don't know what your problem is.\n"
194 signer, err := NewSigner(skey)
199 msg, err := Sign(&Note{Text: text}, signer)
204 want := `If you think cryptography is the answer to your problem,
205 then you don't know what your problem is.
207 — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
209 if string(msg) != want {
210 t.Errorf("Sign: wrong output\nhave:\n%s\nwant:\n%s", msg, want)
213 // Check that existing signature is replaced by new one.
214 msg, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "PeterNeumann", Hash: 0xc74f20a3, Base64: "BADSIGN="}}}, signer)
218 if string(msg) != want {
219 t.Errorf("Sign replacing signature: wrong output\nhave:\n%s\nwant:\n%s", msg, want)
222 // Check various bad inputs.
223 _, err = Sign(&Note{Text: "abc"}, signer)
224 if err == nil || err.Error() != "malformed note" {
225 t.Fatalf("Sign with short text: %v, want malformed note error", err)
228 _, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "a+b", Base64: "ABCD"}}})
229 if err == nil || err.Error() != "malformed note" {
230 t.Fatalf("Sign with bad name: %v, want malformed note error", err)
233 _, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "PeterNeumann", Hash: 0xc74f20a3, Base64: "BADHASH="}}})
234 if err == nil || err.Error() != "malformed note" {
235 t.Fatalf("Sign with bad pre-filled signature: %v, want malformed note error", err)
238 _, err = Sign(&Note{Text: text}, &badSigner{signer})
239 if err == nil || err.Error() != "invalid signer" {
240 t.Fatalf("Sign with bad signer: %v, want invalid signer error", err)
243 _, err = Sign(&Note{Text: text}, &errSigner{signer})
244 if err != errSurprise {
245 t.Fatalf("Sign with failing signer: %v, want errSurprise", err)
249 func TestVerifierList(t *testing.T) {
250 peterKey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
251 peterVerifier, err := NewVerifier(peterKey)
256 enochKey := "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop"
257 enochVerifier, err := NewVerifier(enochKey)
262 list := VerifierList(peterVerifier, enochVerifier, enochVerifier)
263 v, err := list.Verifier("PeterNeumann", 0xc74f20a3)
264 if v != peterVerifier || err != nil {
265 t.Fatalf("list.Verifier(peter) = %v, %v, want %v, nil", v, err, peterVerifier)
267 v, err = list.Verifier("PeterNeumann", 0xc74f20a4)
268 if v != nil || err == nil || err.Error() != "unknown key PeterNeumann+c74f20a4" {
269 t.Fatalf("list.Verifier(peter bad hash) = %v, %v, want nil, unknown key error", v, err)
272 v, err = list.Verifier("PeterNeuman", 0xc74f20a3)
273 if v != nil || err == nil || err.Error() != "unknown key PeterNeuman+c74f20a3" {
274 t.Fatalf("list.Verifier(peter bad name) = %v, %v, want nil, unknown key error", v, err)
276 v, err = list.Verifier("EnochRoot", 0xaf0cfe78)
277 if v != nil || err == nil || err.Error() != "ambiguous key EnochRoot+af0cfe78" {
278 t.Fatalf("list.Verifier(enoch) = %v, %v, want nil, ambiguous key error", v, err)
282 type badSigner struct {
286 func (b *badSigner) Name() string {
290 var errSurprise = errors.New("surprise!")
292 type errSigner struct {
296 func (e *errSigner) Sign([]byte) ([]byte, error) {
297 return nil, errSurprise
300 func TestOpen(t *testing.T) {
301 peterKey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
302 peterVerifier, err := NewVerifier(peterKey)
307 enochKey := "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop"
308 enochVerifier, err := NewVerifier(enochKey)
313 text := `If you think cryptography is the answer to your problem,
314 then you don't know what your problem is.
316 peterSig := "— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n"
317 enochSig := "— EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=\n"
319 peter := Signature{"PeterNeumann", 0xc74f20a3, "x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM="}
320 enoch := Signature{"EnochRoot", 0xaf0cfe78, "rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="}
322 // Check one signature verified, one not.
323 n, err := Open([]byte(text+"\n"+peterSig+enochSig), VerifierList(peterVerifier))
328 t.Errorf("n.Text = %q, want %q", n.Text, text)
330 if len(n.Sigs) != 1 || n.Sigs[0] != peter {
331 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
333 if len(n.UnverifiedSigs) != 1 || n.UnverifiedSigs[0] != enoch {
334 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
337 // Check both verified.
338 n, err = Open([]byte(text+"\n"+peterSig+enochSig), VerifierList(peterVerifier, enochVerifier))
342 if len(n.Sigs) != 2 || n.Sigs[0] != peter || n.Sigs[1] != enoch {
343 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter, enoch})
345 if len(n.UnverifiedSigs) != 0 {
346 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{})
349 // Check both unverified.
350 n, err = Open([]byte(text+"\n"+peterSig+enochSig), VerifierList())
351 if n != nil || err == nil {
352 t.Fatalf("Open unverified = %v, %v, want nil, error", n, err)
354 e, ok := err.(*UnverifiedNoteError)
356 t.Fatalf("Open unverified: err is %T, want *UnverifiedNoteError", err)
358 if err.Error() != "note has no verifiable signatures" {
359 t.Fatalf("Open unverified: err.Error() = %q, want %q", err.Error(), "note has no verifiable signatures")
364 t.Fatalf("Open unverified: missing note in UnverifiedNoteError")
366 if len(n.Sigs) != 0 {
367 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{})
369 if len(n.UnverifiedSigs) != 2 || n.UnverifiedSigs[0] != peter || n.UnverifiedSigs[1] != enoch {
370 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter, enoch})
373 // Check duplicated verifier.
374 _, err = Open([]byte(text+"\n"+enochSig), VerifierList(enochVerifier, peterVerifier, enochVerifier))
375 if err == nil || err.Error() != "ambiguous key EnochRoot+af0cfe78" {
376 t.Fatalf("Open with duplicated verifier: err=%v, want ambiguous key", err)
379 // Check unused duplicated verifier.
380 _, err = Open([]byte(text+"\n"+peterSig), VerifierList(enochVerifier, peterVerifier, enochVerifier))
385 // Check too many signatures.
386 n, err = Open([]byte(text+"\n"+strings.Repeat(peterSig, 101)), VerifierList(peterVerifier))
387 if n != nil || err == nil || err.Error() != "malformed note" {
388 t.Fatalf("Open too many verified signatures = %v, %v, want nil, malformed note error", n, err)
390 n, err = Open([]byte(text+"\n"+strings.Repeat(peterSig, 101)), VerifierList())
391 if n != nil || err == nil || err.Error() != "malformed note" {
392 t.Fatalf("Open too many verified signatures = %v, %v, want nil, malformed note error", n, err)
395 // Invalid signature.
396 n, err = Open([]byte(text+"\n"+peterSig[:60]+"ABCD"+peterSig[60:]), VerifierList(peterVerifier))
397 if n != nil || err == nil || err.Error() != "invalid signature for key PeterNeumann+c74f20a3" {
398 t.Fatalf("Open too many verified signatures = %v, %v, want nil, invalid signature error", n, err)
401 // Duplicated verified and unverified signatures.
402 enochABCD := Signature{"EnochRoot", 0xaf0cfe78, "rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n" + "ABCD" + "2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="}
403 n, err = Open([]byte(text+"\n"+peterSig+peterSig+enochSig+enochSig+enochSig[:60]+"ABCD"+enochSig[60:]), VerifierList(peterVerifier))
407 if len(n.Sigs) != 1 || n.Sigs[0] != peter {
408 t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
410 if len(n.UnverifiedSigs) != 2 || n.UnverifiedSigs[0] != enoch || n.UnverifiedSigs[1] != enochABCD {
411 t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.UnverifiedSigs, []Signature{enoch, enochABCD})
414 // Invalid encoded message syntax.
418 text + "\n" + peterSig[:len(peterSig)-1],
419 "\x01" + text + "\n" + peterSig,
420 "\xff" + text + "\n" + peterSig,
421 text + "\n" + "— Bad Name x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=",
422 text + "\n" + peterSig + "Unexpected line.\n",
424 for _, msg := range badMsgs {
425 n, err := Open([]byte(msg), VerifierList(peterVerifier))
426 if n != nil || err == nil || err.Error() != "malformed note" {
427 t.Fatalf("Open bad msg = %v, %v, want nil, malformed note error\nmsg:\n%s", n, err, msg)
432 func BenchmarkOpen(b *testing.B) {
433 vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
434 msg := []byte("If you think cryptography is the answer to your problem,\n" +
435 "then you don't know what your problem is.\n" +
437 "— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n")
439 verifier, err := NewVerifier(vkey)
443 verifiers := VerifierList(verifier)
444 verifiers0 := VerifierList()
446 // Try with 0 signatures and 1 signature so we can tell how much each signature adds.
448 b.Run("Sig0", func(b *testing.B) {
449 for i := 0; i < b.N; i++ {
450 _, err := Open(msg, verifiers0)
451 e, ok := err.(*UnverifiedNoteError)
453 b.Fatal("expected UnverifiedNoteError")
456 if len(n.Sigs) != 0 || len(n.UnverifiedSigs) != 1 {
457 b.Fatal("wrong signature count")
462 b.Run("Sig1", func(b *testing.B) {
463 for i := 0; i < b.N; i++ {
464 n, err := Open(msg, verifiers)
468 if len(n.Sigs) != 1 || len(n.UnverifiedSigs) != 0 {
469 b.Fatal("wrong signature count")