zpay32: Fix broken last tagged field

This fixes an issue where the last tagged field of an invoice could get
broken due to the malleability of bech32 checksums.

The addition of a specific character in the second to last position of
the checksum could cause the previous signature field to mutate and thus
point to a different public node.
This commit is contained in:
Matheus Degiovani 2019-11-25 18:52:31 -03:00
parent 85f9c03797
commit 409cf55655

@ -90,6 +90,10 @@ var (
// ErrInvalidFieldLength is returned when a tagged field was specified // ErrInvalidFieldLength is returned when a tagged field was specified
// with a length larger than the left over bytes of the data field. // with a length larger than the left over bytes of the data field.
ErrInvalidFieldLength = errors.New("invalid field length") ErrInvalidFieldLength = errors.New("invalid field length")
// ErrBrokenTaggedField is returned when the last tagged field is
// incorrectly formatted and doesn't have enough bytes to be read.
ErrBrokenTaggedField = errors.New("last tagged field is broken")
) )
// MessageSigner is passed to the Encode method to provide a signature // MessageSigner is passed to the Encode method to provide a signature
@ -604,12 +608,14 @@ func parseTimestamp(data []byte) (uint64, error) {
// fills the Invoice struct accordingly. // fills the Invoice struct accordingly.
func parseTaggedFields(invoice *Invoice, fields []byte, net *chaincfg.Params) error { func parseTaggedFields(invoice *Invoice, fields []byte, net *chaincfg.Params) error {
index := 0 index := 0
for { for len(fields)-index > 0 {
// If there are less than 3 groups to read, there cannot be more // If there are less than 3 groups to read, there cannot be more
// interesting information, as we need the type (1 group) and // interesting information, as we need the type (1 group) and
// length (2 groups). // length (2 groups).
//
// This means the last tagged field is broken.
if len(fields)-index < 3 { if len(fields)-index < 3 {
break return ErrBrokenTaggedField
} }
typ := fields[index] typ := fields[index]