...

Source file src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go

Documentation: cmd/vendor/golang.org/x/mod/sumdb/note

     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.
     4  
     5  // Package note defines the notes signed by the Go module database server.
     6  //
     7  // A note is text signed by one or more server keys.
     8  // The text should be ignored unless the note is signed by
     9  // a trusted server key and the signature has been verified
    10  // using the server's public key.
    11  //
    12  // A server's public key is identified by a name, typically the "host[/path]"
    13  // giving the base URL of the server's transparency log.
    14  // The syntactic restrictions on a name are that it be non-empty,
    15  // well-formed UTF-8 containing neither Unicode spaces nor plus (U+002B).
    16  //
    17  // A Go module database server signs texts using public key cryptography.
    18  // A given server may have multiple public keys, each
    19  // identified by a 32-bit hash of the public key.
    20  //
    21  // # Verifying Notes
    22  //
    23  // A [Verifier] allows verification of signatures by one server public key.
    24  // It can report the name of the server and the uint32 hash of the key,
    25  // and it can verify a purported signature by that key.
    26  //
    27  // The standard implementation of a Verifier is constructed
    28  // by [NewVerifier] starting from a verifier key, which is a
    29  // plain text string of the form "<name>+<hash>+<keydata>".
    30  //
    31  // A [Verifiers] allows looking up a Verifier by the combination
    32  // of server name and key hash.
    33  //
    34  // The standard implementation of a Verifiers is constructed
    35  // by VerifierList from a list of known verifiers.
    36  //
    37  // A [Note] represents a text with one or more signatures.
    38  // An implementation can reject a note with too many signatures
    39  // (for example, more than 100 signatures).
    40  //
    41  // A [Signature] represents a signature on a note, verified or not.
    42  //
    43  // The [Open] function takes as input a signed message
    44  // and a set of known verifiers. It decodes and verifies
    45  // the message signatures and returns a [Note] structure
    46  // containing the message text and (verified or unverified) signatures.
    47  //
    48  // # Signing Notes
    49  //
    50  // A [Signer] allows signing a text with a given key.
    51  // It can report the name of the server and the hash of the key
    52  // and can sign a raw text using that key.
    53  //
    54  // The standard implementation of a Signer is constructed
    55  // by [NewSigner] starting from an encoded signer key, which is a
    56  // plain text string of the form "PRIVATE+KEY+<name>+<hash>+<keydata>".
    57  // Anyone with an encoded signer key can sign messages using that key,
    58  // so it must be kept secret. The encoding begins with the literal text
    59  // "PRIVATE+KEY" to avoid confusion with the public server key.
    60  //
    61  // The [Sign] function takes as input a Note and a list of Signers
    62  // and returns an encoded, signed message.
    63  //
    64  // # Signed Note Format
    65  //
    66  // A signed note consists of a text ending in newline (U+000A),
    67  // followed by a blank line (only a newline),
    68  // followed by one or more signature lines of this form:
    69  // em dash (U+2014), space (U+0020),
    70  // server name, space, base64-encoded signature, newline.
    71  //
    72  // Signed notes must be valid UTF-8 and must not contain any
    73  // ASCII control characters (those below U+0020) other than newline.
    74  //
    75  // A signature is a base64 encoding of 4+n bytes.
    76  //
    77  // The first four bytes in the signature are the uint32 key hash
    78  // stored in big-endian order.
    79  //
    80  // The remaining n bytes are the result of using the specified key
    81  // to sign the note text (including the final newline but not the
    82  // separating blank line).
    83  //
    84  // # Generating Keys
    85  //
    86  // There is only one key type, Ed25519 with algorithm identifier 1.
    87  // New key types may be introduced in the future as needed,
    88  // although doing so will require deploying the new algorithms to all clients
    89  // before starting to depend on them for signatures.
    90  //
    91  // The [GenerateKey] function generates and returns a new signer
    92  // and corresponding verifier.
    93  //
    94  // # Example
    95  //
    96  // Here is a well-formed signed note:
    97  //
    98  //	If you think cryptography is the answer to your problem,
    99  //	then you don't know what your problem is.
   100  //
   101  //	— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
   102  //
   103  // It can be constructed and displayed using:
   104  //
   105  //	skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
   106  //	text := "If you think cryptography is the answer to your problem,\n" +
   107  //		"then you don't know what your problem is.\n"
   108  //
   109  //	signer, err := note.NewSigner(skey)
   110  //	if err != nil {
   111  //		log.Fatal(err)
   112  //	}
   113  //
   114  //	msg, err := note.Sign(&note.Note{Text: text}, signer)
   115  //	if err != nil {
   116  //		log.Fatal(err)
   117  //	}
   118  //	os.Stdout.Write(msg)
   119  //
   120  // The note's text is two lines, including the final newline,
   121  // and the text is purportedly signed by a server named
   122  // "PeterNeumann". (Although server names are canonically
   123  // base URLs, the only syntactic requirement is that they
   124  // not contain spaces or newlines).
   125  //
   126  // If [Open] is given access to a [Verifiers] including the
   127  // [Verifier] for this key, then it will succeed at verifying
   128  // the encoded message and returning the parsed [Note]:
   129  //
   130  //	vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
   131  //	msg := []byte("If you think cryptography is the answer to your problem,\n" +
   132  //		"then you don't know what your problem is.\n" +
   133  //		"\n" +
   134  //		"— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n")
   135  //
   136  //	verifier, err := note.NewVerifier(vkey)
   137  //	if err != nil {
   138  //		log.Fatal(err)
   139  //	}
   140  //	verifiers := note.VerifierList(verifier)
   141  //
   142  //	n, err := note.Open([]byte(msg), verifiers)
   143  //	if err != nil {
   144  //		log.Fatal(err)
   145  //	}
   146  //	fmt.Printf("%s (%08x):\n%s", n.Sigs[0].Name, n.Sigs[0].Hash, n.Text)
   147  //
   148  // You can add your own signature to this message by re-signing the note:
   149  //
   150  //	skey, vkey, err := note.GenerateKey(rand.Reader, "EnochRoot")
   151  //	if err != nil {
   152  //		log.Fatal(err)
   153  //	}
   154  //	_ = vkey // give to verifiers
   155  //
   156  //	me, err := note.NewSigner(skey)
   157  //	if err != nil {
   158  //		log.Fatal(err)
   159  //	}
   160  //
   161  //	msg, err := note.Sign(n, me)
   162  //	if err != nil {
   163  //		log.Fatal(err)
   164  //	}
   165  //	os.Stdout.Write(msg)
   166  //
   167  // This will print a doubly-signed message, like:
   168  //
   169  //	If you think cryptography is the answer to your problem,
   170  //	then you don't know what your problem is.
   171  //
   172  //	— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
   173  //	— EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=
   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  // A Verifier verifies messages signed with a specific key.
   192  type Verifier interface {
   193  	// Name returns the server name associated with the key.
   194  	Name() string
   195  
   196  	// KeyHash returns the key hash.
   197  	KeyHash() uint32
   198  
   199  	// Verify reports whether sig is a valid signature of msg.
   200  	Verify(msg, sig []byte) bool
   201  }
   202  
   203  // A Signer signs messages using a specific key.
   204  type Signer interface {
   205  	// Name returns the server name associated with the key.
   206  	Name() string
   207  
   208  	// KeyHash returns the key hash.
   209  	KeyHash() uint32
   210  
   211  	// Sign returns a signature for the given message.
   212  	Sign(msg []byte) ([]byte, error)
   213  }
   214  
   215  // keyHash computes the key hash for the given server name and encoded public key.
   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  // isValidName reports whether name is valid.
   236  // It must be non-empty and not have any Unicode spaces or pluses.
   237  func isValidName(name string) bool {
   238  	return name != "" && utf8.ValidString(name) && strings.IndexFunc(name, unicode.IsSpace) < 0 && !strings.Contains(name, "+")
   239  }
   240  
   241  // NewVerifier construct a new [Verifier] from an encoded verifier key.
   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  // chop chops s at the first instance of sep, if any,
   277  // and returns the text before and after sep.
   278  // If sep is not present, chop returns before is s and after is empty.
   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  // verifier is a trivial Verifier implementation.
   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  // NewSigner constructs a new [Signer] from an encoded signer key.
   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  	// Note: hash is the hash of the public key and we have the private key.
   311  	// Must verify hash after deriving public key.
   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  // signer is a trivial Signer implementation.
   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  // GenerateKey generates a signer and verifier key pair for a named server.
   361  // The signer key skey is private and must be kept secret.
   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  // NewEd25519VerifierKey returns an encoded verifier key using the given name
   377  // and Ed25519 public key.
   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  // A Verifiers is a collection of known verifier keys.
   391  type Verifiers interface {
   392  	// Verifier returns the Verifier associated with the key
   393  	// identified by the name and hash.
   394  	// If the name, hash pair is unknown, Verifier should return
   395  	// an UnknownVerifierError.
   396  	Verifier(name string, hash uint32) (Verifier, error)
   397  }
   398  
   399  // An UnknownVerifierError indicates that the given key is not known.
   400  // The Open function records signatures without associated verifiers as
   401  // unverified signatures.
   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  // An ambiguousVerifierError indicates that the given name and hash
   412  // match multiple keys passed to [VerifierList].
   413  // (If this happens, some malicious actor has taken control of the
   414  // verifier list, at which point we may as well give up entirely,
   415  // but we diagnose the problem instead.)
   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  // VerifierList returns a [Verifiers] implementation that uses the given list of verifiers.
   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  // A Note is a text and signatures.
   454  type Note struct {
   455  	Text           string      // text of note
   456  	Sigs           []Signature // verified signatures
   457  	UnverifiedSigs []Signature // unverified signatures
   458  }
   459  
   460  // A Signature is a single signature found in a note.
   461  type Signature struct {
   462  	// Name and Hash give the name and key hash
   463  	// for the key that generated the signature.
   464  	Name string
   465  	Hash uint32
   466  
   467  	// Base64 records the base64-encoded signature bytes.
   468  	Base64 string
   469  }
   470  
   471  // An UnverifiedNoteError indicates that the note
   472  // successfully parsed but had no verifiable signatures.
   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  // An InvalidSignatureError indicates that the given key was known
   482  // and the associated Verifier rejected the signature.
   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  // Open opens and parses the message msg, checking signatures from the known verifiers.
   502  //
   503  // For each signature in the message, Open calls known.Verifier to find a verifier.
   504  // If known.Verifier returns a verifier and the verifier accepts the signature,
   505  // Open records the signature in the returned note's Sigs field.
   506  // If known.Verifier returns a verifier but the verifier rejects the signature,
   507  // Open returns an InvalidSignatureError.
   508  // If known.Verifier returns an UnknownVerifierError,
   509  // Open records the signature in the returned note's UnverifiedSigs field.
   510  // If known.Verifier returns any other error, Open returns that error.
   511  //
   512  // If no known verifier has signed an otherwise valid note,
   513  // Open returns an [UnverifiedNoteError].
   514  // In this case, the unverified note can be fetched from inside the error.
   515  func Open(msg []byte, known Verifiers) (*Note, error) {
   516  	if known == nil {
   517  		// Treat nil Verifiers as empty list, to produce useful error instead of crash.
   518  		known = VerifierList()
   519  	}
   520  
   521  	// Must have valid UTF-8 with no non-newline ASCII control characters.
   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  	// Must end with signature block preceded by blank line.
   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  	// Parse and verify signatures.
   545  	// Ignore duplicate signatures.
   546  	seen := make(map[nameHash]bool)
   547  	seenUnverified := make(map[string]bool)
   548  	numSig := 0
   549  	for len(sigs) > 0 {
   550  		// Pull out next signature line.
   551  		// We know sigs[len(sigs)-1] == '\n', so IndexByte always finds one.
   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  			// Avoid spending forever parsing a note with many signatures.
   570  			return nil, errMalformedNote
   571  		}
   572  
   573  		v, err := known.Verifier(name, hash)
   574  		if _, ok := err.(*UnknownVerifierError); ok {
   575  			// Drop repeated identical unverified signatures.
   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  		// Check that known.Verifier returned the right verifier.
   588  		if v.Name() != name || v.KeyHash() != hash {
   589  			return nil, errMismatchedVerifier
   590  		}
   591  
   592  		// Drop repeated signatures by a single verifier.
   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  	// Parsed and verified all the signatures.
   607  	if len(n.Sigs) == 0 {
   608  		return nil, &UnverifiedNoteError{n}
   609  	}
   610  	return n, nil
   611  }
   612  
   613  // Sign signs the note with the given signers and returns the encoded message.
   614  // The new signatures from signers are listed in the encoded message after
   615  // the existing signatures already present in n.Sigs.
   616  // If any signer uses the same key as an existing signature,
   617  // the existing signature is elided from the output.
   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  	// Prepare signatures.
   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()) // buf holds n.Text
   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  	// Emit existing signatures not replaced by new ones.
   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  			// Double-check hash against base64.
   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