Skip to content

Commit 674eafc

Browse files
Aditya Sharmaadi2011
authored andcommitted
Add method to derive Peer Storage encryption key
Add get_peer_storage_key method to derive a 32-byte encryption key for securing Peer Storage. This method utilizes HKDF with the node's secret key as input and a fixed info string to generate the encryption key. - Add 'get_peer_storage_key' to NodeSigner. - Implement 'get_peer_storage_key' for KeysManager & PhantomKeysManager.
1 parent 22d4b42 commit 674eafc

File tree

8 files changed

+77
-15
lines changed

8 files changed

+77
-15
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessa
6262
use lightning::routing::router::{
6363
InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, Router,
6464
};
65-
use lightning::sign::{EntropySource, InMemorySigner, NodeSigner, Recipient, SignerProvider};
65+
use lightning::sign::{
66+
EntropySource, InMemorySigner, NodeSigner, PeerStorageKey, Recipient, SignerProvider,
67+
};
6668
use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
6769
use lightning::util::config::UserConfig;
6870
use lightning::util::hash_tables::*;
@@ -337,6 +339,10 @@ impl NodeSigner for KeyProvider {
337339
unreachable!()
338340
}
339341

342+
fn get_peer_storage_key(&self) -> PeerStorageKey {
343+
PeerStorageKey::new([42; 32])
344+
}
345+
340346
fn sign_bolt12_invoice(
341347
&self, _invoice: &UnsignedBolt12Invoice,
342348
) -> Result<schnorr::Signature, ()> {

fuzz/src/full_stack.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use lightning::blinded_path::message::{BlindedMessagePath, MessageContext};
3434
use lightning::blinded_path::payment::{BlindedPaymentPath, ReceiveTlvs};
3535
use lightning::chain;
3636
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
37-
use lightning::chain::chainmonitor;
37+
use lightning::chain::chainmonitor::{self, PeerStorageKey};
3838
use lightning::chain::transaction::OutPoint;
3939
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen};
4040
use lightning::events::Event;
@@ -420,6 +420,10 @@ impl NodeSigner for KeyProvider {
420420
let secp_ctx = Secp256k1::signing_only();
421421
Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
422422
}
423+
424+
fn get_peer_storage_key(&self) -> PeerStorageKey {
425+
PeerStorageKey::new([42; 32])
426+
}
423427
}
424428

425429
impl SignerProvider for KeyProvider {
@@ -608,6 +612,14 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
608612
];
609613

610614
let broadcast = Arc::new(TestBroadcaster { txn_broadcasted: Mutex::new(Vec::new()) });
615+
616+
let keys_manager = Arc::new(KeyProvider {
617+
node_secret: our_network_key.clone(),
618+
inbound_payment_key: ExpandedKey::new(inbound_payment_key),
619+
counter: AtomicU64::new(0),
620+
signer_state: RefCell::new(new_hash_map()),
621+
});
622+
611623
let monitor = Arc::new(chainmonitor::ChainMonitor::new(
612624
None,
613625
broadcast.clone(),
@@ -616,12 +628,6 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
616628
Arc::new(TestPersister { update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed) }),
617629
));
618630

619-
let keys_manager = Arc::new(KeyProvider {
620-
node_secret: our_network_key.clone(),
621-
inbound_payment_key: ExpandedKey::new(inbound_payment_key),
622-
counter: AtomicU64::new(0),
623-
signer_state: RefCell::new(new_hash_map()),
624-
});
625631
let network = Network::Bitcoin;
626632
let best_block_timestamp = genesis_block(network).header.time;
627633
let params = ChainParameters { network, best_block: BestBlock::from_network(network) };

fuzz/src/onion_message.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use lightning::blinded_path::message::{
99
AsyncPaymentsContext, BlindedMessagePath, MessageContext, OffersContext,
1010
};
1111
use lightning::blinded_path::EmptyNodeIdLookUp;
12+
use lightning::chain::chainmonitor::PeerStorageKey;
1213
use lightning::ln::inbound_payment::ExpandedKey;
1314
use lightning::ln::msgs::{self, BaseMessageHandler, DecodeError, OnionMessageHandler};
1415
use lightning::ln::peer_handler::IgnoringMessageHandler;
@@ -249,6 +250,10 @@ impl NodeSigner for KeyProvider {
249250
) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
250251
unreachable!()
251252
}
253+
254+
fn get_peer_storage_key(&self) -> PeerStorageKey {
255+
unreachable!()
256+
}
252257
}
253258

