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, _ := strings.Cut(vkey, "+")
244 hash16, key64, _ := strings.Cut(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 type verifier struct {
278 name string
279 hash uint32
280 verify func([]byte, []byte) bool
281 }
282
283 func (v *verifier) Name() string { return v.name }
284 func (v *verifier) KeyHash() uint32 { return v.hash }
285 func (v *verifier) Verify(msg, sig []byte) bool { return v.verify(msg, sig) }
286
287
288 func NewSigner(skey string) (Signer, error) {
289 priv1, skey, _ := strings.Cut(skey, "+")
290 priv2, skey, _ := strings.Cut(skey, "+")
291 name, skey, _ := strings.Cut(skey, "+")
292 hash16, key64, _ := strings.Cut(skey, "+")
293 hash, err1 := strconv.ParseUint(hash16, 16, 32)
294 key, err2 := base64.StdEncoding.DecodeString(key64)
295 if priv1 != "PRIVATE" || priv2 != "KEY" || len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
296 return nil, errSignerID
297 }
298
299
300
301
302 s := &signer{
303 name: name,
304 hash: uint32(hash),
305 }
306
307 var pubkey []byte
308
309 alg, key := key[0], key[1:]
310 switch alg {
311 default:
312 return nil, errSignerAlg
313
314 case algEd25519:
315 if len(key) != 32 {
316 return nil, errSignerID
317 }
318 key = ed25519.NewKeyFromSeed(key)
319 pubkey = append([]byte{algEd25519}, key[32:]...)
320 s.sign = func(msg []byte) ([]byte, error) {
321 return ed25519.Sign(key, msg), nil
322 }
323 }
324
325 if uint32(hash) != keyHash(name, pubkey) {
326 return nil, errSignerHash
327 }
328
329 return s, nil
330 }
331
332 var (
333 errSignerID = errors.New("malformed verifier id")
334 errSignerAlg = errors.New("unknown verifier algorithm")
335 errSignerHash = errors.New("invalid verifier hash")
336 )
337
338
339 type signer struct {
340 name string
341 hash uint32
342 sign func([]byte) ([]byte, error)
343 }
344
345 func (s *signer) Name() string { return s.name }
346 func (s *signer) KeyHash() uint32 { return s.hash }
347 func (s *signer) Sign(msg []byte) ([]byte, error) { return s.sign(msg) }
348
349
350
351 func GenerateKey(rand io.Reader, name string) (skey, vkey string, err error) {
352 pub, priv, err := ed25519.GenerateKey(rand)
353 if err != nil {
354 return "", "", err
355 }
356 pubkey := append([]byte{algEd25519}, pub...)
357 privkey := append([]byte{algEd25519}, priv.Seed()...)
358 h := keyHash(name, pubkey)
359
360 skey = fmt.Sprintf("PRIVATE+KEY+%s+%08x+%s", name, h, base64.StdEncoding.EncodeToString(privkey))
361 vkey = fmt.Sprintf("%s+%08x+%s", name, h, base64.StdEncoding.EncodeToString(pubkey))
362 return skey, vkey, nil
363 }
364
365
366
367 func NewEd25519VerifierKey(name string, key ed25519.PublicKey) (string, error) {
368 if len(key) != ed25519.PublicKeySize {
369 return "", fmt.Errorf("invalid public key size %d, expected %d", len(key), ed25519.PublicKeySize)
370 }
371
372 pubkey := append([]byte{algEd25519}, key...)
373 hash := keyHash(name, pubkey)
374
375 b64Key := base64.StdEncoding.EncodeToString(pubkey)
376 return fmt.Sprintf("%s+%08x+%s", name, hash, b64Key), nil
377 }
378
379
380 type Verifiers interface {
381
382
383
384
385 Verifier(name string, hash uint32) (Verifier, error)
386 }
387
388
389
390
391 type UnknownVerifierError struct {
392 Name string
393 KeyHash uint32
394 }
395
396 func (e *UnknownVerifierError) Error() string {
397 return fmt.Sprintf("unknown key %s+%08x", e.Name, e.KeyHash)
398 }
399
400
401
402
403
404
405 type ambiguousVerifierError struct {
406 name string
407 hash uint32
408 }
409
410 func (e *ambiguousVerifierError) Error() string {
411 return fmt.Sprintf("ambiguous key %s+%08x", e.name, e.hash)
412 }
413
414
415 func VerifierList(list ...Verifier) Verifiers {
416 m := make(verifierMap)
417 for _, v := range list {
418 k := nameHash{v.Name(), v.KeyHash()}
419 m[k] = append(m[k], v)
420 }
421 return m
422 }
423
424 type nameHash struct {
425 name string
426 hash uint32
427 }
428
429 type verifierMap map[nameHash][]Verifier
430
431 func (m verifierMap) Verifier(name string, hash uint32) (Verifier, error) {
432 v, ok := m[nameHash{name, hash}]
433 if !ok {
434 return nil, &UnknownVerifierError{name, hash}
435 }
436 if len(v) > 1 {
437 return nil, &ambiguousVerifierError{name, hash}
438 }
439 return v[0], nil
440 }
441
442
443 type Note struct {
444 Text string
445 Sigs []Signature
446 UnverifiedSigs []Signature
447 }
448
449
450 type Signature struct {
451
452
453 Name string
454 Hash uint32
455
456
457 Base64 string
458 }
459
460
461
462 type UnverifiedNoteError struct {
463 Note *Note
464 }
465
466 func (e *UnverifiedNoteError) Error() string {
467 return "note has no verifiable signatures"
468 }
469
470
471
472 type InvalidSignatureError struct {
473 Name string
474 Hash uint32
475 }
476
477 func (e *InvalidSignatureError) Error() string {
478 return fmt.Sprintf("invalid signature for key %s+%08x", e.Name, e.Hash)
479 }
480
481 var (
482 errMalformedNote = errors.New("malformed note")
483 errInvalidSigner = errors.New("invalid signer")
484 errMismatchedVerifier = errors.New("verifier name or hash doesn't match signature")
485
486 sigSplit = []byte("\n\n")
487 sigPrefix = []byte("— ")
488 )
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504 func Open(msg []byte, known Verifiers) (*Note, error) {
505 if known == nil {
506
507 known = VerifierList()
508 }
509
510
511 for i := 0; i < len(msg); {
512 r, size := utf8.DecodeRune(msg[i:])
513 if r < 0x20 && r != '\n' || r == utf8.RuneError && size == 1 {
514 return nil, errMalformedNote
515 }
516 i += size
517 }
518
519
520 split := bytes.LastIndex(msg, sigSplit)
521 if split < 0 {
522 return nil, errMalformedNote
523 }
524 text, sigs := msg[:split+1], msg[split+2:]
525 if len(sigs) == 0 || sigs[len(sigs)-1] != '\n' {
526 return nil, errMalformedNote
527 }
528
529 n := &Note{
530 Text: string(text),
531 }
532
533
534
535 seen := make(map[nameHash]bool)
536 seenUnverified := make(map[string]bool)
537 numSig := 0
538 for len(sigs) > 0 {
539
540
541 i := bytes.IndexByte(sigs, '\n')
542 line := sigs[:i]
543 sigs = sigs[i+1:]
544
545 if !bytes.HasPrefix(line, sigPrefix) {
546 return nil, errMalformedNote
547 }
548 line = line[len(sigPrefix):]
549 name, b64, _ := strings.Cut(string(line), " ")
550 sig, err := base64.StdEncoding.DecodeString(b64)
551 if err != nil || !isValidName(name) || b64 == "" || len(sig) < 5 {
552 return nil, errMalformedNote
553 }
554 hash := binary.BigEndian.Uint32(sig[0:4])
555 sig = sig[4:]
556
557 if numSig++; numSig > 100 {
558
559 return nil, errMalformedNote
560 }
561
562 v, err := known.Verifier(name, hash)
563 if _, ok := err.(*UnknownVerifierError); ok {
564
565 if seenUnverified[string(line)] {
566 continue
567 }
568 seenUnverified[string(line)] = true
569 n.UnverifiedSigs = append(n.UnverifiedSigs, Signature{Name: name, Hash: hash, Base64: b64})
570 continue
571 }
572 if err != nil {
573 return nil, err
574 }
575
576
577 if v.Name() != name || v.KeyHash() != hash {
578 return nil, errMismatchedVerifier
579 }
580
581
582 if seen[nameHash{name, hash}] {
583 continue
584 }
585 seen[nameHash{name, hash}] = true
586
587 ok := v.Verify(text, sig)
588 if !ok {
589 return nil, &InvalidSignatureError{name, hash}
590 }
591
592 n.Sigs = append(n.Sigs, Signature{Name: name, Hash: hash, Base64: b64})
593 }
594
595
596 if len(n.Sigs) == 0 {
597 return nil, &UnverifiedNoteError{n}
598 }
599 return n, nil
600 }
601
602
603
604
605
606
607 func Sign(n *Note, signers ...Signer) ([]byte, error) {
608 var buf bytes.Buffer
609 if !strings.HasSuffix(n.Text, "\n") {
610 return nil, errMalformedNote
611 }
612 buf.WriteString(n.Text)
613
614
615 var sigs bytes.Buffer
616 have := make(map[nameHash]bool)
617 for _, s := range signers {
618 name := s.Name()
619 hash := s.KeyHash()
620 have[nameHash{name, hash}] = true
621 if !isValidName(name) {
622 return nil, errInvalidSigner
623 }
624
625 sig, err := s.Sign(buf.Bytes())
626 if err != nil {
627 return nil, err
628 }
629
630 var hbuf [4]byte
631 binary.BigEndian.PutUint32(hbuf[:], hash)
632 b64 := base64.StdEncoding.EncodeToString(append(hbuf[:], sig...))
633 sigs.WriteString("— ")
634 sigs.WriteString(name)
635 sigs.WriteString(" ")
636 sigs.WriteString(b64)
637 sigs.WriteString("\n")
638 }
639
640 buf.WriteString("\n")
641
642
643 for _, list := range [][]Signature{n.Sigs, n.UnverifiedSigs} {
644 for _, sig := range list {
645 name, hash := sig.Name, sig.Hash
646 if !isValidName(name) {
647 return nil, errMalformedNote
648 }
649 if have[nameHash{name, hash}] {
650 continue
651 }
652
653 raw, err := base64.StdEncoding.DecodeString(sig.Base64)
654 if err != nil || len(raw) < 4 || binary.BigEndian.Uint32(raw) != hash {
655 return nil, errMalformedNote
656 }
657 buf.WriteString("— ")
658 buf.WriteString(sig.Name)
659 buf.WriteString(" ")
660 buf.WriteString(sig.Base64)
661 buf.WriteString("\n")
662 }
663 }
664 buf.Write(sigs.Bytes())
665
666 return buf.Bytes(), nil
667 }
668
View as plain text