Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zpay32: Fix broken last tagged field #3767

Merged
merged 3 commits into from
Dec 5, 2019

Conversation

matheusd
Copy link
Contributor

This fixes an issue with bech32 decoding where inserting a specific character in the checksum might generate a valid signature albeit with a different destination node than the original invoice.

This fixes the issue by ensuring that the last tagged field has all the required data instead of silently discarding a partial field, such as a field with only a type element but no length elements.

I tested this behavior in other implementations. c-lightning and lightning-payencode (python) fail to decode invoices with a partial field. Bolt11 (node) accepts it.

This should probably be clarified in BOLT-11 so that the behavior is consistent across implementations.

For context: sipa/bech32#51

This switches the applicable error to use an exported sentinel error so
that it is more testable.
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 adds tests for checksum malleability issue of bech32 strings as
used by LN invoices.
Copy link
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent PR! LGTM 👍

It's an interesting observation, that the signature can be changed this way while keeping the invoice valid. We could start adding the tagged field for pubkey by default to mitigate, but if someone can modify an invoice like this to change the destination, they probably can also just resign the invoice.

@matheusd
Copy link
Contributor Author

We could start adding the tagged field for pubkey by default to mitigate

Other options (but these involves changing BOLT-11) would be to include the length of tagged data as a prefixed field (along with the timestamp) or as a new tagged field. These have the advantage of being smaller than the pubkey.

if someone can modify an invoice like this to change the destination, they probably can also just resign the invoice.

Indeed.

Copy link
Contributor

@cfromknecht cfromknecht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matheusd nice work! one small comment on the checksum unit test

zpay32/invoice_test.go Show resolved Hide resolved
@halseth halseth merged commit 509d0fb into lightningnetwork:master Dec 5, 2019
@matheusd matheusd deleted the fix-zpay32 branch December 13, 2019 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants