func Sign()

in sumdb/note/note.go [618:678]


func Sign(n *Note, signers ...Signer) ([]byte, error) {
	var buf bytes.Buffer
	if !strings.HasSuffix(n.Text, "\n") {
		return nil, errMalformedNote
	}
	buf.WriteString(n.Text)

	// Prepare signatures.
	var sigs bytes.Buffer
	have := make(map[nameHash]bool)
	for _, s := range signers {
		name := s.Name()
		hash := s.KeyHash()
		have[nameHash{name, hash}] = true
		if !isValidName(name) {
			return nil, errInvalidSigner
		}

		sig, err := s.Sign(buf.Bytes()) // buf holds n.Text
		if err != nil {
			return nil, err
		}

		var hbuf [4]byte
		binary.BigEndian.PutUint32(hbuf[:], hash)
		b64 := base64.StdEncoding.EncodeToString(append(hbuf[:], sig...))
		sigs.WriteString("— ")
		sigs.WriteString(name)
		sigs.WriteString(" ")
		sigs.WriteString(b64)
		sigs.WriteString("\n")
	}

	buf.WriteString("\n")

	// Emit existing signatures not replaced by new ones.
	for _, list := range [][]Signature{n.Sigs, n.UnverifiedSigs} {
		for _, sig := range list {
			name, hash := sig.Name, sig.Hash
			if !isValidName(name) {
				return nil, errMalformedNote
			}
			if have[nameHash{name, hash}] {
				continue
			}
			// Double-check hash against base64.
			raw, err := base64.StdEncoding.DecodeString(sig.Base64)
			if err != nil || len(raw) < 4 || binary.BigEndian.Uint32(raw) != hash {
				return nil, errMalformedNote
			}
			buf.WriteString("— ")
			buf.WriteString(sig.Name)
			buf.WriteString(" ")
			buf.WriteString(sig.Base64)
			buf.WriteString("\n")
		}
	}
	buf.Write(sigs.Bytes())

	return buf.Bytes(), nil
}