1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 package note
180
181 import (
182 "bytes"
183 "crypto/sha256"
184 "encoding/base64"
185 "encoding/binary"
186 "errors"
187 "fmt"
188 "io"
189 "strconv"
190 "strings"
191 "unicode"
192 "unicode/utf8"
193
194 "golang.org/x/crypto/ed25519"
195 )
196
197
198 type Verifier interface {
199
200 Name() string
201
202
203 KeyHash() uint32
204
205
206 Verify(msg, sig []byte) bool
207 }
208
209
210 type Signer interface {
211
212 Name() string
213
214
215 KeyHash() uint32
216
217
218 Sign(msg []byte) ([]byte, error)
219 }
220
221
222 func keyHash(name string, key []byte) uint32 {
223 h := sha256.New()
224 h.Write([]byte(name))
225 h.Write([]byte("\n"))
226 h.Write(key)
227 sum := h.Sum(nil)
228 return binary.BigEndian.Uint32(sum)
229 }
230
231 var (
232 errVerifierID = errors.New("malformed verifier id")
233 errVerifierAlg = errors.New("unknown verifier algorithm")
234 errVerifierHash = errors.New("invalid verifier hash")
235 )
236
237 const (
238 algEd25519 = 1
239 )
240
241
242
243 func isValidName(name string) bool {
244 return name != "" && utf8.ValidString(name) && strings.IndexFunc(name, unicode.IsSpace) < 0 && !strings.Contains(name, "+")
245 }
246
247
248 func NewVerifier(vkey string) (Verifier, error) {
249 name, vkey := chop(vkey, "+")
250 hash16, key64 := chop(vkey, "+")
251 hash, err1 := strconv.ParseUint(hash16, 16, 32)
252 key, err2 := base64.StdEncoding.DecodeString(key64)
253 if len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
254 return nil, errVerifierID
255 }
256 if uint32(hash) != keyHash(name, key) {
257 return nil, errVerifierHash
258 }
259
260 v := &verifier{
261 name: name,
262 hash: uint32(hash),
263 }
264
265 alg, key := key[0], key[1:]
266 switch alg {
267 default:
268 return nil, errVerifierAlg
269
270 case algEd25519:
271 if len(key) != 32 {
272 return nil, errVerifierID
273 }
274 v.verify = func(msg, sig []byte) bool {
275 return ed25519.Verify(key, msg, sig)
276 }
277 }
278
279 return v, nil
280 }
281
282
283
284
285 func chop(s, sep string) (before, after string) {
286 i := strings.Index(s, sep)
287 if i < 0 {
288 return s, ""
289 }
290 return s[:i], s[i+len(sep):]
291 }
292
293
294 type verifier struct {
295 name string
296 hash uint32
297 verify func([]byte, []byte) bool
298 }
299
300 func (v *verifier) Name() string { return v.name }
301 func (v *verifier) KeyHash() uint32 { return v.hash }
302 func (v *verifier) Verify(msg, sig []byte) bool { return v.verify(msg, sig) }
303
304
305 func NewSigner(skey string) (Signer, error) {
306 priv1, skey := chop(skey, "+")
307 priv2, skey := chop(skey, "+")
308 name, skey := chop(skey, "+")
309 hash16, key64 := chop(skey, "+")
310 hash, err1 := strconv.ParseUint(hash16, 16, 32)
311 key, err2 := base64.StdEncoding.DecodeString(key64)
312 if priv1 != "PRIVATE" || priv2 != "KEY" || len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
313 return nil, errSignerID
314 }
315
316
317
318
319 s := &signer{
320 name: name,
321 hash: uint32(hash),
322 }
323
324 var pubkey []byte
325
326 alg, key := key[0], key[1:]
327 switch alg {
328 default:
329 return nil, errSignerAlg
330
331 case algEd25519:
332 if len(key) != 32 {
333 return nil, errSignerID
334 }
335 key = ed25519.NewKeyFromSeed(key)
336 pubkey = append([]byte{algEd25519}, key[32:]...)
337 s.sign = func(msg []byte) ([]byte, error) {
338 return ed25519.Sign(key, msg), nil
339 }
340 }
341
342 if uint32(hash) != keyHash(name, pubkey) {
343 return nil, errSignerHash
344 }
345
346 return s, nil
347 }
348
349 var (
350 errSignerID = errors.New("malformed verifier id")
351 errSignerAlg = errors.New("unknown verifier algorithm")
352 errSignerHash = errors.New("invalid verifier hash")
353 )
354
355
356 type signer struct {
357 name string
358 hash uint32
359 sign func([]byte) ([]byte, error)
360 }
361
362 func (s *signer) Name() string { return s.name }
363 func (s *signer) KeyHash() uint32 { return s.hash }
364 func (s *signer) Sign(msg []byte) ([]byte, error) { return s.sign(msg) }
365
366
367
368 func GenerateKey(rand io.Reader, name string) (skey, vkey string, err error) {
369 pub, priv, err := ed25519.GenerateKey(rand)
370 if err != nil {
371 return "", "", err
372 }
373 pubkey := append([]byte{algEd25519}, pub...)
374 privkey := append([]byte{algEd25519}, priv.Seed()...)
375 h := keyHash(name, pubkey)
376
377 skey = fmt.Sprintf("PRIVATE+KEY+%s+%08x+%s", name, h, base64.StdEncoding.EncodeToString(privkey))
378 vkey = fmt.Sprintf("%s+%08x+%s", name, h, base64.StdEncoding.EncodeToString(pubkey))
379 return skey, vkey, nil
380 }
381
382
383
384 func NewEd25519VerifierKey(name string, key ed25519.PublicKey) (string, error) {
385 if len(key) != ed25519.PublicKeySize {
386 return "", fmt.Errorf("invalid public key size %d, expected %d", len(key), ed25519.PublicKeySize)
387 }
388
389 pubkey := append([]byte{algEd25519}, key...)
390 hash := keyHash(name, pubkey)
391
392 b64Key := base64.StdEncoding.EncodeToString(pubkey)
393 return fmt.Sprintf("%s+%08x+%s", name, hash, b64Key), nil
394 }
395
396
397 type Verifiers interface {
398
399
400
401
402 Verifier(name string, hash uint32) (Verifier, error)
403 }
404
405
406
407
408 type UnknownVerifierError struct {
409 Name string
410 KeyHash uint32
411 }
412
413 func (e *UnknownVerifierError) Error() string {
414 return fmt.Sprintf("unknown key %s+%08x", e.Name, e.KeyHash)
415 }
416
417
418
419
420
421
422 type ambiguousVerifierError struct {
423 name string
424 hash uint32
425 }
426
427 func (e *ambiguousVerifierError) Error() string {
428 return fmt.Sprintf("ambiguous key %s+%08x", e.name, e.hash)
429 }
430
431
432 func VerifierList(list ...Verifier) Verifiers {
433 m := make(verifierMap)
434 for _, v := range list {
435 k := nameHash{v.Name(), v.KeyHash()}
436 m[k] = append(m[k], v)
437 }
438 return m
439 }
440
441 type nameHash struct {
442 name string
443 hash uint32
444 }
445
446 type verifierMap map[nameHash][]Verifier
447
448 func (m verifierMap) Verifier(name string, hash uint32) (Verifier, error) {
449 v, ok := m[nameHash{name, hash}]
450 if !ok {
451 return nil, &UnknownVerifierError{name, hash}
452 }
453 if len(v) > 1 {
454 return nil, &ambiguousVerifierError{name, hash}
455 }
456 return v[0], nil
457 }
458
459
460 type Note struct {
461 Text string
462 Sigs []Signature
463 UnverifiedSigs []Signature
464 }
465
466
467 type Signature struct {
468
469
470 Name string
471 Hash uint32
472
473
474 Base64 string
475 }
476
477
478
479 type UnverifiedNoteError struct {
480 Note *Note
481 }
482
483 func (e *UnverifiedNoteError) Error() string {
484 return "note has no verifiable signatures"
485 }
486
487
488
489 type InvalidSignatureError struct {
490 Name string
491 Hash uint32
492 }
493
494 func (e *InvalidSignatureError) Error() string {
495 return fmt.Sprintf("invalid signature for key %s+%08x", e.Name, e.Hash)
496 }
497
498 var (
499 errMalformedNote = errors.New("malformed note")
500 errInvalidSigner = errors.New("invalid signer")
501
502 sigSplit = []byte("\n\n")
503 sigPrefix = []byte("— ")
504 )
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520 func Open(msg []byte, known Verifiers) (*Note, error) {
521 if known == nil {
522
523 known = VerifierList()
524 }
525
526
527 for i := 0; i < len(msg); {
528 r, size := utf8.DecodeRune(msg[i:])
529 if r < 0x20 && r != '\n' || r == utf8.RuneError && size == 1 {
530 return nil, errMalformedNote
531 }
532 i += size
533 }
534
535
536 split := bytes.LastIndex(msg, sigSplit)
537 if split < 0 {
538 return nil, errMalformedNote
539 }
540 text, sigs := msg[:split+1], msg[split+2:]
541 if len(sigs) == 0 || sigs[len(sigs)-1] != '\n' {
542 return nil, errMalformedNote
543 }
544
545 n := &Note{
546 Text: string(text),
547 }
548
549
550
551 seen := make(map[nameHash]bool)
552 seenUnverified := make(map[string]bool)
553 numSig := 0
554 for len(sigs) > 0 {
555
556
557 i := bytes.IndexByte(sigs, '\n')
558 line := sigs[:i]
559 sigs = sigs[i+1:]
560
561 if !bytes.HasPrefix(line, sigPrefix) {
562 return nil, errMalformedNote
563 }
564 line = line[len(sigPrefix):]
565 name, b64 := chop(string(line), " ")
566 sig, err := base64.StdEncoding.DecodeString(b64)
567 if err != nil || !isValidName(name) || b64 == "" || len(sig) < 5 {
568 return nil, errMalformedNote
569 }
570 hash := binary.BigEndian.Uint32(sig[0:4])
571 sig = sig[4:]
572
573 if numSig++; numSig > 100 {
574
575 return nil, errMalformedNote
576 }
577
578 v, err := known.Verifier(name, hash)
579 if _, ok := err.(*UnknownVerifierError); ok {
580
581 if seenUnverified[string(line)] {
582 continue
583 }
584 seenUnverified[string(line)] = true
585 n.UnverifiedSigs = append(n.UnverifiedSigs, Signature{Name: name, Hash: hash, Base64: b64})
586 continue
587 }
588 if err != nil {
589 return nil, err
590 }
591
592
593 if seen[nameHash{name, hash}] {
594 continue
595 }
596 seen[nameHash{name, hash}] = true
597
598 ok := v.Verify(text, sig)
599 if !ok {
600 return nil, &InvalidSignatureError{name, hash}
601 }
602
603 n.Sigs = append(n.Sigs, Signature{Name: name, Hash: hash, Base64: b64})
604 }
605
606
607 if len(n.Sigs) == 0 {
608 return nil, &UnverifiedNoteError{n}
609 }
610 return n, nil
611 }
612
613
614
615
616
617
618 func Sign(n *Note, signers ...Signer) ([]byte, error) {
619 var buf bytes.Buffer
620 if !strings.HasSuffix(n.Text, "\n") {
621 return nil, errMalformedNote
622 }
623 buf.WriteString(n.Text)
624
625
626 var sigs bytes.Buffer
627 have := make(map[nameHash]bool)
628 for _, s := range signers {
629 name := s.Name()
630 hash := s.KeyHash()
631 have[nameHash{name, hash}] = true
632 if !isValidName(name) {
633 return nil, errInvalidSigner
634 }
635
636 sig, err := s.Sign(buf.Bytes())
637 if err != nil {
638 return nil, err
639 }
640
641 var hbuf [4]byte
642 binary.BigEndian.PutUint32(hbuf[:], hash)
643 b64 := base64.StdEncoding.EncodeToString(append(hbuf[:], sig...))
644 sigs.WriteString("— ")
645 sigs.WriteString(name)
646 sigs.WriteString(" ")
647 sigs.WriteString(b64)
648 sigs.WriteString("\n")
649 }
650
651 buf.WriteString("\n")
652
653
654 for _, list := range [][]Signature{n.Sigs, n.UnverifiedSigs} {
655 for _, sig := range list {
656 name, hash := sig.Name, sig.Hash
657 if !isValidName(name) {
658 return nil, errMalformedNote
659 }
660 if have[nameHash{name, hash}] {
661 continue
662 }
663
664 raw, err := base64.StdEncoding.DecodeString(sig.Base64)
665 if err != nil || len(raw) < 4 || binary.BigEndian.Uint32(raw) != hash {
666 return nil, errMalformedNote
667 }
668 buf.WriteString("— ")
669 buf.WriteString(sig.Name)
670 buf.WriteString(" ")
671 buf.WriteString(sig.Base64)
672 buf.WriteString("\n")
673 }
674 }
675 buf.Write(sigs.Bytes())
676
677 return buf.Bytes(), nil
678 }
679
View as plain text