254259
impl SignerProvider for KeyProvider {

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::offers::invoice::UnsignedBolt12Invoice;
3232
use crate::offers::nonce::Nonce;
3333
use crate::prelude::*;
3434
use crate::routing::router::{BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters, TrampolineHop};
35-
use crate::sign::{NodeSigner, Recipient};
35+
use crate::sign::{NodeSigner, PeerStorageKey, Recipient};
3636
use crate::util::config::UserConfig;
3737
use crate::util::ser::{WithoutLength, Writeable};
3838
use crate::util::test_utils;
@@ -1609,6 +1609,7 @@ fn route_blinding_spec_test_vector() {
16091609
fn sign_invoice(
16101610
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
16111611
) -> Result<RecoverableSignature, ()> { unreachable!() }
1612+
fn get_peer_storage_key(&self) -> PeerStorageKey { unreachable!() }
16121613
fn sign_bolt12_invoice(
16131614
&self, _invoice: &UnsignedBolt12Invoice,
16141615
) -> Result<schnorr::Signature, ()> { unreachable!() }
@@ -1918,6 +1919,7 @@ fn test_trampoline_inbound_payment_decoding() {
19181919
fn sign_invoice(
19191920
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
19201921
) -> Result<RecoverableSignature, ()> { unreachable!() }
1922+
fn get_peer_storage_key(&self) -> PeerStorageKey { unreachable!() }
19211923
fn sign_bolt12_invoice(
19221924
&self, _invoice: &UnsignedBolt12Invoice,
19231925
) -> Result<schnorr::Signature, ()> { unreachable!() }

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16400,19 +16400,19 @@ pub mod bench {
1640016400
config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253);
1640116401
config.channel_handshake_config.minimum_depth = 1;
1640216402

16403-
let chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a);
1640416403
let seed_a = [1u8; 32];
1640516404
let keys_manager_a = KeysManager::new(&seed_a, 42, 42);
16405+
let chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a, keys_manager_a.get_peer_storage_key());
1640616406
let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &router, &message_router, &logger_a, &keys_manager_a, &keys_manager_a, &keys_manager_a, config.clone(), ChainParameters {
1640716407
network,
1640816408
best_block: BestBlock::from_network(network),
1640916409
}, genesis_block.header.time);
1641016410
let node_a_holder = ANodeHolder { node: &node_a };
1641116411

