Skip to content

Commit 2c77166

Browse files
f Use unique keys for deriving inbound payment secrets
1 parent 3aa79c5 commit 2c77166

File tree

1 file changed

+34
-7
lines changed

1 file changed

+34
-7
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,8 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
640640
our_network_key: SecretKey,
641641
our_network_pubkey: PublicKey,
642642

643+
inbound_payments_key: SecretKey,
644+
643645
/// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
644646
/// value increases strictly since we don't assume access to a time source.
645647
last_node_announcement_serial: AtomicUsize,
@@ -1340,6 +1342,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
13401342
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()),
13411343
secp_ctx,
13421344

1345+
inbound_payments_key: SecretKey::from_slice(&keys_manager.get_secure_random_bytes()).expect("broken RNG"),
1346+
13431347
last_node_announcement_serial: AtomicUsize::new(0),
13441348
highest_seen_timestamp: AtomicUsize::new(0),
13451349

@@ -2590,7 +2594,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25902594
// Check that an inbound payment's `payment_data` field is sane.
25912595
fn verify_inbound_payment_data(&self, payment_hash: PaymentHash, payment_data: msgs::FinalOnionHopData) -> Result<Option<PaymentPreimage>, ()> {
25922596
let (iv_bytes, encrypted_metadata_bytes) = payment_data.payment_secret.0.split_at(16);
2593-
let mut chacha = ChaCha20::new(&self.our_network_key[..], &iv_bytes[..12]);
2597+
let mut chacha = ChaCha20::new(&self.inbound_payments_key[..], &iv_bytes[..12]);
25942598
let mut chacha_bytes = [0; 16];
25952599
chacha.process_in_place(&mut chacha_bytes);
25962600

@@ -2606,9 +2610,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
26062610
}
26072611

26082612
let is_user_payment_hash = metadata_bytes[0] & 1 << 7 != 0;
2613+
let (user_pmt_hash_key, ldk_pmt_hash_key) = hkdf_extract_expand(&vec![0], &self.inbound_payments_key[..]);
26092614
let mut payment_preimage = None;
26102615
if is_user_payment_hash {
2611-
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
2616+
let mut hmac = HmacEngine::<Sha256>::new(&user_pmt_hash_key);
26122617
hmac.input(&metadata_bytes[..]);
26132618
hmac.input(&payment_hash.0[..]);
26142619
if iv_bytes != Hmac::from_engine(hmac).into_inner().split_at_mut(16).0 {
@@ -2630,7 +2635,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
26302635
log_trace!(self.logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", log_bytes!(payment_hash.0), payment_data.total_msat, min_amt_msat);
26312636
return Err(())
26322637
}
2633-
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
2638+
let mut hmac = HmacEngine::<Sha256>::new(&ldk_pmt_hash_key);
26342639
hmac.input(&iv_bytes);
26352640
hmac.input(&metadata_bytes);
26362641
let decoded_payment_preimage = Hmac::from_engine(hmac).into_inner();
@@ -4626,7 +4631,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46264631
let rand_bytes = self.keys_manager.get_secure_random_bytes();
46274632
let iv_bytes = &rand_bytes[..16];
46284633

4629-
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
4634+
let (_, ldk_pmt_hash_key) = hkdf_extract_expand(&vec![0], &self.inbound_payments_key[..]);
4635+
let mut hmac = HmacEngine::<Sha256>::new(&ldk_pmt_hash_key);
46304636
hmac.input(iv_bytes);
46314637
hmac.input(&metadata_bytes);
46324638
let payment_preimage_bytes = Hmac::from_engine(hmac).into_inner();
@@ -4636,7 +4642,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46364642
let (iv_slice, encrypted_metadata_slice) = payment_secret_bytes.split_at_mut(16);
46374643
iv_slice.copy_from_slice(iv_bytes);
46384644

4639-
let mut chacha = ChaCha20::new(&self.our_network_key[..], &iv_bytes[..12]);
4645+
let mut chacha = ChaCha20::new(&self.inbound_payments_key[..], &iv_bytes[..12]);
46404646
let mut chacha_bytes = [0; 16];
46414647
chacha.process_in_place(&mut chacha_bytes);
46424648

@@ -4705,7 +4711,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47054711
expiry_slice.copy_from_slice(&expiry_bytes);
47064712
}
47074713

4708-
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
4714+
let (user_pmt_hash_key, _) = hkdf_extract_expand(&vec![0], &self.inbound_payments_key[..]);
4715+
let mut hmac = HmacEngine::<Sha256>::new(&user_pmt_hash_key);
47094716
hmac.input(&metadata_bytes);
47104717
hmac.input(&payment_hash.0);
47114718
let hmac_bytes = Hmac::from_engine(hmac).into_inner();
@@ -4716,7 +4723,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
47164723
let (iv_slice, encrypted_metadata_slice) = payment_secret_bytes.split_at_mut(16);
47174724
iv_slice.copy_from_slice(iv_bytes);
47184725

4719-
let mut chacha = ChaCha20::new(&self.our_network_key[..], &iv_bytes[..12]);
4726+
let mut chacha = ChaCha20::new(&self.inbound_payments_key[..], &iv_bytes[..12]);
47204727
let mut chacha_bytes = [0; 16];
47214728
chacha.process_in_place(&mut chacha_bytes);
47224729

@@ -5796,6 +5803,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
57965803
}
57975804
write_tlv_fields!(writer, {
57985805
(1, pending_outbound_payments_no_retry, required),
5806+
(2, self.inbound_payments_key, required),
57995807
(3, pending_outbound_payments, required),
58005808
});
58015809

@@ -6089,10 +6097,15 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
60896097
// pending_outbound_payments_no_retry is for compatibility with 0.0.101 clients.
60906098
let mut pending_outbound_payments_no_retry: Option<HashMap<PaymentId, HashSet<[u8; 32]>>> = None;
60916099
let mut pending_outbound_payments = None;
6100+
let mut inbound_payments_key = None;
60926101
read_tlv_fields!(reader, {
60936102
(1, pending_outbound_payments_no_retry, option),
6103+
(2, inbound_payments_key, option),
60946104
(3, pending_outbound_payments, option),
60956105
});
6106+
if inbound_payments_key.is_none() {
6107+
inbound_payments_key = Some(SecretKey::from_slice(&args.keys_manager.get_secure_random_bytes()).expect("broken RNG"));
6108+
}
60966109
if pending_outbound_payments.is_none() && pending_outbound_payments_no_retry.is_none() {
60976110
pending_outbound_payments = Some(pending_outbound_payments_compat);
60986111
} else if pending_outbound_payments.is_none() {
@@ -6170,6 +6183,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
61706183
claimable_htlcs,
61716184
pending_msg_events: Vec::new(),
61726185
}),
6186+
inbound_payments_key: inbound_payments_key.unwrap(),
61736187
pending_inbound_payments: Mutex::new(pending_inbound_payments),
61746188
pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
61756189

@@ -6203,6 +6217,19 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
62036217
}
62046218
}
62056219

6220+
fn hkdf_extract_expand(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
6221+
let mut hmac = HmacEngine::<Sha256>::new(salt);
6222+
hmac.input(ikm);
6223+
let prk = Hmac::from_engine(hmac).into_inner();
6224+
let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
6225+
hmac.input(&[1; 1]);
6226+
let t1 = Hmac::from_engine(hmac).into_inner();
6227+
let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
6228+
hmac.input(&t1);
6229+
hmac.input(&[2; 1]);
6230+
(t1, Hmac::from_engine(hmac).into_inner())
6231+
}
6232+
62066233
#[cfg(test)]
62076234
mod tests {
62086235
use bitcoin::hashes::Hash;

0 commit comments

Comments
 (0)