Skip to content

Commit 40b7284

Browse files
committed
Add OffersContext::InvoiceRequest
To authenticate that an InvoiceRequest is for a valid Offer, include the nonce from the Offer::metadata in the Offer::paths. This can be used to prevent de-anonymization attacks where an attacker sends requests using self-constructed paths to nodes near the Offer::paths' introduction nodes.
1 parent ccb1891 commit 40b7284

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::io;
2222
use crate::io::Cursor;
2323
use crate::ln::channelmanager::PaymentId;
2424
use crate::ln::onion_utils;
25+
use crate::offers::nonce::Nonce;
2526
use crate::onion_message::packet::ControlTlvs;
2627
use crate::sign::{NodeSigner, Recipient};
2728
use crate::crypto::streams::ChaChaPolyReadAdapter;
@@ -112,6 +113,18 @@ pub enum OffersContext {
112113
/// This variant is used when a message is sent without using a [`BlindedPath`] or over one
113114
/// created prior to LDK version 0.0.124.
114115
Unknown {},
116+
/// Context used by a [`BlindedPath`] within an [`Offer`] for sending an [`InvoiceRequest`].
117+
///
118+
/// [`Offer`]: crate::offers::offer::Offer
119+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
120+
InvoiceRequest {
121+
/// A nonce used for authenticating that an [`InvoiceRequest`] is for a valid [`Offer`] and
122+
/// for deriving the offer's signing keys.
123+
///
124+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
125+
/// [`Offer`]: crate::offers::offer::Offer
126+
nonce: Nonce,
127+
},
115128
/// Context used by a [`BlindedPath`] within a [`Refund`] or as a reply path for an
116129
/// [`InvoiceRequest`].
117130
///
@@ -133,7 +146,10 @@ impl_writeable_tlv_based_enum!(MessageContext, ;
133146

134147
impl_writeable_tlv_based_enum!(OffersContext,
135148
(0, Unknown) => {},
136-
(1, OutboundPayment) => {
149+
(1, InvoiceRequest) => {
150+
(0, nonce, required),
151+
},
152+
(2, OutboundPayment) => {
137153
(0, payment_id, required),
138154
},
139155
;);

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8623,7 +8623,8 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
86238623
let secp_ctx = &$self.secp_ctx;
86248624

86258625
let nonce = Nonce::from_entropy_source(entropy);
8626-
let path = $self.create_blinded_path_using_absolute_expiry(OffersContext::Unknown {}, absolute_expiry)
8626+
let context = OffersContext::InvoiceRequest { nonce };
8627+
let path = $self.create_blinded_path_using_absolute_expiry(context, absolute_expiry)
86278628
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
86288629
let builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
86298630
.chain_hash($self.chain_hash)

lightning/src/offers/nonce.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99

1010
//! A number used only once.
1111
12+
use crate::io::{self, Read};
13+
use crate::ln::msgs::DecodeError;
1214
use crate::sign::EntropySource;
15+
use crate::util::ser::{Readable, Writeable, Writer};
1316
use core::ops::Deref;
1417

1518
#[allow(unused_imports)]
@@ -62,3 +65,15 @@ impl TryFrom<&[u8]> for Nonce {
6265
Ok(Self(copied_bytes))
6366
}
6467
}
68+
69+
impl Writeable for Nonce {
70+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
71+
self.0.write(w)
72+
}
73+
}
74+
75+
impl Readable for Nonce {
76+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
77+
Ok(Nonce(Readable::read(r)?))
78+
}
79+
}

0 commit comments

Comments
 (0)