1641216412
let logger_b = test_utils::TestLogger::with_id("node a".to_owned());
16413-
let chain_monitor_b = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b);
1641416413
let seed_b = [2u8; 32];
1641516414
let keys_manager_b = KeysManager::new(&seed_b, 42, 42);
16415+
let chain_monitor_b = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b, keys_manager_b.get_peer_storage_key());
1641616416
let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &router, &message_router, &logger_b, &keys_manager_b, &keys_manager_b, &keys_manager_b, config.clone(), ChainParameters {
1641716417
network,
1641816418
best_block: BestBlock::from_network(network),

lightning/src/sign/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,13 @@ pub trait ChannelSigner {
794794
fn channel_keys_id(&self) -> [u8; 32];
795795
}
796796

797+
/// Represents Secret Key used for encrypting Peer Storage.
798+
#[derive(Clone, Copy, PartialEq, Eq)]
799+
pub struct PeerStorageKey {
800+
/// Represents the key used to encrypt and decrypt Peer Storage.
801+
pub inner: [u8; 32],
802+
}
803+
797804
/// Specifies the recipient of an invoice.
798805
///
799806
/// This indicates to [`NodeSigner::sign_invoice`] what node secret key should be used to sign
@@ -832,6 +839,15 @@ pub trait NodeSigner {
832839
/// [phantom node payments]: PhantomKeysManager
833840
fn get_inbound_payment_key(&self) -> ExpandedKey;
834841

842+
/// Defines a method to derive a 32-byte encryption key for peer storage.
843+
///
844+
/// Implementations of this method must derive a secure encryption key.
845+
/// The key is used to encrypt or decrypt backups of our state stored with our peers.
846+
///
847+
/// Thus, if you wish to rely on recovery using this method, you should use a key which
848+
/// can be re-derived from data which would be available after state loss (eg the wallet seed).
849+
fn get_peer_storage_key(&self) -> PeerStorageKey;
850+
835851
/// Get node id based on the provided [`Recipient`].
836852
///
837853
/// This method must return the same value each time it is called with a given [`Recipient`]
@@ -1771,6 +1787,7 @@ pub struct KeysManager {
17711787
shutdown_pubkey: PublicKey,
17721788
channel_master_key: Xpriv,
17731789
channel_child_index: AtomicUsize,
1790+
peer_storage_key: PeerStorageKey,
17741791

17751792
#[cfg(test)]
17761793
pub(crate) entropy_source: RandomBytes,
@@ -1839,6 +1856,10 @@ impl KeysManager {
18391856
.private_key;
18401857
let mut inbound_pmt_key_bytes = [0; 32];
18411858
inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]);
1859+
let peer_storage_key: SecretKey = master_key
1860+
.derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(6).unwrap())
1861+
.expect("Your RNG is busted")
1862+
.private_key;
18421863

18431864
let mut rand_bytes_engine = Sha256::engine();
18441865
rand_bytes_engine.input(&starting_time_secs.to_be_bytes());
@@ -1854,6 +1875,8 @@ impl KeysManager {
18541875
node_id,
18551876
inbound_payment_key: ExpandedKey::new(inbound_pmt_key_bytes),
18561877

1878+
peer_storage_key: PeerStorageKey { inner: peer_storage_key.secret_bytes() },
1879+
18571880
destination_script,
18581881
shutdown_pubkey,
18591882

@@ -2079,6 +2102,10 @@ impl NodeSigner for KeysManager {
20792102
self.inbound_payment_key.clone()
20802103
}
20812104

2105+
fn get_peer_storage_key(&self) -> PeerStorageKey {
2106+
self.peer_storage_key.clone()
2107+
}
2108+
20822109
fn sign_invoice(
20832110
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
20842111
) -> Result<RecoverableSignature, ()> {
@@ -2240,6 +2267,10 @@ impl NodeSigner for PhantomKeysManager {
22402267
self.inbound_payment_key.clone()
22412268
}
22422269

2270+
fn get_peer_storage_key(&self) -> PeerStorageKey {
2271+
self.inner.peer_storage_key.clone()
2272+
}
2273+
22432274
fn sign_invoice(
22442275
&self, invoice: &RawBolt11Invoice, recipient: Recipient,
22452276
) -> Result<RecoverableSignature, ()> {

lightning/src/util/dyn_signer.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ use crate::sign::taproot::TaprootChannelSigner;
1717
use crate::sign::ChannelSigner;
1818
use crate::sign::InMemorySigner;
1919
use crate::sign::{EntropySource, HTLCDescriptor, OutputSpender, PhantomKeysManager};
20-
use crate::sign::{NodeSigner, Recipient, SignerProvider, SpendableOutputDescriptor};
20+
use crate::sign::{
21+
NodeSigner, PeerStorageKey, Recipient, SignerProvider, SpendableOutputDescriptor,
22+
};
2123
use bitcoin;
2224
use bitcoin::absolute::LockTime;
2325
use bitcoin::secp256k1::All;
@@ -214,7 +216,8 @@ inner,
214216
fn sign_bolt12_invoice(,
215217
invoice: &crate::offers::invoice::UnsignedBolt12Invoice
216218
) -> Result<secp256k1::schnorr::Signature, ()>,
217-
fn get_inbound_payment_key(,) -> ExpandedKey
219+
fn get_inbound_payment_key(,) -> ExpandedKey,
220+
fn get_peer_storage_key(,) -> PeerStorageKey
218221
);
219222

220223
delegate!(DynKeysInterface, SignerProvider,
@@ -278,7 +281,8 @@ delegate!(DynPhantomKeysInterface, NodeSigner,
278281
fn sign_invoice(, invoice: &RawBolt11Invoice, recipient: Recipient) -> Result<RecoverableSignature, ()>,
279282
fn sign_bolt12_invoice(, invoice: &crate::offers::invoice::UnsignedBolt12Invoice
280283
) -> Result<secp256k1::schnorr::Signature, ()>,
281-
fn get_inbound_payment_key(,) -> ExpandedKey
284+
fn get_inbound_payment_key(,) -> ExpandedKey,
285+
fn get_peer_storage_key(,) -> PeerStorageKey
282286
);
283287

284288
impl SignerProvider for DynPhantomKeysInterface {

lightning/src/util/test_utils.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use crate::routing::router::{
4646
use crate::routing::scoring::{ChannelUsage, ScoreLookUp, ScoreUpdate};
4747
use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult};
4848
use crate::sign;
49-
use crate::sign::ChannelSigner;
49+
use crate::sign::{ChannelSigner, PeerStorageKey};
5050
use crate::sync::RwLock;
5151
use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures};
5252
use crate::util::config::UserConfig;
@@ -1490,6 +1490,10 @@ impl NodeSigner for TestNodeSigner {
14901490
unreachable!()
14911491
}
14921492

1493+
fn get_peer_storage_key(&self) -> PeerStorageKey {
1494+
unreachable!()
1495+
}
1496+
14931497
fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
14941498
let node_secret = match recipient {
14951499
Recipient::Node => Ok(&self.node_secret),
@@ -1569,6 +1573,10 @@ impl NodeSigner for TestKeysInterface {
15691573
self.backing.sign_invoice(invoice, recipient)
15701574
}
15711575

1576+
fn get_peer_storage_key(&self) -> PeerStorageKey {
1577+
self.backing.get_peer_storage_key()
1578+
}
1579+
15721580
fn sign_bolt12_invoice(
15731581
&self, invoice: &UnsignedBolt12Invoice,
15741582
) -> Result<schnorr::Signature, ()> {

0 commit comments

Comments
 (0)