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 package note
175
176 import (
177 "bytes"
178 "crypto/ed25519"
179 "crypto/sha256"
180 "encoding/base64"
181 "encoding/binary"
182 "errors"
183 "fmt"
184 "io"
185 "strconv"
186 "strings"
187 "unicode"
188 "unicode/utf8"
189 )
190
191
192 type Verifier interface {
193
194 Name() string
195
196
197 KeyHash() uint32
198
199
200 Verify(msg, sig []byte) bool
201 }
202
203
204 type Signer interface {
205
206 Name() string
207
208
209 KeyHash() uint32
210
211
212 Sign(msg []byte) ([]byte, error)
213 }
214
215
216 func keyHash(name string, key []byte) uint32 {
217 h := sha256.New()
218 h.Write([]byte(name))
219 h.Write([]byte("\n"))
220 h.Write(key)
221 sum := h.Sum(nil)
222 return binary.BigEndian.Uint32(sum)
223 }
224
225 var (
226 errVerifierID = errors.New("malformed verifier id")
227 errVerifierAlg = errors.New("unknown verifier algorithm")
228 errVerifierHash = errors.New("invalid verifier hash")
229 )
230
231 const (
232 algEd25519 = 1
233 )
234
235
236
237 func isValidName(name string) bool {
238 return name != "" && utf8.ValidString(name) && strings.IndexFunc(name, unicode.IsSpace) < 0 && !strings.Contains(name, "+")
239 }
240
241
242 func NewVerifier(vkey string) (Verifier, error) {
243 name, vkey := chop(vkey, "+")
244 hash16, key64 := chop(vkey, "+")
245 hash, err1 := strconv.ParseUint(hash16, 16, 32)
246 key, err2 := base64.StdEncoding.DecodeString(key64)
247 if len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
248 return nil, errVerifierID
249 }
250 if uint32(hash) != keyHash(name, key) {
251 return nil, errVerifierHash
252 }
253
254 v := &verifier{
255 name: name,
256 hash: uint32(hash),
257 }
258
259 alg, key := key[0], key[1:]
260 switch alg {
261 default:
262 return nil, errVerifierAlg
263
264 case algEd25519:
265 if len(key) != 32 {
266 return nil, errVerifierID
267 }
268 v.verify = func(msg, sig []byte) bool {
269 return ed25519.Verify(key, msg, sig)
270 }
271 }
272
273 return v, nil
274 }
275
276
277
278
279 func chop(s, sep string) (before, after string) {
280 i := strings.Index(s, sep)
281 if i < 0 {
282 return s, ""
283 }
284 return s[:i], s[i+len(sep):]
285 }
286
287
288 type verifier struct {
289 name string
290 hash uint32
291 verify func([]byte, []byte) bool
292 }
293
294 func (v *verifier) Name() string { return v.name }
295 func (v *verifier) KeyHash() uint32 { return v.hash }
296 func (v *verifier) Verify(msg, sig []byte) bool { return v.verify(msg, sig) }
297
298
299 func NewSigner(skey string) (Signer, error) {
300 priv1, skey := chop(skey, "+")
301 priv2, skey := chop(skey, "+")
302 name, skey := chop(skey, "+")
303 hash16, key64 := chop(skey, "+")
304 hash, err1 := strconv.ParseUint(hash16, 16, 32)
305 key, err2 := base64.StdEncoding.DecodeString(key64)
306 if priv1 != "PRIVATE" || priv2 != "KEY" || len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
307 return nil, errSignerID
308 }
309
310
311
312
313 s := &signer{
314 name: name,
315 hash: uint32(hash),
316 }
317
318 var pubkey []byte
319
320 alg, key := key[0], key[1:]
321 switch alg {
322 default:
323 return nil, errSignerAlg
324
325 case algEd25519:
326 if len(key) != 32 {
327 return nil, errSignerID
328 }
329 key = ed25519.NewKeyFromSeed(key)
330 pubkey = append([]byte{algEd25519}, key[32:]...)
331 s.sign = func(msg []byte) ([]byte, error) {
332 return ed25519.Sign(key, msg), nil
333 }
334 }
335
336 if uint32(hash) != keyHash(name, pubkey) {
337 return nil, errSignerHash
338 }
339
340 return s, nil
341 }
342
343 var (
344 errSignerID = errors.New("malformed verifier id")
345 errSignerAlg = errors.New("unknown verifier algorithm")
346 errSignerHash = errors.New("invalid verifier hash")
347 )
348
349
350 type signer struct {
351 name string
352 hash uint32
353 sign func([]byte) ([]byte, error)
354 }
355
356 func (s *signer) Name() string { return s.name }
357 func (s *signer) KeyHash() uint32 { return s.hash }
358 func (s *signer) Sign(msg []byte) ([]byte, error) { return s.sign(msg) }
359
360
361
362 func GenerateKey(rand io.Reader, name string) (skey, vkey string, err error) {
363 pub, priv, err := ed25519.GenerateKey(rand)
364 if err != nil {
365 return "", "", err
366 }
367 pubkey := append([]byte{algEd25519}, pub...)
368 privkey := append([]byte{algEd25519}, priv.Seed()...)
369 h := keyHash(name, pubkey)
370
371 skey = fmt.Sprintf("PRIVATE+KEY+%s+%08x+%s", name, h, base64.StdEncoding.EncodeToString(privkey))
372 vkey = fmt.Sprintf("%s+%08x+%s", name, h, base64.StdEncoding.EncodeToString(pubkey))
373 return skey, vkey, nil
374 }
375
376
377
378 func NewEd25519VerifierKey(name string, key ed25519.PublicKey) (string, error) {
379 if len(key) != ed25519.PublicKeySize {
380 return "", fmt.Errorf("invalid public key size %d, expected %d", len(key), ed25519.PublicKeySize)
381 }
382
383 pubkey := append([]byte{algEd25519}, key...)
384 hash := keyHash(name, pubkey)
385
386 b64Key := base64.StdEncoding.EncodeToString(pubkey)
387 return fmt.Sprintf("%s+%08x+%s", name, hash, b64Key), nil
388 }
389
390
391 type Verifiers interface {
392
393
394
395
396 Verifier(name string, hash uint32) (Verifier, error)
397 }
398
399
400
401
402 type UnknownVerifierError struct {
403 Name string
404 KeyHash uint32
405 }
406
407 func (e *UnknownVerifierError) Error() string {
408 return fmt.Sprintf("unknown key %s+%08x", e.Name, e.KeyHash)
409 }
410
411
412
413
414
415
416 type ambiguousVerifierError struct {
417 name string
418 hash uint32
419 }
420
421 func (e *ambiguousVerifierError) Error() string {
422 return fmt.Sprintf("ambiguous key %s+%08x", e.name, e.hash)
423 }
424
425
426 func VerifierList(list ...Verifier) Verifiers {
427 m := make(verifierMap)
428 for _, v := range list {
429 k := nameHash{v.Name(), v.KeyHash()}
430 m[k] = append(m[k], v)
431 }
432 return m
433 }
434
435 type nameHash struct {
436 name string
437 hash uint32
438 }
439
440 type verifierMap map[nameHash][]Verifier
441
442 func (m verifierMap) Verifier(name string, hash uint32) (Verifier, error) {
443 v, ok := m[nameHash{name, hash}]
444 if !ok {
445 return nil, &UnknownVerifierError{name, hash}
446 }
447 if len(v) > 1 {
448 return nil, &ambiguousVerifierError{name, hash}
449 }
450 return v[0], nil
451 }
452
453
454 type Note struct {
455 Text string
456 Sigs []Signature
457 UnverifiedSigs []Signature
458 }
459
460
461 type Signature struct {
462
463
464 Name string
465 Hash uint32
466
467
468 Base64 string
469 }
470
471
472
473 type UnverifiedNoteError struct {
474 Note *Note
475 }
476
477 func (e *UnverifiedNoteError) Error() string {
478 return "note has no verifiable signatures"
479 }
480
481
482
483 type InvalidSignatureError struct {
484 Name string
485 Hash uint32
486 }
487
488 func (e *InvalidSignatureError) Error() string {
489 return fmt.Sprintf("invalid signature for key %s+%08x", e.Name, e.Hash)
490 }
491
492 var (
493 errMalformedNote = errors.New("malformed note")
494 errInvalidSigner = errors.New("invalid signer")
495 errMismatchedVerifier = errors.New("verifier name or hash doesn't match signature")
496
497 sigSplit = []byte("\n\n")
498 sigPrefix = []byte("— ")
499 )
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515 func Open(msg []byte, known Verifiers) (*Note, error) {
516 if known == nil {
517
518 known = VerifierList()
519 }
520
521
522 for i := 0; i < len(msg); {
523 r, size := utf8.DecodeRune(msg[i:])
524 if r < 0x20 && r != '\n' || r == utf8.RuneError && size == 1 {
525 return nil, errMalformedNote
526 }
527 i += size
528 }
529
530
531 split := bytes.LastIndex(msg, sigSplit)
532 if split < 0 {
533 return nil, errMalformedNote
534 }
535 text, sigs := msg[:split+1], msg[split+2:]
536 if len(sigs) == 0 || sigs[len(sigs)-1] != '\n' {
537 return nil, errMalformedNote
538 }
539
540 n := &Note{
541 Text: string(text),
542 }
543
544
545
546 seen := make(map[nameHash]bool)
547 seenUnverified := make(map[string]bool)
548 numSig := 0
549 for len(sigs) > 0 {
550
551
552 i := bytes.IndexByte(sigs, '\n')
553 line := sigs[:i]
554 sigs = sigs[i+1:]
555
556 if !bytes.HasPrefix(line, sigPrefix) {
557 return nil, errMalformedNote
558 }
559 line = line[len(sigPrefix):]
560 name, b64 := chop(string(line), " ")
561 sig, err := base64.StdEncoding.DecodeString(b64)
562 if err != nil || !isValidName(name) || b64 == "" || len(sig) < 5 {
563 return nil, errMalformedNote
564 }
565 hash := binary.BigEndian.Uint32(sig[0:4])
566 sig = sig[4:]
567
568 if numSig++; numSig > 100 {
569
570 return nil, errMalformedNote
571 }
572
573 v, err := known.Verifier(name, hash)
574 if _, ok := err.(*UnknownVerifierError); ok {
575
576 if seenUnverified[string(line)] {
577 continue
578 }
579 seenUnverified[string(line)] = true
580 n.UnverifiedSigs = append(n.UnverifiedSigs, Signature{Name: name, Hash: hash, Base64: b64})
581 continue
582 }
583 if err != nil {
584 return nil, err
585 }
586
587
588 if v.Name() != name || v.KeyHash() != hash {
589 return nil, errMismatchedVerifier
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