Skip to content

Commit ceb9671

Browse files
Aditya SharmaAditya Sharma
authored andcommitted
lightning: Add a key inside NodeSigner which would be used to encrypt or decrpt the peerstorage and send PeerStorage on every RAA and upon reconnection.
1 parent 620aa1d commit ceb9671

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,9 @@ where
23312331

23322332
inbound_payment_key: inbound_payment::ExpandedKey,
23332333

2334+
/// The key used to encrypt our peer storage that would be sent to our peers.
2335+
our_peerstorage_encryption_key: [u8;32],
2336+
23342337
/// LDK puts the [fake scids] that it generates into namespaces, to identify the type of an
23352338
/// incoming payment. To make it harder for a third-party to identify the type of a payment,
23362339
/// we encrypt the namespace identifier using these bytes.
@@ -3211,6 +3214,7 @@ where
32113214
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
32123215
let inbound_pmt_key_material = node_signer.get_inbound_payment_key_material();
32133216
let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
3217+
let our_peerstorage_encryption_key = node_signer.get_peer_storage_key();
32143218
ChannelManager {
32153219
default_configuration: config.clone(),
32163220
chain_hash: ChainHash::using_genesis_block(params.network),
@@ -3236,6 +3240,8 @@ where
32363240
secp_ctx,
32373241

32383242
inbound_payment_key: expanded_inbound_key,
3243+
our_peerstorage_encryption_key,
3244+
32393245
fake_scid_rand_bytes: entropy_source.get_secure_random_bytes(),
32403246

32413247
probing_cookie_secret: entropy_source.get_secure_random_bytes(),
@@ -3273,6 +3279,13 @@ where
32733279
&self.default_configuration
32743280
}
32753281

3282+
/// Returns the encrypted [`OurPeerStorage`] which can be distributed among our peers.
3283+
/// We use a key derived from our seed to encrypt this.
3284+
pub fn get_encrypted_our_peer_storage(&self) -> Vec<u8> {
3285+
let our_peer_storage = self.our_peer_storage.read().unwrap();
3286+
our_peer_storage.encrypt_our_peer_storage(self.our_peerstorage_encryption_key)
3287+
}
3288+
32763289
fn create_and_insert_outbound_scid_alias(&self) -> u64 {
32773290
let height = self.best_block.read().unwrap().height;
32783291
let mut outbound_scid_alias = 0;
@@ -8580,6 +8593,30 @@ where
85808593
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id))
85818594
}
85828595
};
8596+
8597+
{
8598+
let per_peer_state = self.per_peer_state.read().unwrap();
8599+
let mut peer_state_lock = per_peer_state.get(counterparty_node_id)
8600+
.ok_or_else(|| {
8601+
debug_assert!(false);
8602+
MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
8603+
}).map(|mtx| mtx.lock().unwrap())?;
8604+
let peer_state = &mut *peer_state_lock;
8605+
let our_peer_storage = self.get_encrypted_our_peer_storage();
8606+
8607+
for context in peer_state.channel_by_id.iter().map(|(_, phase)| phase.context()) {
8608+
// Update latest PeerStorage for the peer.
8609+
peer_state.pending_msg_events.push(
8610+
events::MessageSendEvent::SendPeerStorageMessage {
8611+
node_id: context.get_counterparty_node_id(),
8612+
msg: msgs::PeerStorageMessage {
8613+
data: our_peer_storage.clone()
8614+
},
8615+
}
8616+
);
8617+
}
8618+
}
8619+
85838620
self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id, counterparty_node_id);
85848621
Ok(())
85858622
}
@@ -10881,6 +10918,7 @@ where
1088110918
if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) {
1088210919
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
1088310920
let peer_state = &mut *peer_state_lock;
10921+
let num_channels = peer_state.total_channel_count();
1088410922
let pending_msg_events = &mut peer_state.pending_msg_events;
1088510923

1088610924
if !peer_state.peer_storage.is_empty() {
@@ -10892,6 +10930,15 @@ where
1089210930
});
1089310931
}
1089410932

