mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 15:02:20 +01:00
Stop using rng in peer_channel_encryptor to generate ephemeral keys
This removes the bulk of our reliance on the rand crate in non-test envs, paving a way towards a syscall-less rust-lightning and WASM. Since this is a breaking change for full_stack_target (and several fuzz targets), go ahead and make other changes to make things more distinct.
This commit is contained in:
parent
1650992ec2
commit
084ef28708
6 changed files with 121 additions and 114 deletions
|
@ -37,7 +37,7 @@ use lightning::ln::channelmonitor::{ChannelMonitorUpdateErr, HTLCUpdate};
|
|||
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage};
|
||||
use lightning::ln::router::{Route, RouteHop};
|
||||
use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, HandleError, UpdateAddHTLC, LocalFeatures};
|
||||
use lightning::util::{reset_rng_state, fill_bytes, events};
|
||||
use lightning::util::{reset_rng_state, events};
|
||||
use lightning::util::logger::Logger;
|
||||
use lightning::util::config::UserConfig;
|
||||
use lightning::util::events::{EventsProvider, MessageSendEventsProvider};
|
||||
|
@ -52,6 +52,7 @@ use secp256k1::Secp256k1;
|
|||
use std::cmp::Ordering;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::{Arc,Mutex};
|
||||
use std::sync::atomic;
|
||||
use std::io::Cursor;
|
||||
|
||||
struct FuzzEstimator {}
|
||||
|
@ -91,6 +92,8 @@ impl channelmonitor::ManyChannelMonitor for TestChannelMonitor {
|
|||
|
||||
struct KeyProvider {
|
||||
node_id: u8,
|
||||
session_id: atomic::AtomicU8,
|
||||
channel_id: atomic::AtomicU8,
|
||||
}
|
||||
impl KeysInterface for KeyProvider {
|
||||
fn get_node_secret(&self) -> SecretKey {
|
||||
|
@ -121,15 +124,13 @@ impl KeysInterface for KeyProvider {
|
|||
}
|
||||
|
||||
fn get_session_key(&self) -> SecretKey {
|
||||
let mut session_key = [0; 32];
|
||||
fill_bytes(&mut session_key);
|
||||
SecretKey::from_slice(&session_key).unwrap()
|
||||
let id = self.session_id.fetch_add(1, atomic::Ordering::Relaxed);
|
||||
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, id, 10, self.node_id]).unwrap()
|
||||
}
|
||||
|
||||
fn get_channel_id(&self) -> [u8; 32] {
|
||||
let mut channel_id = [0; 32];
|
||||
fill_bytes(&mut channel_id);
|
||||
channel_id
|
||||
let id = self.channel_id.fetch_add(1, atomic::Ordering::Relaxed);
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, id, 11, self.node_id]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +147,7 @@ pub fn do_test(data: &[u8]) {
|
|||
let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger)));
|
||||
let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone()));
|
||||
|
||||
let keys_manager = Arc::new(KeyProvider { node_id: $node_id });
|
||||
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, session_id: atomic::AtomicU8::new(0), channel_id: atomic::AtomicU8::new(0) });
|
||||
let mut config = UserConfig::new();
|
||||
config.channel_options.fee_proportional_millionths = 0;
|
||||
config.channel_options.announced_channel = true;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -34,13 +34,17 @@ pub fn do_test(data: &[u8]) {
|
|||
Ok(key) => key,
|
||||
Err(_) => return,
|
||||
};
|
||||
let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) {
|
||||
Ok(key) => key,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let mut crypter = if get_slice!(1)[0] != 0 {
|
||||
let their_pubkey = match PublicKey::from_slice(get_slice!(33)) {
|
||||
Ok(key) => key,
|
||||
Err(_) => return,
|
||||
};
|
||||
let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey);
|
||||
let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key);
|
||||
crypter.get_act_one();
|
||||
match crypter.process_act_two(get_slice!(50), &our_network_key) {
|
||||
Ok(_) => {},
|
||||
|
@ -50,7 +54,7 @@ pub fn do_test(data: &[u8]) {
|
|||
crypter
|
||||
} else {
|
||||
let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key);
|
||||
match crypter.process_act_one_with_key(get_slice!(50), &our_network_key) {
|
||||
match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key) {
|
||||
Ok(_) => {},
|
||||
Err(_) => return,
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsPro
|
|||
use util::errors::APIError;
|
||||
use util::ser::{Writeable, ReadableArgs};
|
||||
use util::config::UserConfig;
|
||||
use util::rng;
|
||||
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
|
@ -44,6 +43,8 @@ use std::sync::Arc;
|
|||
use std::sync::atomic::Ordering;
|
||||
use std::mem;
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use ln::functional_test_utils::*;
|
||||
|
||||
#[test]
|
||||
|
@ -1191,7 +1192,6 @@ fn duplicate_htlc_test() {
|
|||
}
|
||||
|
||||
fn do_channel_reserve_test(test_recv: bool) {
|
||||
use util::rng;
|
||||
use std::sync::atomic::Ordering;
|
||||
use ln::msgs::HandleError;
|
||||
|
||||
|
@ -1308,7 +1308,8 @@ fn do_channel_reserve_test(test_recv: bool) {
|
|||
let secp_ctx = Secp256k1::new();
|
||||
let session_priv = SecretKey::from_slice(&{
|
||||
let mut session_key = [0; 32];
|
||||
rng::fill_bytes(&mut session_key);
|
||||
let mut rng = thread_rng();
|
||||
rng.fill_bytes(&mut session_key);
|
||||
session_key
|
||||
}).expect("RNG is bad!");
|
||||
|
||||
|
@ -5082,7 +5083,8 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() {
|
|||
|
||||
let session_priv = SecretKey::from_slice(&{
|
||||
let mut session_key = [0; 32];
|
||||
rng::fill_bytes(&mut session_key);
|
||||
let mut rng = thread_rng();
|
||||
rng.fill_bytes(&mut session_key);
|
||||
session_key
|
||||
}).expect("RNG is bad!");
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use secp256k1::ecdh::SharedSecret;
|
|||
use secp256k1;
|
||||
|
||||
use util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
|
||||
use util::{byte_utils,rng};
|
||||
use util::byte_utils;
|
||||
|
||||
// Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256")
|
||||
const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1];
|
||||
|
@ -70,12 +70,8 @@ pub struct PeerChannelEncryptor {
|
|||
}
|
||||
|
||||
impl PeerChannelEncryptor {
|
||||
pub fn new_outbound(their_node_id: PublicKey) -> PeerChannelEncryptor {
|
||||
let mut key = [0u8; 32];
|
||||
rng::fill_bytes(&mut key);
|
||||
|
||||
pub fn new_outbound(their_node_id: PublicKey, ephemeral_key: SecretKey) -> PeerChannelEncryptor {
|
||||
let secp_ctx = Secp256k1::signing_only();
|
||||
let sec_key = SecretKey::from_slice(&key).unwrap(); //TODO: nicer rng-is-bad error message
|
||||
|
||||
let mut sha = Sha256::engine();
|
||||
sha.input(&NOISE_H);
|
||||
|
@ -88,7 +84,7 @@ impl PeerChannelEncryptor {
|
|||
noise_state: NoiseState::InProgress {
|
||||
state: NoiseStep::PreActOne,
|
||||
directional_state: DirectionalNoiseState::Outbound {
|
||||
ie: sec_key,
|
||||
ie: ephemeral_key,
|
||||
},
|
||||
bidirectional_state: BidirectionalNoiseState {
|
||||
h: h,
|
||||
|
@ -243,8 +239,7 @@ impl PeerChannelEncryptor {
|
|||
}
|
||||
}
|
||||
|
||||
// Separated for testing:
|
||||
fn process_act_one_with_ephemeral_key(&mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey) -> Result<[u8; 50], HandleError> {
|
||||
pub fn process_act_one_with_keys(&mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey) -> Result<[u8; 50], HandleError> {
|
||||
assert_eq!(act_one.len(), 50);
|
||||
|
||||
match self.noise_state {
|
||||
|
@ -271,15 +266,6 @@ impl PeerChannelEncryptor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn process_act_one_with_key(&mut self, act_one: &[u8], our_node_secret: &SecretKey) -> Result<[u8; 50], HandleError> {
|
||||
assert_eq!(act_one.len(), 50);
|
||||
|
||||
let mut key = [0u8; 32];
|
||||
rng::fill_bytes(&mut key);
|
||||
let our_ephemeral_key = SecretKey::from_slice(&key).unwrap(); //TODO: nicer rng-is-bad error message
|
||||
self.process_act_one_with_ephemeral_key(act_one, our_node_secret, our_ephemeral_key)
|
||||
}
|
||||
|
||||
pub fn process_act_two(&mut self, act_two: &[u8], our_node_secret: &SecretKey) -> Result<([u8; 66], PublicKey), HandleError> {
|
||||
assert_eq!(act_two.len(), 50);
|
||||
|
||||
|
@ -485,21 +471,12 @@ mod tests {
|
|||
|
||||
use hex;
|
||||
|
||||
use ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState,DirectionalNoiseState};
|
||||
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);
|
||||
match outbound_peer.noise_state {
|
||||
NoiseState::InProgress { state: _, ref mut directional_state, bidirectional_state: _ } => {
|
||||
*directional_state = DirectionalNoiseState::Outbound { // overwrite ie...
|
||||
ie: SecretKey::from_slice(&hex::decode("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap(),
|
||||
};
|
||||
},
|
||||
_ => panic!()
|
||||
}
|
||||
|
||||
let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&hex::decode("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap());
|
||||
assert_eq!(outbound_peer.get_act_one()[..], hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap()[..]);
|
||||
outbound_peer
|
||||
}
|
||||
|
@ -566,7 +543,7 @@ mod tests {
|
|||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
|
||||
assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.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
|
||||
|
@ -594,28 +571,28 @@ mod tests {
|
|||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
|
||||
assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
|
||||
}
|
||||
{
|
||||
// transport-responder act1 bad key serialization test
|
||||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one =hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
|
||||
assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
|
||||
}
|
||||
{
|
||||
// transport-responder act1 bad MAC test
|
||||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec();
|
||||
assert!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
|
||||
assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
|
||||
}
|
||||
{
|
||||
// transport-responder act3 bad version test
|
||||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
|
||||
assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.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());
|
||||
|
@ -629,7 +606,7 @@ mod tests {
|
|||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
|
||||
assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.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());
|
||||
|
@ -639,7 +616,7 @@ mod tests {
|
|||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
|
||||
assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.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());
|
||||
|
@ -649,7 +626,7 @@ mod tests {
|
|||
let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
|
||||
assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.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());
|
||||
|
@ -692,7 +669,7 @@ mod tests {
|
|||
inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
|
||||
|
||||
let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
|
||||
assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
|
||||
assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.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
|
||||
|
|
|
@ -20,6 +20,10 @@ use std::sync::{Arc, Mutex};
|
|||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::{cmp,error,hash,fmt};
|
||||
|
||||
use bitcoin_hashes::sha256::Hash as Sha256;
|
||||
use bitcoin_hashes::sha256::HashEngine as Sha256Engine;
|
||||
use bitcoin_hashes::{HashEngine, Hash};
|
||||
|
||||
/// Provides references to trait impls which handle different types of messages.
|
||||
pub struct MessageHandler {
|
||||
/// A message handler which handles messages specific to channels. Usually this is just a
|
||||
|
@ -151,12 +155,25 @@ impl<Descriptor: SocketDescriptor> PeerHolder<Descriptor> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
|
||||
fn _check_usize_is_32_or_64() {
|
||||
// See below, less than 32 bit pointers may be unsafe here!
|
||||
unsafe { mem::transmute::<*const usize, [u8; 4]>(panic!()); }
|
||||
}
|
||||
|
||||
/// A PeerManager manages a set of peers, described by their SocketDescriptor and marshalls socket
|
||||
/// events into messages which it passes on to its MessageHandlers.
|
||||
pub struct PeerManager<Descriptor: SocketDescriptor> {
|
||||
message_handler: MessageHandler,
|
||||
peers: Mutex<PeerHolder<Descriptor>>,
|
||||
our_node_secret: SecretKey,
|
||||
ephemeral_key_midstate: Sha256Engine,
|
||||
|
||||
// Usize needs to be at least 32 bits to avoid overflowing both low and high. If usize is 64
|
||||
// bits we will never realistically count into high:
|
||||
peer_counter_low: AtomicUsize,
|
||||
peer_counter_high: AtomicUsize,
|
||||
|
||||
initial_syncs_sent: AtomicUsize,
|
||||
logger: Arc<Logger>,
|
||||
}
|
||||
|
@ -188,7 +205,12 @@ const INITIAL_SYNCS_TO_SEND: usize = 5;
|
|||
/// PeerIds may repeat, but only after disconnect_event() has been called.
|
||||
impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
||||
/// Constructs a new PeerManager with the given message handlers and node_id secret key
|
||||
pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey, logger: Arc<Logger>) -> PeerManager<Descriptor> {
|
||||
/// 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: Arc<Logger>) -> PeerManager<Descriptor> {
|
||||
let mut ephemeral_key_midstate = Sha256::engine();
|
||||
ephemeral_key_midstate.input(ephemeral_random_data);
|
||||
|
||||
PeerManager {
|
||||
message_handler: message_handler,
|
||||
peers: Mutex::new(PeerHolder {
|
||||
|
@ -197,6 +219,9 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
|||
node_id_to_descriptor: HashMap::new()
|
||||
}),
|
||||
our_node_secret: our_node_secret,
|
||||
ephemeral_key_midstate,
|
||||
peer_counter_low: AtomicUsize::new(0),
|
||||
peer_counter_high: AtomicUsize::new(0),
|
||||
initial_syncs_sent: AtomicUsize::new(0),
|
||||
logger,
|
||||
}
|
||||
|
@ -217,6 +242,19 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
|||
}).collect()
|
||||
}
|
||||
|
||||
fn get_ephemeral_key(&self) -> SecretKey {
|
||||
let mut ephemeral_hash = self.ephemeral_key_midstate.clone();
|
||||
let low = self.peer_counter_low.fetch_add(1, Ordering::AcqRel);
|
||||
let high = if low == 0 {
|
||||
self.peer_counter_high.fetch_add(1, Ordering::AcqRel)
|
||||
} else {
|
||||
self.peer_counter_high.load(Ordering::Acquire)
|
||||
};
|
||||
ephemeral_hash.input(&byte_utils::le64_to_array(low as u64));
|
||||
ephemeral_hash.input(&byte_utils::le64_to_array(high as u64));
|
||||
SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).into_inner()).expect("You broke SHA-256!")
|
||||
}
|
||||
|
||||
/// Indicates a new outbound connection has been established to a node with the given node_id.
|
||||
/// Note that if an Err is returned here you MUST NOT call disconnect_event for the new
|
||||
/// descriptor but must disconnect the connection immediately.
|
||||
|
@ -226,7 +264,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
|||
/// Panics if descriptor is duplicative with some other descriptor which has not yet has a
|
||||
/// disconnect_event.
|
||||
pub fn new_outbound_connection(&self, their_node_id: PublicKey, descriptor: Descriptor) -> Result<Vec<u8>, PeerHandleError> {
|
||||
let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone());
|
||||
let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone(), self.get_ephemeral_key());
|
||||
let res = peer_encryptor.get_act_one().to_vec();
|
||||
let pending_read_buffer = [0; 50].to_vec(); // Noise act two is 50 bytes
|
||||
|
||||
|
@ -517,7 +555,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
|||
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_key(&peer.pending_read_buffer[..], &self.our_node_secret)).to_vec();
|
||||
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();
|
||||
peer.pending_outbound_buffer.push_back(act_two);
|
||||
peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long
|
||||
},
|
||||
|
@ -1096,6 +1134,8 @@ mod tests {
|
|||
let mut peers = Vec::new();
|
||||
let mut rng = thread_rng();
|
||||
let logger : Arc<Logger> = Arc::new(test_utils::TestLogger::new());
|
||||
let mut ephemeral_bytes = [0; 32];
|
||||
rng.fill_bytes(&mut ephemeral_bytes);
|
||||
|
||||
for _ in 0..peer_count {
|
||||
let chan_handler = test_utils::TestChannelMessageHandler::new();
|
||||
|
@ -1106,7 +1146,7 @@ mod tests {
|
|||
SecretKey::from_slice(&key_slice).unwrap()
|
||||
};
|
||||
let msg_handler = MessageHandler { chan_handler: Arc::new(chan_handler), route_handler: Arc::new(router) };
|
||||
let peer = PeerManager::new(msg_handler, node_id, Arc::clone(&logger));
|
||||
let peer = PeerManager::new(msg_handler, node_id, &ephemeral_bytes, Arc::clone(&logger));
|
||||
peers.push(peer);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue