Skip to content

Commit 92b169b

Browse files
committed
Elide nonce from payer metadata
InvoiceRequest and Refund have payer_metadata which consists of an encrypted payment id and a nonce used to derive its signing keys and authenticate any corresponding invoices. Now that the blinded paths include this data in their OffersContext, remove the nonce as it is now redundant. Keep the encrypted payment id as some data is needed in the payer metadata according to the spec. This saves space and prevents de-anonymization attacks as along as the nonce isn't revealed.
1 parent 327ba53 commit 92b169b

File tree

5 files changed

+35
-39
lines changed

5 files changed

+35
-39
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4106,15 +4106,35 @@ where
41064106
/// whether or not the payment was successful.
41074107
///
41084108
/// [timer tick]: Self::timer_tick_occurred
4109-
pub fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice) -> Result<(), Bolt12PaymentError> {
4110-
let secp_ctx = &self.secp_ctx;
4111-
let expanded_key = &self.inbound_payment_key;
4112-
match invoice.verify(expanded_key, secp_ctx) {
4109+
pub fn send_payment_for_bolt12_invoice(
4110+
&self, invoice: &Bolt12Invoice, context: &OffersContext,
4111+
) -> Result<(), Bolt12PaymentError> {
4112+
match self.verify_bolt12_invoice(invoice, context) {
41134113
Ok(payment_id) => self.send_payment_for_verified_bolt12_invoice(invoice, payment_id),
41144114
Err(()) => Err(Bolt12PaymentError::UnexpectedInvoice),
41154115
}
41164116
}
41174117

4118+
fn verify_bolt12_invoice(
4119+
&self, invoice: &Bolt12Invoice, context: &OffersContext,
4120+
) -> Result<PaymentId, ()> {
4121+
let secp_ctx = &self.secp_ctx;
4122+
let expanded_key = &self.inbound_payment_key;
4123+
4124+
match context {
4125+
OffersContext::Unknown {} if invoice.is_for_refund_without_paths() => {
4126+
invoice.verify(expanded_key, secp_ctx)
4127+
},
4128+
OffersContext::OutboundPayment { payment_id, nonce } => {
4129+
invoice
4130+
.verify_using_payer_data(*payment_id, *nonce, expanded_key, secp_ctx)
4131+
.then(|| *payment_id)
4132+
.ok_or(())
4133+
},
4134+
_ => Err(()),
4135+
}
4136+
}
4137+
41184138
fn send_payment_for_verified_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> {
41194139
let best_block_height = self.best_block.read().unwrap().height;
41204140
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
@@ -10644,24 +10664,9 @@ where
1064410664
}
1064510665
},
1064610666
OffersMessage::Invoice(invoice) => {
10647-
let payer_data = match context {
10648-
OffersContext::Unknown {} if invoice.is_for_refund_without_paths() => None,
10649-
OffersContext::OutboundPayment { payment_id, nonce } => Some((payment_id, nonce)),
10650-
_ => return ResponseInstruction::NoResponse,
10651-
};
10652-
10653-
let payment_id = match payer_data {
10654-
Some((payment_id, nonce)) => {
10655-
if invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) {
10656-
payment_id
10657-
} else {
10658-
return ResponseInstruction::NoResponse;
10659-
}
10660-
},
10661-
None => match invoice.verify(expanded_key, secp_ctx) {
10662-
Ok(payment_id) => payment_id,
10663-
Err(()) => return ResponseInstruction::NoResponse,
10664-
},
10667+
let payment_id = match self.verify_bolt12_invoice(&invoice, &context) {
10668+
Ok(payment_id) => payment_id,
10669+
Err(()) => return ResponseInstruction::NoResponse,
1066510670
};
1066610671

1066710672
let result = {

lightning/src/ln/offers_tests.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,10 +1085,10 @@ fn pays_bolt12_invoice_asynchronously() {
10851085
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
10861086
bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
10871087

1088-
let invoice = match get_event!(bob, Event::InvoiceReceived) {
1089-
Event::InvoiceReceived { payment_id: actual_payment_id, invoice, .. } => {
1088+
let (invoice, context) = match get_event!(bob, Event::InvoiceReceived) {
1089+
Event::InvoiceReceived { payment_id: actual_payment_id, invoice, context, .. } => {
10901090
assert_eq!(actual_payment_id, payment_id);
1091-
invoice
1091+
(invoice, context)
10921092
},
10931093
_ => panic!("No Event::InvoiceReceived"),
10941094
};
@@ -1099,9 +1099,9 @@ fn pays_bolt12_invoice_asynchronously() {
10991099
assert_eq!(path.introduction_node, IntroductionNode::NodeId(alice_id));
11001100
}
11011101

1102-
assert!(bob.node.send_payment_for_bolt12_invoice(&invoice).is_ok());
1102+
assert!(bob.node.send_payment_for_bolt12_invoice(&invoice, &context).is_ok());
11031103
assert_eq!(
1104-
bob.node.send_payment_for_bolt12_invoice(&invoice),
1104+
bob.node.send_payment_for_bolt12_invoice(&invoice, &context),
11051105
Err(Bolt12PaymentError::DuplicateInvoice),
11061106
);
11071107

@@ -1112,7 +1112,7 @@ fn pays_bolt12_invoice_asynchronously() {
11121112
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
11131113

11141114
assert_eq!(
1115-
bob.node.send_payment_for_bolt12_invoice(&invoice),
1115+
bob.node.send_payment_for_bolt12_invoice(&invoice, &context),
11161116
Err(Bolt12PaymentError::DuplicateInvoice),
11171117
);
11181118

@@ -1121,7 +1121,7 @@ fn pays_bolt12_invoice_asynchronously() {
11211121
}
11221122

11231123
assert_eq!(
1124-
bob.node.send_payment_for_bolt12_invoice(&invoice),
1124+
bob.node.send_payment_for_bolt12_invoice(&invoice, &context),
11251125
Err(Bolt12PaymentError::UnexpectedInvoice),
11261126
);
11271127
}

lightning/src/offers/invoice_request.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,10 +1487,6 @@ mod tests {
14871487
.unwrap()
14881488
.build().unwrap()
14891489
.sign(recipient_sign).unwrap();
1490-
match invoice.verify(&expanded_key, &secp_ctx) {
1491-
Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])),
1492-
Err(()) => panic!("verification failed"),
1493-
}
14941490
assert!(invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx));
14951491

14961492
// Fails verification with altered fields

lightning/src/offers/refund.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,10 +1107,6 @@ mod tests {
11071107
.unwrap()
11081108
.build().unwrap()
11091109
.sign(recipient_sign).unwrap();
1110-
match invoice.verify(&expanded_key, &secp_ctx) {
1111-
Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])),
1112-
Err(()) => panic!("verification failed"),
1113-
}
11141110
assert!(invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx));
11151111

11161112
// Fails verification with altered fields

lightning/src/offers/signer.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,7 @@ impl MetadataMaterial {
249249
self.hmac.input(DERIVED_METADATA_AND_KEYS_HMAC_INPUT);
250250
self.maybe_include_encrypted_payment_id();
251251

252-
let mut bytes = self.encrypted_payment_id.map(|id| id.to_vec()).unwrap_or(vec![]);
253-
bytes.extend_from_slice(self.nonce.as_slice());
252+
let bytes = self.encrypted_payment_id.map(|id| id.to_vec()).unwrap_or(vec![]);
254253

255254
let hmac = Hmac::from_engine(self.hmac);
256255
let privkey = SecretKey::from_slice(hmac.as_byte_array()).unwrap();

0 commit comments

Comments
 (0)