10933+
if peer_state.latest_features.supports_provide_peer_storage() && num_channels > 0 {
10934+
let our_peer_storage = self.get_encrypted_our_peer_storage();
10935+
pending_msg_events.push(events::MessageSendEvent::SendPeerStorageMessage {
10936+
node_id: counterparty_node_id.clone(),
10937+
msg: msgs::PeerStorageMessage {
10938+
data: our_peer_storage
10939+
},
10940+
});
10941+
}
1089510942

1089610943
for (_, phase) in peer_state.channel_by_id.iter_mut() {
1089710944
match phase {
@@ -12929,6 +12976,7 @@ where
1292912976

1293012977
let inbound_pmt_key_material = args.node_signer.get_inbound_payment_key_material();
1293112978
let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
12979+
let our_peerstorage_encryption_key = args.node_signer.get_peer_storage_key();
1293212980

1293312981
let mut claimable_payments = hash_map_with_capacity(claimable_htlcs_list.len());
1293412982
if let Some(purposes) = claimable_htlc_purposes {
@@ -13154,6 +13202,7 @@ where
1315413202
best_block: RwLock::new(BestBlock::new(best_block_hash, best_block_height)),
1315513203

1315613204
inbound_payment_key: expanded_inbound_key,
13205+
our_peerstorage_encryption_key,
1315713206
pending_inbound_payments: Mutex::new(pending_inbound_payments),
1315813207
pending_outbound_payments: pending_outbounds,
1315913208
pending_intercepted_htlcs: Mutex::new(pending_intercepted_htlcs.unwrap()),

lightning/src/sign/mod.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,35 @@ pub trait NodeSigner {
835835
/// [phantom node payments]: PhantomKeysManager
836836
fn get_inbound_payment_key_material(&self) -> KeyMaterial;
837837

838+
/// Generates a 32-byte key used for peer storage encryption.
839+
///
840+
/// This function derives an encryption key for peer storage by using the HKDF
841+
/// (HMAC-based Key Derivation Function) with a specific label and the node
842+
/// secret key. The derived key is used for encrypting or decrypting peer storage
843+
/// data.
844+
///
845+
/// The process involves the following steps:
846+
/// 1. Retrieves the node secret key.
847+
/// 2. Uses the node secret key and the label `"Peer Storage Encryption Key"`
848+
/// to perform HKDF extraction and expansion.
849+
/// 3. Returns the first part of the derived key, which is a 32-byte array.
850+
///
851+
/// # Returns
852+
///
853+
/// Returns a 32-byte array that serves as the encryption key for peer storage.
854+
///
855+
/// # Panics
856+
///
857+
/// This function does not panic under normal circumstances, but failures in
858+
/// obtaining the node secret key or issues within the HKDF function may cause
859+
/// unexpected behavior.
860+
///
861+
/// # Notes
862+
///
863+
/// Ensure that the node secret key is securely managed, as it is crucial for
864+
/// the security of the derived encryption key.
865+
fn get_peer_storage_key(&self) -> [u8; 32];
866+
838867
/// Get node id based on the provided [`Recipient`].
839868
///
840869
/// This method must return the same value each time it is called with a given [`Recipient`]
@@ -2174,6 +2203,14 @@ impl NodeSigner for KeysManager {
21742203
self.inbound_payment_key.clone()
21752204
}
21762205

2206+
fn get_peer_storage_key(&self) -> [u8; 32] {
2207+
let (t1, _) = hkdf_extract_expand_twice(
2208+
b"Peer Storage Encryption Key",
2209+
&self.get_node_secret_key().secret_bytes(),
2210+
);
2211+
t1
2212+
}
2213+
21772214
fn sign_invoice(
21782215
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
21792216
) -> Result<RecoverableSignature, ()> {
@@ -2352,6 +2389,14 @@ impl NodeSigner for PhantomKeysManager {
23522389
self.inbound_payment_key.clone()
23532390
}
23542391

2392+
fn get_peer_storage_key(&self) -> [u8; 32] {
2393+
let (t1, _) = hkdf_extract_expand_twice(
2394+
b"Peer Storage Encryption Key",
2395+
&self.get_node_secret_key().secret_bytes(),
2396+
);
2397+
t1
2398+
}
2399+
23552400
fn sign_invoice(
23562401
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
23572402
) -> Result<RecoverableSignature, ()> {

0 commit comments

Comments
 (0)