From 409cf5565511ee9600b74f9966ed4e8e1762dab4 Mon Sep 17 00:00:00 2001 From: Matheus Degiovani Date: Mon, 25 Nov 2019 18:52:31 -0300 Subject: [PATCH] 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. --- zpay32/invoice.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zpay32/invoice.go b/zpay32/invoice.go index 9a9fde33..83370737 100644 --- a/zpay32/invoice.go +++ b/zpay32/invoice.go @@ -90,6 +90,10 @@ var ( // ErrInvalidFieldLength is returned when a tagged field was specified // with a length larger than the left over bytes of the data field. 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 @@ -604,12 +608,14 @@ func parseTimestamp(data []byte) (uint64, error) { // fills the Invoice struct accordingly. func parseTaggedFields(invoice *Invoice, fields []byte, net *chaincfg.Params) error { index := 0 - for { + for len(fields)-index > 0 { // If there are less than 3 groups to read, there cannot be more // interesting information, as we need the type (1 group) and // length (2 groups). + // + // This means the last tagged field is broken. if len(fields)-index < 3 { - break + return ErrBrokenTaggedField } typ := fields[index]