Skip to content

Commit 67744e0

Browse files
committed
Include HMAC and Nonce in payment::ReceiveTlvs
In order to authenticate a PaymentContext, an HMAC and Nonce must be included along with it in payment::ReceiveTlvs. Compute the HMAC when constructing a BlindedPaymentPath and include it in the recipient's BlindedPaymentTlvs. Authentication will be added in an upcoming commit.
1 parent 611b221 commit 67744e0

File tree

5 files changed

+34
-6
lines changed

5 files changed

+34
-6
lines changed

fuzz/src/invoice_request_deser.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ use lightning::blinded_path::payment::{
1414
BlindedPaymentPath, Bolt12OfferContext, ForwardTlvs, PaymentConstraints, PaymentContext,
1515
PaymentForwardNode, PaymentRelay, ReceiveTlvs,
1616
};
17-
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
17+
use lightning::ln::channelmanager::{MIN_FINAL_CLTV_EXPIRY_DELTA, Verification};
18+
use lightning::ln::inbound_payment::ExpandedKey;
1819
use lightning::offers::invoice::UnsignedBolt12Invoice;
1920
use lightning::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields};
21+
use lightning::offers::nonce::Nonce;
2022
use lightning::offers::offer::OfferId;
2123
use lightning::offers::parse::Bolt12SemanticError;
22-
use lightning::sign::EntropySource;
24+
use lightning::sign::{EntropySource, KeyMaterial};
2325
use lightning::types::features::BlindedHopFeatures;
2426
use lightning::types::payment::{PaymentHash, PaymentSecret};
2527
use lightning::util::ser::Writeable;
@@ -80,6 +82,7 @@ fn privkey(byte: u8) -> SecretKey {
8082
fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
8183
invoice_request: &InvoiceRequest, secp_ctx: &Secp256k1<T>,
8284
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
85+
let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
8386
let entropy_source = Randomness {};
8487
let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
8588
offer_id: OfferId([42; 32]),
@@ -92,13 +95,16 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
9295
human_readable_name: None,
9396
},
9497
});
98+
let nonce = Nonce::from_entropy_source(&entropy_source);
99+
let hmac = payment_context.hmac_for_offer_payment(nonce, &expanded_key);
95100
let payee_tlvs = ReceiveTlvs {
96101
payment_secret: PaymentSecret([42; 32]),
97102
payment_constraints: PaymentConstraints {
98103
max_cltv_expiry: 1_000_000,
99104
htlc_minimum_msat: 1,
100105
},
101106
payment_context,
107+
authentication: (hmac, nonce),
102108
};
103109
let intermediate_nodes = [PaymentForwardNode {
104110
tlvs: ForwardTlvs {

fuzz/src/refund_deser.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ use lightning::blinded_path::payment::{
1414
BlindedPaymentPath, Bolt12RefundContext, ForwardTlvs, PaymentConstraints, PaymentContext,
1515
PaymentForwardNode, PaymentRelay, ReceiveTlvs,
1616
};
17-
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
17+
use lightning::ln::channelmanager::{MIN_FINAL_CLTV_EXPIRY_DELTA, Verification};
18+
use lightning::ln::inbound_payment::ExpandedKey;
1819
use lightning::offers::invoice::UnsignedBolt12Invoice;
20+
use lightning::offers::nonce::Nonce;
1921
use lightning::offers::parse::Bolt12SemanticError;
2022
use lightning::offers::refund::Refund;
21-
use lightning::sign::EntropySource;
23+
use lightning::sign::{EntropySource, KeyMaterial};
2224
use lightning::types::features::BlindedHopFeatures;
2325
use lightning::types::payment::{PaymentHash, PaymentSecret};
2426
use lightning::util::ser::Writeable;
@@ -67,15 +69,19 @@ fn privkey(byte: u8) -> SecretKey {
6769
fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
6870
refund: &Refund, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>,
6971
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
72+
let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
7073
let entropy_source = Randomness {};
7174
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
75+
let nonce = Nonce::from_entropy_source(&entropy_source);
76+
let hmac = payment_context.hmac_for_offer_payment(nonce, &expanded_key);
7277
let payee_tlvs = ReceiveTlvs {
7378
payment_secret: PaymentSecret([42; 32]),
7479
payment_constraints: PaymentConstraints {
7580
max_cltv_expiry: 1_000_000,
7681
htlc_minimum_msat: 1,
7782
},
7883
payment_context,
84+
authentication: (hmac, nonce),
7985
};
8086
let intermediate_nodes = [PaymentForwardNode {
8187
tlvs: ForwardTlvs {

lightning/src/blinded_path/payment.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
//! Data structures and methods for constructing [`BlindedPaymentPath`]s to send a payment over.
1111
12+
use bitcoin::hashes::hmac::Hmac;
13+
use bitcoin::hashes::sha256::Hash as Sha256;
1214
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
1315

1416
use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NodeIdLookUp};
@@ -22,6 +24,7 @@ use crate::types::features::BlindedHopFeatures;
2224
use crate::ln::msgs::DecodeError;
2325
use crate::ln::onion_utils;
2426
use crate::offers::invoice_request::InvoiceRequestFields;
27+
use crate::offers::nonce::Nonce;
2528
use crate::offers::offer::OfferId;
2629
use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
2730
use crate::sign::{EntropySource, NodeSigner, Recipient};
@@ -260,6 +263,8 @@ pub struct ReceiveTlvs {
260263
pub payment_constraints: PaymentConstraints,
261264
/// Context for the receiver of this payment.
262265
pub payment_context: PaymentContext,
266+
/// An HMAC of `payment_context` along with a nonce used to construct it.
267+
pub authentication: (Hmac<Sha256>, Nonce),
263268
}
264269

265270
/// Data to construct a [`BlindedHop`] for sending a payment over.
@@ -404,7 +409,8 @@ impl Writeable for ReceiveTlvs {
404409
encode_tlv_stream!(w, {
405410
(12, self.payment_constraints, required),
406411
(65536, self.payment_secret, required),
407-
(65537, self.payment_context, required)
412+
(65537, self.payment_context, required),
413+
(65539, self.authentication, required),
408414
});
409415
Ok(())
410416
}
@@ -432,6 +438,7 @@ impl Readable for BlindedPaymentTlvs {
432438
(14, features, (option, encoding: (BlindedHopFeatures, WithoutLength))),
433439
(65536, payment_secret, option),
434440
(65537, payment_context, (default_value, PaymentContext::unknown())),
441+
(65539, authentication, option),
435442
});
436443
let _padding: Option<utils::Padding> = _padding;
437444

@@ -452,6 +459,7 @@ impl Readable for BlindedPaymentTlvs {
452459
payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
453460
payment_constraints: payment_constraints.0.unwrap(),
454461
payment_context: payment_context.0.unwrap(),
462+
authentication: authentication.ok_or(DecodeError::InvalidValue)?,
455463
}))
456464
}
457465
}

lightning/src/ln/channelmanager.rs

+8
Original file line numberDiff line numberDiff line change
@@ -10472,20 +10472,28 @@ where
1047210472
fn create_blinded_payment_paths(
1047310473
&self, amount_msats: u64, payment_secret: PaymentSecret, payment_context: PaymentContext
1047410474
) -> Result<Vec<BlindedPaymentPath>, ()> {
10475+
let expanded_key = &self.inbound_payment_key;
10476+
let entropy = &*self.entropy_source;
1047510477
let secp_ctx = &self.secp_ctx;
1047610478

1047710479
let first_hops = self.list_usable_channels();
1047810480
let payee_node_id = self.get_our_node_id();
1047910481
let max_cltv_expiry = self.best_block.read().unwrap().height + CLTV_FAR_FAR_AWAY
1048010482
+ LATENCY_GRACE_PERIOD_BLOCKS;
10483+
10484+
let nonce = Nonce::from_entropy_source(entropy);
10485+
let hmac = payment_context.hmac_for_offer_payment(nonce, expanded_key);
10486+
1048110487
let payee_tlvs = ReceiveTlvs {
1048210488
payment_secret,
1048310489
payment_constraints: PaymentConstraints {
1048410490
max_cltv_expiry,
1048510491
htlc_minimum_msat: 1,
1048610492
},
1048710493
payment_context,
10494+
authentication: (hmac, nonce),
1048810495
};
10496+
1048910497
self.router.create_blinded_payment_paths(
1049010498
payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx
1049110499
)

lightning/src/ln/msgs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2908,7 +2908,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
29082908
})
29092909
},
29102910
ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs {
2911-
payment_secret, payment_constraints, payment_context
2911+
payment_secret, payment_constraints, payment_context, authentication: _,
29122912
})} => {
29132913
if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
29142914
Ok(Self::BlindedReceive {

0 commit comments

Comments
 (0)