diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 084ea62efb6..5cabf3c833f 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -345,7 +345,7 @@ mod tests { use bitcoin::network::constants::Network; use lightning::chain::{BestBlock, Confirm, chainmonitor}; use lightning::chain::channelmonitor::ANTI_REORG_DELAY; - use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeysInterface, KeysManager}; + use lightning::chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager}; use lightning::chain::transaction::OutPoint; use lightning::get_event_msg; use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager}; @@ -428,7 +428,7 @@ mod tests { let network_graph = Arc::new(NetworkGraph::new(genesis_block.header.block_hash())); let net_graph_msg_handler = Some(Arc::new(NetGraphMsgHandler::new(network_graph.clone(), Some(chain_source.clone()), logger.clone()))); let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new() )}; - let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_node_secret(Recipient::Node).unwrap(), &seed, logger.clone(), IgnoringMessageHandler{})); + let peer_manager = Arc::new(PeerManager::new(msg_handler, keys_manager.get_shared_secret_producer(), &seed, logger.clone(), IgnoringMessageHandler{})); let node = Node { node: manager, net_graph_msg_handler, peer_manager, chain_monitor, persister, tx_broadcaster, network_graph, logger, best_block }; nodes.push(node); } diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index 2582cc597f2..0d58cfd141e 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -475,6 +475,7 @@ mod tests { use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::time::Duration; + use lightning::chain::keysinterface::EphemeralSharedSecretProducer; pub struct TestLogger(); impl lightning::util::logger::Logger for TestLogger { @@ -560,7 +561,7 @@ mod tests { let a_manager = Arc::new(PeerManager::new(MessageHandler { chan_handler: Arc::clone(&a_handler), route_handler: Arc::clone(&a_handler), - }, a_key.clone(), &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); + }, EphemeralSharedSecretProducer::new(a_key.clone()), &[1; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); let (b_connected_sender, mut b_connected) = mpsc::channel(1); let (b_disconnected_sender, mut b_disconnected) = mpsc::channel(1); @@ -574,7 +575,7 @@ mod tests { let b_manager = Arc::new(PeerManager::new(MessageHandler { chan_handler: Arc::clone(&b_handler), route_handler: Arc::clone(&b_handler), - }, b_key.clone(), &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); + }, EphemeralSharedSecretProducer::new(b_key.clone()), &[2; 32], Arc::new(TestLogger()), Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler{}))); // We bind on localhost, hoping the environment is properly configured with a local // address. This may not always be the case in containers and the like, so if this test is diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 1daeec4ef62..1d3cc9317f8 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -25,8 +25,9 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::WPubkeyHash; +use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::key::{SecretKey, PublicKey}; -use bitcoin::secp256k1::{Secp256k1, Signature, Signing}; +use bitcoin::secp256k1::{Secp256k1, Signature, Signing, All, SignOnly}; use bitcoin::secp256k1::recovery::RecoverableSignature; use bitcoin::secp256k1; @@ -37,7 +38,7 @@ use util::ser::{Writeable, Writer, Readable, ReadableArgs}; use chain::transaction::OutPoint; use ln::{chan_utils, PaymentPreimage}; use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction}; -use ln::msgs::UnsignedChannelAnnouncement; +use ln::msgs::{UnsignedChannelAnnouncement, UnsignedChannelUpdate, UnsignedNodeAnnouncement}; use ln::script::ShutdownScript; use prelude::*; @@ -392,16 +393,60 @@ pub enum Recipient { PhantomNode, } +/// +pub trait SharedSecretProduce: Send + Sync { + /// + fn public_key(&self, secp_ctx: &secp256k1::Secp256k1) -> PublicKey; + /// + fn shared_secret(&self, other: &PublicKey) -> SharedSecret; + /// + fn do_clone(&self) -> Box; +} + +/// +pub struct EphemeralSharedSecretProducer { + /// + pub secret_key: SecretKey +} + +impl SharedSecretProduce for EphemeralSharedSecretProducer { + fn public_key(&self, secp_ctx: &Secp256k1) -> PublicKey { + PublicKey::from_secret_key(&secp_ctx, &self.secret_key) + } + + fn shared_secret(&self, other: &PublicKey) -> SharedSecret { + SharedSecret::new(other, &self.secret_key) + } + + fn do_clone(&self) -> Box { + Box::new(Self { secret_key: self.secret_key }) + } +} + +impl EphemeralSharedSecretProducer { + /// + pub fn new(secret_key: SecretKey) -> Box { + Box::new( Self { secret_key }) + } +} + /// A trait to describe an object which can get user secrets and key material. pub trait KeysInterface { /// A type which implements Sign which will be returned by get_channel_signer. type Signer : Sign; - /// Get node secret key (aka node_id or network_key) based on the provided [`Recipient`]. + /// A shared secret producer using the node key + fn get_shared_secret_producer(&self) -> Box; + + /// ECDH + fn shared_secret(&self, recipient: Recipient, other: &PublicKey) -> Result; + + /// Get node public key (AKA node ID) /// /// This method must return the same value each time it is called with a given `Recipient` /// parameter. - fn get_node_secret(&self, recipient: Recipient) -> Result; + fn get_node_key(&self, recipient: Recipient, secp_ctx: &Secp256k1) -> Result; + /// Get a script pubkey which we send funds to when claiming on-chain contestable outputs. /// /// This method should return a different value each time it is called, to avoid linking @@ -441,6 +486,12 @@ pub trait KeysInterface { /// The secret key used to sign the invoice is dependent on the [`Recipient`]. fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], receipient: Recipient) -> Result; + /// Sign a node announcement + fn sign_node_announcement(&self, msg: &UnsignedNodeAnnouncement, secp_ctx: &Secp256k1) -> Result; + + /// Sign a channel update + fn sign_channel_update(&self, msg: &UnsignedChannelUpdate, secp_ctx: &Secp256k1) -> Result; + /// Get secret key material as bytes for use in encrypting and decrypting inbound payment data. /// /// If the implementor of this trait supports [phantom node payments], then every node that is @@ -1118,10 +1169,6 @@ impl KeysManager { Ok(spend_tx) } -} - -impl KeysInterface for KeysManager { - type Signer = InMemorySigner; fn get_node_secret(&self, recipient: Recipient) -> Result { match recipient { @@ -1129,6 +1176,14 @@ impl KeysInterface for KeysManager { Recipient::PhantomNode => Err(()) } } +} + +impl KeysInterface for KeysManager { + type Signer = InMemorySigner; + + fn get_shared_secret_producer(&self) -> Box { + EphemeralSharedSecretProducer::new(self.node_secret) + } fn get_inbound_payment_key_material(&self) -> KeyMaterial { self.inbound_payment_key.clone() @@ -1169,12 +1224,30 @@ impl KeysInterface for KeysManager { fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data); - let secret = match recipient { - Recipient::Node => self.get_node_secret(Recipient::Node)?, - Recipient::PhantomNode => return Err(()), - }; + let secret = self.get_node_secret(recipient)?; Ok(self.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret)) } + + fn sign_node_announcement(&self, msg: &UnsignedNodeAnnouncement, secp_ctx: &Secp256k1) -> Result { + let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); + Ok(secp_ctx.sign(&msghash, &self.node_secret)) + + } + + fn sign_channel_update(&self, msg: &UnsignedChannelUpdate, secp_ctx: &Secp256k1) -> Result { + let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); + Ok(secp_ctx.sign(&msghash, &self.node_secret)) + } + + fn shared_secret(&self, recipient: Recipient, other: &PublicKey) -> Result { + let secret = self.get_node_secret(recipient)?; + Ok(SharedSecret::new(other, &secret)) + } + + fn get_node_key(&self, recipient: Recipient, secp_ctx: &Secp256k1) -> Result { + let secret = self.get_node_secret(recipient)?; + Ok(PublicKey::from_secret_key(&secp_ctx, &secret)) + } } /// Similar to [`KeysManager`], but allows the node using this struct to receive phantom node @@ -1207,11 +1280,8 @@ pub struct PhantomKeysManager { impl KeysInterface for PhantomKeysManager { type Signer = InMemorySigner; - fn get_node_secret(&self, recipient: Recipient) -> Result { - match recipient { - Recipient::Node => self.inner.get_node_secret(Recipient::Node), - Recipient::PhantomNode => Ok(self.phantom_secret.clone()), - } + fn get_shared_secret_producer(&self) -> Box { + EphemeralSharedSecretProducer::new(self.inner.node_secret) } fn get_inbound_payment_key_material(&self) -> KeyMaterial { @@ -1243,6 +1313,23 @@ impl KeysInterface for PhantomKeysManager { let secret = self.get_node_secret(recipient)?; Ok(self.inner.secp_ctx.sign_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret)) } + + fn sign_node_announcement(&self, msg: &UnsignedNodeAnnouncement, secp_ctx: &Secp256k1) -> Result { + self.inner.sign_node_announcement(msg, secp_ctx) + } + + fn sign_channel_update(&self, msg: &UnsignedChannelUpdate, secp_ctx: &Secp256k1) -> Result { + self.inner.sign_channel_update(msg, secp_ctx) + } + + fn shared_secret(&self, recipient: Recipient, other: &PublicKey) -> Result { + let secret = self.get_node_secret(recipient)?; + Ok(SharedSecret::new(other, &secret)) + } + + fn get_node_key(&self, recipient: Recipient, secp_ctx: &Secp256k1) -> Result { + Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?)) + } } impl PhantomKeysManager { @@ -1275,6 +1362,13 @@ impl PhantomKeysManager { pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner { self.inner.derive_channel_keys(channel_value_satoshis, params) } + + pub(crate) fn get_node_secret(&self, recipient: Recipient) -> Result { + match recipient { + Recipient::Node => Ok(self.inner.node_secret.clone()), + Recipient::PhantomNode => Ok(self.phantom_secret.clone()) + } + } } // Ensure that BaseSign can have a vtable diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 71e0ea121a9..a4f97f972f2 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -6265,13 +6265,13 @@ mod tests { use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys}; use ln::channel::MAX_FUNDING_SATOSHIS; use ln::features::InitFeatures; - use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate}; + use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate, UnsignedNodeAnnouncement}; use ln::script::ShutdownScript; use ln::chan_utils; use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, htlc_success_tx_weight, htlc_timeout_tx_weight}; use chain::BestBlock; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; - use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, BaseSign}; + use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, BaseSign, SharedSecretProduce}; use chain::transaction::OutPoint; use util::config::UserConfig; use util::enforcing_trait_impls::EnforcingSigner; @@ -6280,6 +6280,7 @@ mod tests { use util::test_utils::OnGetShutdownScriptpubkey; use util::logger::Logger; use bitcoin::secp256k1::{Secp256k1, Message, Signature, All}; + use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ffi::Signature as FFISignature; use bitcoin::secp256k1::key::{SecretKey,PublicKey}; use bitcoin::secp256k1::recovery::RecoverableSignature; @@ -6319,7 +6320,7 @@ mod tests { impl KeysInterface for Keys { type Signer = InMemorySigner; - fn get_node_secret(&self, _recipient: Recipient) -> Result { panic!(); } + fn get_shared_secret_producer(&self) -> Box { panic!(); } fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); } fn get_destination_script(&self) -> Script { let secp_ctx = Secp256k1::signing_only(); @@ -6340,6 +6341,10 @@ mod tests { fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { panic!(); } + fn sign_node_announcement(&self, _msg: &UnsignedNodeAnnouncement, _secp_ctx: &Secp256k1) -> Result { panic!(); } + fn sign_channel_update(&self, _msg: &UnsignedChannelUpdate, _secp_ctx: &Secp256k1) -> Result { panic!(); } + fn shared_secret(&self, _recipient: Recipient, _other: &PublicKey) -> Result { panic!(); } + fn get_node_key(&self, _recipient: Recipient, _secp_ctx: &Secp256k1) -> Result { panic!(); } } fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index f3913c5167c..25a36175934 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -25,12 +25,10 @@ use bitcoin::network::constants::Network; use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::secp256k1::key::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1; use chain; @@ -985,7 +983,6 @@ pub struct ChannelManager>, - our_network_key: SecretKey, our_network_pubkey: PublicKey, inbound_payment_key: inbound_payment::ExpandedKey, @@ -1778,8 +1775,7 @@ impl ChannelMana pending_inbound_payments: Mutex::new(HashMap::new()), pending_outbound_payments: Mutex::new(HashMap::new()), - our_network_key: keys_manager.get_node_secret(Recipient::Node).unwrap(), - our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret(Recipient::Node).unwrap()), + our_network_pubkey: keys_manager.get_node_key(Recipient::Node, &secp_ctx).unwrap(), secp_ctx, inbound_payment_key: expanded_inbound_key, @@ -2287,7 +2283,8 @@ impl ChannelMana let shared_secret = { let mut arr = [0; 32]; - arr.copy_from_slice(&SharedSecret::new(&msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key)[..]); + let secret = self.keys_manager.shared_secret(Recipient::Node, &msg.onion_routing_packet.public_key.unwrap()).unwrap(); + arr.copy_from_slice(&secret[..]); arr }; @@ -2514,7 +2511,7 @@ impl ChannelMana Some(id) => id, }; - let were_node_one = PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).serialize()[..] < chan.get_counterparty_node_id().serialize()[..]; + let were_node_one = self.keys_manager.get_node_key(Recipient::Node, &self.secp_ctx).unwrap().serialize()[..] < chan.get_counterparty_node_id().serialize()[..]; let unsigned = msgs::UnsignedChannelUpdate { chain_hash: self.genesis_hash, @@ -2529,8 +2526,7 @@ impl ChannelMana excess_data: Vec::new(), }; - let msg_hash = Sha256dHash::hash(&unsigned.encode()[..]); - let sig = self.secp_ctx.sign(&hash_to_message!(&msg_hash[..]), &self.our_network_key); + let sig = self.keys_manager.sign_channel_update(&unsigned, &self.secp_ctx).unwrap(); Ok(msgs::ChannelUpdate { signature: sig, @@ -3051,8 +3047,7 @@ impl ChannelMana excess_address_data: Vec::new(), excess_data: Vec::new(), }; - let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]); - let node_announce_sig = self.secp_ctx.sign(&msghash, &self.our_network_key); + let node_announce_sig = self.keys_manager.sign_node_announcement(&announcement, &self.secp_ctx).unwrap(); let mut channel_state_lock = self.channel_state.lock().unwrap(); let channel_state = &mut *channel_state_lock; @@ -3129,11 +3124,11 @@ impl ChannelMana } } if let PendingHTLCRouting::Forward { onion_packet, .. } = routing { - let phantom_secret_res = self.keys_manager.get_node_secret(Recipient::PhantomNode); - if phantom_secret_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id) { + let phantom_shared_secret_res = self.keys_manager.shared_secret(Recipient::PhantomNode, &onion_packet.public_key.unwrap()); + if phantom_shared_secret_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id) { let phantom_shared_secret = { let mut arr = [0; 32]; - arr.copy_from_slice(&SharedSecret::new(&onion_packet.public_key.unwrap(), &phantom_secret_res.unwrap())[..]); + arr.copy_from_slice(&phantom_shared_secret_res.unwrap()[..]); arr }; let next_hop = match onion_utils::decode_next_hop(phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac, payment_hash) { @@ -6850,11 +6845,10 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> pending_events_read.append(&mut channel_closures); } - let our_network_key = match args.keys_manager.get_node_secret(Recipient::Node) { + let our_network_pubkey = match args.keys_manager.get_node_key(Recipient::Node, &secp_ctx) { Ok(key) => key, Err(()) => return Err(DecodeError::InvalidValue) }; - let our_network_pubkey = PublicKey::from_secret_key(&secp_ctx, &our_network_key); if let Some(network_pubkey) = received_network_pubkey { if network_pubkey != our_network_pubkey { log_error!(args.logger, "Key that was generated does not match the existing key."); @@ -6912,7 +6906,6 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> outbound_scid_aliases: Mutex::new(outbound_scid_aliases), fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(), - our_network_key, our_network_pubkey, secp_ctx, diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index 070d88dda9a..cee2817a704 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -12,7 +12,7 @@ //! returned errors decode to the correct thing. use chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS}; -use chain::keysinterface::{KeysInterface, Recipient}; +use chain::keysinterface::{Recipient, KeysInterface}; use ln::{PaymentHash, PaymentSecret}; use ln::channelmanager::{HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting}; use ln::onion_utils; @@ -33,7 +33,7 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1; use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::key::{PublicKey, SecretKey}; +use bitcoin::secp256k1::key::SecretKey; use io; use prelude::*; @@ -580,8 +580,7 @@ fn test_onion_failure() { macro_rules! get_phantom_route { ($nodes: expr, $amt: expr, $channel: expr) => {{ let secp_ctx = Secp256k1::new(); - let phantom_secret = $nodes[1].keys_manager.get_node_secret(Recipient::PhantomNode).unwrap(); - let phantom_pubkey = PublicKey::from_secret_key(&secp_ctx, &phantom_secret); + let phantom_pubkey = $nodes[1].keys_manager.get_node_key(Recipient::PhantomNode, &secp_ctx).unwrap(); let phantom_route_hint = $nodes[1].node.get_phantom_route_hints(); let payment_params = PaymentParameters::from_node_id(phantom_pubkey) .with_features(InvoiceFeatures::known()) diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index fbd32526ea6..c3827e8dc93 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -15,14 +15,15 @@ use ln::msgs; use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::key::{PublicKey,SecretKey}; +use bitcoin::secp256k1::{Secp256k1, SignOnly}; +use bitcoin::secp256k1::key::PublicKey; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1; use util::chacha20poly1305rfc::ChaCha20Poly1305RFC; use util::crypto::hkdf_extract_expand_twice; use bitcoin::hashes::hex::ToHex; +use chain::keysinterface::SharedSecretProduce; /// Maximum Lightning message data length according to /// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification) @@ -55,11 +56,11 @@ struct BidirectionalNoiseState { } enum DirectionalNoiseState { Outbound { - ie: SecretKey, + ie: Box, }, Inbound { ie: Option, // filled in if state >= PostActOne - re: Option, // filled in if state >= PostActTwo + re: Option>, // filled in if state >= PostActTwo temp_k2: Option<[u8; 32]>, // filled in if state >= PostActTwo } } @@ -87,7 +88,7 @@ pub struct PeerChannelEncryptor { } impl PeerChannelEncryptor { - pub fn new_outbound(their_node_id: PublicKey, ephemeral_key: SecretKey) -> PeerChannelEncryptor { + pub fn new_outbound(their_node_id: PublicKey, shared_secrete_producer: Box) -> PeerChannelEncryptor { let secp_ctx = Secp256k1::signing_only(); let mut sha = Sha256::engine(); @@ -101,7 +102,7 @@ impl PeerChannelEncryptor { noise_state: NoiseState::InProgress { state: NoiseStep::PreActOne, directional_state: DirectionalNoiseState::Outbound { - ie: ephemeral_key, + ie: shared_secrete_producer, }, bidirectional_state: BidirectionalNoiseState { h, @@ -111,12 +112,12 @@ impl PeerChannelEncryptor { } } - pub fn new_inbound(our_node_secret: &SecretKey) -> PeerChannelEncryptor { + pub fn new_inbound(shared_secret_producer: Box) -> PeerChannelEncryptor { let secp_ctx = Secp256k1::signing_only(); let mut sha = Sha256::engine(); sha.input(&NOISE_H); - let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret); + let our_node_id = shared_secret_producer.public_key(&secp_ctx); sha.input(&our_node_id.serialize()[..]); let h = Sha256::from_engine(sha).into_inner(); @@ -169,15 +170,15 @@ impl PeerChannelEncryptor { } #[inline] - fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) { - let our_pub = PublicKey::from_secret_key(secp_ctx, &our_key); + fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, shared_secret_producer: Box, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) { + let our_pub = shared_secret_producer.public_key(secp_ctx); let mut sha = Sha256::engine(); sha.input(&state.h); sha.input(&our_pub.serialize()[..]); state.h = Sha256::from_engine(sha).into_inner(); - let ss = SharedSecret::new(&their_key, &our_key); + let ss = shared_secret_producer.shared_secret(their_key); let temp_k = PeerChannelEncryptor::hkdf(state, ss); let mut res = [0; 50]; @@ -193,7 +194,7 @@ impl PeerChannelEncryptor { } #[inline] - fn inbound_noise_act(state: &mut BidirectionalNoiseState, act: &[u8], our_key: &SecretKey) -> Result<(PublicKey, [u8; 32]), LightningError> { + fn inbound_noise_act(state: &mut BidirectionalNoiseState, act: &[u8], shared_secret_producer: Box) -> Result<(PublicKey, [u8; 32]), LightningError> { assert_eq!(act.len(), 50); if act[0] != 0 { @@ -210,7 +211,7 @@ impl PeerChannelEncryptor { sha.input(&their_pub.serialize()[..]); state.h = Sha256::from_engine(sha).into_inner(); - let ss = SharedSecret::new(&their_pub, &our_key); + let ss = shared_secret_producer.shared_secret(&their_pub); let temp_k = PeerChannelEncryptor::hkdf(state, ss); let mut dec = [0; 0]; @@ -233,7 +234,7 @@ impl PeerChannelEncryptor { panic!("Requested act at wrong step"); } - let (res, _) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &ie, &self.their_node_id.unwrap()); + let (res, _) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, ie.do_clone(), &self.their_node_id.unwrap()); *state = NoiseStep::PostActOne; res }, @@ -243,7 +244,7 @@ impl PeerChannelEncryptor { } } - pub fn process_act_one_with_keys(&mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey) -> Result<[u8; 50], LightningError> { + pub fn process_act_one_with_keys(&mut self, act_one: &[u8], shared_secret_producer: Box, our_ephemeral: Box) -> Result<[u8; 50], LightningError> { assert_eq!(act_one.len(), 50); match self.noise_state { @@ -254,12 +255,12 @@ impl PeerChannelEncryptor { panic!("Requested act at wrong step"); } - let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, &our_node_secret)?; + let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, shared_secret_producer)?; ie.get_or_insert(their_pub); re.get_or_insert(our_ephemeral); - let (res, temp_k) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &re.unwrap(), &ie.unwrap()); + let (res, temp_k) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, re.as_ref().unwrap().do_clone(), ie.as_ref().unwrap()); *temp_k2 = Some(temp_k); *state = NoiseStep::PostActTwo; Ok(res) @@ -270,7 +271,7 @@ impl PeerChannelEncryptor { } } - pub fn process_act_two(&mut self, act_two: &[u8], our_node_secret: &SecretKey) -> Result<([u8; 66], PublicKey), LightningError> { + pub fn process_act_two(&mut self, act_two: &[u8], shared_secret_producer: Box) -> Result<([u8; 66], PublicKey), LightningError> { assert_eq!(act_two.len(), 50); let final_hkdf; @@ -283,10 +284,10 @@ impl PeerChannelEncryptor { panic!("Requested act at wrong step"); } - let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, &ie)?; + let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, ie.do_clone())?; let mut res = [0; 66]; - let our_node_id = PublicKey::from_secret_key(&self.secp_ctx, &our_node_secret); + let our_node_id = shared_secret_producer.public_key(&self.secp_ctx); PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]); @@ -295,7 +296,7 @@ impl PeerChannelEncryptor { sha.input(&res[1..50]); bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - let ss = SharedSecret::new(&re, our_node_secret); + let ss = shared_secret_producer.shared_secret(&re); let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]); @@ -349,7 +350,7 @@ impl PeerChannelEncryptor { sha.input(&act_three[1..50]); bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - let ss = SharedSecret::new(&self.their_node_id.unwrap(), &re.unwrap()); + let ss = re.as_ref().unwrap().shared_secret(&self.their_node_id.unwrap()); let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); PeerChannelEncryptor::decrypt_with_ad(&mut [0; 0], 0, &temp_k, &bidirectional_state.h, &act_three[50..])?; @@ -476,26 +477,28 @@ mod tests { use bitcoin::secp256k1::key::{PublicKey,SecretKey}; use hex; + use chain::keysinterface::EphemeralSharedSecretProducer; use ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState}; fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor { let their_node_id = PublicKey::from_slice(&hex::decode("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap(); - let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&hex::decode("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap()); + let producer = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap()); + let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, producer); assert_eq!(outbound_peer.get_act_one()[..], hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap()[..]); outbound_peer } fn get_inbound_peer_for_test_vectors() -> PeerChannelEncryptor { // transport-responder successful handshake - let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); + let node = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap()); + let ephemeral = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap()); - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], node, ephemeral.do_clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); // test vector doesn't specify the initiator static key, but it's the same as the one @@ -519,14 +522,14 @@ mod tests { #[test] fn noise_initiator_test_vectors() { - let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); + let node = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap()); { // transport-initiator successful handshake let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); + assert_eq!(outbound_peer.process_act_two(&act_two[..], node.do_clone()).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { @@ -549,7 +552,7 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); + assert!(outbound_peer.process_act_two(&act_two[..], node.do_clone()).is_err()); } { @@ -557,7 +560,7 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); + assert!(outbound_peer.process_act_two(&act_two[..], node.do_clone()).is_err()); } { @@ -565,14 +568,14 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); + assert!(outbound_peer.process_act_two(&act_two[..], node.do_clone()).is_err()); } } #[test] fn noise_responder_test_vectors() { - let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); + let node = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap()); + let ephemeral = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap()); { let _ = get_inbound_peer_for_test_vectors(); @@ -583,31 +586,31 @@ mod tests { } { // transport-responder act1 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); + assert!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).is_err()); } { // transport-responder act1 bad key serialization test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one =hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); + assert!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).is_err()); } { // transport-responder act1 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); + assert!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).is_err()); } { // transport-responder act3 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); @@ -618,30 +621,30 @@ mod tests { } { // transport-responder act3 bad MAC for ciphertext test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { // transport-responder act3 bad rs test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); } { // transport-responder act3 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); + let mut inbound_peer = PeerChannelEncryptor::new_inbound(node.do_clone()); let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); + assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], node.do_clone(), ephemeral.do_clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec(); assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); @@ -656,10 +659,10 @@ mod tests { let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); { - let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); + let node = EphemeralSharedSecretProducer::new(SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap()); let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); + assert_eq!(outbound_peer.process_act_two(&act_two[..], node.do_clone()).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); match outbound_peer.noise_state { NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index d3ac2ebe9a3..1e8847bb0a2 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -42,6 +42,7 @@ use core::convert::Infallible; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256::HashEngine as Sha256Engine; use bitcoin::hashes::{HashEngine, Hash}; +use chain::keysinterface::{EphemeralSharedSecretProducer, SharedSecretProduce}; /// Handler for BOLT1-compliant messages. pub trait CustomMessageHandler: wire::CustomMessageReader { @@ -412,7 +413,7 @@ pub struct PeerManager, peers: Mutex>, - our_node_secret: SecretKey, + shared_secret_producer: Box, ephemeral_key_midstate: Sha256Engine, custom_message_handler: CMH, @@ -456,11 +457,11 @@ impl PeerManager Self { + pub fn new_channel_only(channel_message_handler: CM, protocol_encrypt: Box, ephemeral_random_data: &[u8; 32], logger: L) -> Self { Self::new(MessageHandler { chan_handler: channel_message_handler, route_handler: IgnoringMessageHandler{}, - }, our_node_secret, ephemeral_random_data, logger, IgnoringMessageHandler{}) + }, protocol_encrypt, ephemeral_random_data, logger, IgnoringMessageHandler{}) } } @@ -476,11 +477,11 @@ impl PeerManager Self { + pub fn new_routing_only(routing_message_handler: RM, protocol_encrypt: Box, ephemeral_random_data: &[u8; 32], logger: L) -> Self { Self::new(MessageHandler { chan_handler: ErroringMessageHandler::new(), route_handler: routing_message_handler, - }, our_node_secret, ephemeral_random_data, logger, IgnoringMessageHandler{}) + }, protocol_encrypt, ephemeral_random_data, logger, IgnoringMessageHandler{}) } } @@ -503,7 +504,7 @@ impl P /// Constructs a new PeerManager with the given message handlers and node_id secret key /// ephemeral_random_data is used to derive per-connection ephemeral keys and must be /// cryptographically secure random bytes. - pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self { + pub fn new(message_handler: MessageHandler, protocol_encrypt: Box, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self { let mut ephemeral_key_midstate = Sha256::engine(); ephemeral_key_midstate.input(ephemeral_random_data); @@ -513,7 +514,7 @@ impl P peers: HashMap::new(), node_id_to_descriptor: HashMap::new() }), - our_node_secret, + shared_secret_producer: protocol_encrypt, ephemeral_key_midstate, peer_counter: AtomicCounter::new(), logger, @@ -554,7 +555,8 @@ impl P /// /// [`socket_disconnected()`]: PeerManager::socket_disconnected pub fn new_outbound_connection(&self, their_node_id: PublicKey, descriptor: Descriptor) -> Result, PeerHandleError> { - let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone(), self.get_ephemeral_key()); + let ephemeral_producer = EphemeralSharedSecretProducer::new(self.get_ephemeral_key()); + let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone(), ephemeral_producer); let res = peer_encryptor.get_act_one().to_vec(); let pending_read_buffer = [0; 50].to_vec(); // Noise act two is 50 bytes @@ -595,7 +597,7 @@ impl P /// /// [`socket_disconnected()`]: PeerManager::socket_disconnected pub fn new_inbound_connection(&self, descriptor: Descriptor) -> Result<(), PeerHandleError> { - let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.our_node_secret); + let peer_encryptor = PeerChannelEncryptor::new_inbound(self.shared_secret_producer.do_clone()); let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes let mut peers = self.peers.lock().unwrap(); @@ -851,12 +853,13 @@ impl P let next_step = peer.channel_encryptor.get_noise_step(); match next_step { NextNoiseStep::ActOne => { - let act_two = try_potential_handleerror!(peer.channel_encryptor.process_act_one_with_keys(&peer.pending_read_buffer[..], &self.our_node_secret, self.get_ephemeral_key())).to_vec(); + let ephemeral_producer = EphemeralSharedSecretProducer::new(self.get_ephemeral_key()); + let act_two = try_potential_handleerror!(peer.channel_encryptor.process_act_one_with_keys(&peer.pending_read_buffer[..], self.shared_secret_producer.do_clone(), ephemeral_producer)).to_vec(); peer.pending_outbound_buffer.push_back(act_two); peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long }, NextNoiseStep::ActTwo => { - let (act_three, their_node_id) = try_potential_handleerror!(peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], &self.our_node_secret)); + let (act_three, their_node_id) = try_potential_handleerror!(peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], self.shared_secret_producer.do_clone())); peer.pending_outbound_buffer.push_back(act_three.to_vec()); peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes peer.pending_read_is_header = true; @@ -1669,11 +1672,12 @@ mod tests { use util::test_utils; use bitcoin::secp256k1::Secp256k1; - use bitcoin::secp256k1::key::{SecretKey, PublicKey}; + use bitcoin::secp256k1::key::SecretKey; use prelude::*; use sync::{Arc, Mutex}; use core::sync::atomic::Ordering; + use chain::keysinterface::EphemeralSharedSecretProducer; #[derive(Clone)] struct FileDescriptor { @@ -1726,18 +1730,19 @@ mod tests { let mut peers = Vec::new(); for i in 0..peer_count { let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap(); + let producer = EphemeralSharedSecretProducer::new(node_secret); let ephemeral_bytes = [i as u8; 32]; let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler }; - let peer = PeerManager::new(msg_handler, node_secret, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {}); + let peer = PeerManager::new(msg_handler, producer, &ephemeral_bytes, &cfgs[i].logger, IgnoringMessageHandler {}); peers.push(peer); } peers } - fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { - let secp_ctx = Secp256k1::new(); - let a_id = PublicKey::from_secret_key(&secp_ctx, &peer_a.our_node_secret); + fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + let secp_ctx = Secp256k1::signing_only(); + let a_id = peer_a.shared_secret_producer.public_key(&secp_ctx); let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let initial_data = peer_b.new_outbound_connection(a_id, fd_b.clone()).unwrap(); @@ -1760,8 +1765,8 @@ mod tests { establish_connection(&peers[0], &peers[1]); assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 1); - let secp_ctx = Secp256k1::new(); - let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret); + let secp_ctx = Secp256k1::signing_only(); + let their_id = peers[1].shared_secret_producer.public_key(&secp_ctx); chan_handler.pending_events.lock().unwrap().push(events::MessageSendEvent::HandleError { node_id: their_id, @@ -1844,8 +1849,9 @@ mod tests { cfgs[1].routing_handler.request_full_sync.store(true, Ordering::Release); let peers = create_network(2, &cfgs); - let secp_ctx = Secp256k1::new(); - let a_id = PublicKey::from_secret_key(&secp_ctx, &peers[0].our_node_secret); + let secp_ctx = Secp256k1::signing_only(); + let a_id = peers[0].shared_secret_producer.public_key(&secp_ctx); + let mut fd_a = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let mut fd_b = FileDescriptor { fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())) }; let initial_data = peers[1].new_outbound_connection(a_id, fd_b.clone()).unwrap(); diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 27c2d9de874..d7f77ed95e9 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -19,7 +19,7 @@ use chain::transaction::OutPoint; use chain::keysinterface; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; -use ln::msgs::OptionalField; +use ln::msgs::{OptionalField, UnsignedChannelUpdate, UnsignedNodeAnnouncement}; use ln::script::ShutdownScript; use routing::scoring::FixedPenaltyScorer; use util::enforcing_trait_impls::{EnforcingSigner, EnforcementState}; @@ -35,7 +35,8 @@ use bitcoin::blockdata::block::BlockHeader; use bitcoin::network::constants::Network; use bitcoin::hash_types::{BlockHash, Txid}; -use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, Signature}; +use bitcoin::secp256k1::ecdh::SharedSecret; +use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, Signature, All}; use bitcoin::secp256k1::recovery::RecoverableSignature; use regex; @@ -47,7 +48,7 @@ use sync::{Mutex, Arc}; use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use core::{cmp, mem}; use bitcoin::bech32::u5; -use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial}; +use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, SharedSecretProduce}; pub struct TestVecWriter(pub Vec); impl Writer for TestVecWriter { @@ -70,7 +71,7 @@ pub struct OnlyReadsKeysInterface {} impl keysinterface::KeysInterface for OnlyReadsKeysInterface { type Signer = EnforcingSigner; - fn get_node_secret(&self, _recipient: Recipient) -> Result { unreachable!(); } + fn get_shared_secret_producer(&self) -> Box { unreachable!(); } fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!(); } fn get_destination_script(&self) -> Script { unreachable!(); } fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!(); } @@ -89,6 +90,14 @@ impl keysinterface::KeysInterface for OnlyReadsKeysInterface { )) } fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result { unreachable!(); } + + fn sign_node_announcement(&self, _msg: &UnsignedNodeAnnouncement, _secp_ctx: &Secp256k1) -> Result { unreachable!() } + + fn sign_channel_update(&self, _msg: &UnsignedChannelUpdate, _secp_ctx: &Secp256k1) -> Result { unreachable!() } + + fn shared_secret(&self, _recipient: Recipient, _other: &PublicKey) -> Result { unreachable!() } + + fn get_node_key(&self, _recipient: Recipient, _secp_ctx: &Secp256k1) -> Result { unreachable!() } } pub struct TestChainMonitor<'a> { @@ -486,9 +495,10 @@ pub struct TestKeysInterface { impl keysinterface::KeysInterface for TestKeysInterface { type Signer = EnforcingSigner; - fn get_node_secret(&self, recipient: Recipient) -> Result { - self.backing.get_node_secret(recipient) + fn get_shared_secret_producer(&self) -> Box { + self.backing.get_shared_secret_producer() } + fn get_inbound_payment_key_material(&self) -> keysinterface::KeyMaterial { self.backing.get_inbound_payment_key_material() } @@ -521,7 +531,8 @@ impl keysinterface::KeysInterface for TestKeysInterface { fn read_chan_signer(&self, buffer: &[u8]) -> Result { let mut reader = io::Cursor::new(buffer); - let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret(Recipient::Node).unwrap())?; + let node_secret = self.backing.get_node_secret(Recipient::Node).unwrap(); + let inner: InMemorySigner = ReadableArgs::read(&mut reader, node_secret)?; let state = self.make_enforcement_state_cell(inner.commitment_seed); Ok(EnforcingSigner::new_with_revoked( @@ -534,6 +545,22 @@ impl keysinterface::KeysInterface for TestKeysInterface { fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result { self.backing.sign_invoice(hrp_bytes, invoice_data, recipient) } + + fn sign_node_announcement(&self, msg: &UnsignedNodeAnnouncement, secp_ctx: &Secp256k1) -> Result { + self.backing.sign_node_announcement(msg, secp_ctx) + } + + fn sign_channel_update(&self, msg: &UnsignedChannelUpdate, secp_ctx: &Secp256k1) -> Result { + self.backing.sign_channel_update(msg, secp_ctx) + } + + fn shared_secret(&self, recipient: Recipient, other: &PublicKey) -> Result { + self.backing.shared_secret(recipient, other) + } + + fn get_node_key(&self, recipient: Recipient, secp_ctx: &Secp256k1) -> Result { + self.backing.get_node_key(recipient, secp_ctx) + } } impl TestKeysInterface {