Skip to content

Commit 9e91b2e

Browse files
authored
Merge pull request #4349 from vincenzopalazzo/macros/bolt12-invalid-padding-test-vector
BOLT 12: Validate bech32 padding per BIP-173
2 parents 3fee76b + cea1c72 commit 9e91b2e

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

lightning/src/offers/offer.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,5 +2528,12 @@ mod bolt12_tests {
25282528
"lno1pgx9getnwss8vetrw3hhyucsespjgef743p5fzqq9nqxh0ah7y87rzv3ud0eleps9kl2d5348hq2k8qzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgqpqqqqqqqqqqqqqqqqqqqqqqqqqqqzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqqzq3zyg3zyg3zygszqqqqyqqqqsqqvpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsq".parse::<Offer>(),
25292529
Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)),
25302530
);
2531+
2532+
// Bech32 padding exceeds 4-bit limit (BOLT 12 test vector)
2533+
// See: https://github.com/lightning/bolts/pull/1312
2534+
assert!(matches!(
2535+
"lno1zcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pkseseq".parse::<Offer>(),
2536+
Err(Bolt12ParseError::InvalidPadding(_))
2537+
));
25312538
}
25322539
}

lightning/src/offers/parse.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use crate::io;
1313
use crate::ln::msgs::DecodeError;
1414
use crate::util::ser::CursorReadable;
15-
use bech32::primitives::decode::CheckedHrpstringError;
15+
use bech32::primitives::decode::{CheckedHrpstringError, PaddingError};
1616
use bitcoin::secp256k1;
1717

1818
#[allow(unused_imports)]
@@ -76,6 +76,10 @@ mod sealed {
7676
return Err(Bolt12ParseError::InvalidBech32Hrp);
7777
}
7878

79+
// Validate that bech32 padding is valid per BIP-173:
80+
// "Any incomplete group at the end MUST be 4 bits or less, MUST be all zeroes"
81+
parsed.validate_segwit_padding()?;
82+
7983
let data = parsed.byte_iter().collect::<Vec<u8>>();
8084
Self::try_from(data)
8185
}
@@ -146,6 +150,11 @@ pub enum Bolt12ParseError {
146150
/// This is not exported to bindings users as the details don't matter much
147151
CheckedHrpstringError,
148152
),
153+
/// The bech32 data has invalid padding per BIP-173 (more than 4 bits or non-zero padding).
154+
InvalidPadding(
155+
/// This is not exported to bindings users as the details don't matter much
156+
PaddingError,
157+
),
149158
/// The bech32 decoded string could not be decoded as the expected message type.
150159
Decode(DecodeError),
151160
/// The parsed message has invalid semantics.
@@ -232,6 +241,12 @@ impl From<CheckedHrpstringError> for Bolt12ParseError {
232241
}
233242
}
234243

244+
impl From<PaddingError> for Bolt12ParseError {
245+
fn from(error: PaddingError) -> Self {
246+
Self::InvalidPadding(error)
247+
}
248+
}
249+
235250
impl From<DecodeError> for Bolt12ParseError {
236251
fn from(error: DecodeError) -> Self {
237252
Self::Decode(error)
@@ -326,7 +341,7 @@ mod bolt12_tests {
326341

327342
#[cfg(test)]
328343
mod tests {
329-
use super::Bolt12ParseError;
344+
use super::{Bolt12ParseError, PaddingError};
330345
use crate::ln::msgs::DecodeError;
331346
use crate::offers::offer::Offer;
332347
use bech32::primitives::decode::{CharError, CheckedHrpstringError, UncheckedHrpstringError};
@@ -371,4 +386,15 @@ mod tests {
371386
Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
372387
}
373388
}
389+
390+
#[test]
391+
fn fails_parsing_bech32_encoded_offer_with_invalid_padding() {
392+
// BOLT 12 test vector for invalid bech32 padding
393+
// See: https://github.com/lightning/bolts/pull/1312
394+
let encoded_offer = "lno1zcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pkseseq";
395+
match encoded_offer.parse::<Offer>() {
396+
Ok(_) => panic!("Valid offer: {}", encoded_offer),
397+
Err(e) => assert_eq!(e, Bolt12ParseError::InvalidPadding(PaddingError::TooMuch)),
398+
}
399+
}
374400
}

0 commit comments

Comments
 (0)