From 4d273ea6131fac94e3eed797b29b15a4e0c97247 Mon Sep 17 00:00:00 2001 From: Simon Wicky Date: Mon, 11 Mar 2024 15:28:01 +0100 Subject: [PATCH] change to psk structure and port checking to allow same ip --- .../client-libs/mixnet-client/src/client.rs | 1 - common/nymnoise/src/lib.rs | 50 ++++++------------- common/topology/src/lib.rs | 13 ++++- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/common/client-libs/mixnet-client/src/client.rs b/common/client-libs/mixnet-client/src/client.rs index b95810d121..6d53deccd5 100644 --- a/common/client-libs/mixnet-client/src/client.rs +++ b/common/client-libs/mixnet-client/src/client.rs @@ -135,7 +135,6 @@ impl Client { Default::default(), &topology, epoch_id, - local_identity.public_key(), local_identity.private_key(), ) .await diff --git a/common/nymnoise/src/lib.rs b/common/nymnoise/src/lib.rs index ded97850e7..c5b28262a3 100644 --- a/common/nymnoise/src/lib.rs +++ b/common/nymnoise/src/lib.rs @@ -15,10 +15,11 @@ pub mod connection; pub mod error; pub mod stream; +const NOISE_PSK_PREFIX: &[u8] = b"NYMTECH_NOISE_dQw4w9WgXcQ"; + pub async fn upgrade_noise_initiator( conn: TcpStream, pattern: NoisePattern, - local_public_key: Option<&encryption::PublicKey>, local_private_key: &encryption::PrivateKey, remote_pub_key: &encryption::PublicKey, epoch: u32, @@ -27,9 +28,7 @@ pub async fn upgrade_noise_initiator( //In case the local key cannot be known by the remote party, e.g. in a client-gateway connection let secret = [ - local_public_key - .map(|k| k.to_bytes().to_vec()) - .unwrap_or_default(), + NOISE_PSK_PREFIX.to_vec(), remote_pub_key.to_bytes().to_vec(), epoch.to_be_bytes().to_vec(), ] @@ -52,7 +51,6 @@ pub async fn upgrade_noise_initiator_with_topology( pattern: NoisePattern, topology: &NymTopology, epoch: u32, - local_public_key: &encryption::PublicKey, local_private_key: &encryption::PrivateKey, ) -> Result { //Get init material @@ -61,7 +59,7 @@ pub async fn upgrade_noise_initiator_with_topology( Error::Prereq(Prerequisite::RemotePublicKey) })?; - let remote_pub_key = match topology.find_node_key_by_mix_host(responder_addr) { + let remote_pub_key = match topology.find_node_key_by_mix_host(responder_addr, true) { Ok(Some(key)) => encryption::PublicKey::from_base58_string(key)?, Ok(None) => { warn!( @@ -79,15 +77,7 @@ pub async fn upgrade_noise_initiator_with_topology( } }; - upgrade_noise_initiator( - conn, - pattern, - Some(local_public_key), - local_private_key, - &remote_pub_key, - epoch, - ) - .await + upgrade_noise_initiator(conn, pattern, local_private_key, &remote_pub_key, epoch).await } pub async fn upgrade_noise_responder( @@ -95,16 +85,13 @@ pub async fn upgrade_noise_responder( pattern: NoisePattern, local_public_key: &encryption::PublicKey, local_private_key: &encryption::PrivateKey, - remote_pub_key: Option<&encryption::PublicKey>, epoch: u32, ) -> Result { trace!("Perform Noise Handshake, responder side"); //If the remote_key cannot be kwnown, e.g. in a client-gateway connection let secret = [ - remote_pub_key - .map(|k| k.to_bytes().to_vec()) - .unwrap_or_default(), + NOISE_PSK_PREFIX.to_vec(), local_public_key.to_bytes().to_vec(), epoch.to_be_bytes().to_vec(), ] @@ -139,31 +126,26 @@ pub async fn upgrade_noise_responder_with_topology( }; //SW : for private gateway, we could try to perform the handshake without that key? - let remote_pub_key = match topology.find_node_key_by_mix_host(initiator_addr) { - Ok(Some(key)) => encryption::PublicKey::from_base58_string(key)?, + match topology.find_node_key_by_mix_host(initiator_addr, false) { + Ok(Some(_)) => { + //Existing node supporting Noise + upgrade_noise_responder(conn, pattern, local_public_key, local_private_key, epoch).await + } Ok(None) => { + //Existing node not supporting Noise yet warn!( "{:?} can't speak Noise yet, falling back to TCP", initiator_addr ); - return Ok(Connection::Tcp(conn)); + Ok(Connection::Tcp(conn)) } Err(_) => { + //Non existing node error!( "Cannot find public key for node with address {:?}", initiator_addr ); //Do we still pursue a TCP connection with that node or not? - return Err(Error::Prereq(Prerequisite::RemotePublicKey).into()); + Err(Error::Prereq(Prerequisite::RemotePublicKey).into()) } - }; - - upgrade_noise_responder( - conn, - pattern, - local_public_key, - local_private_key, - Some(&remote_pub_key), - epoch, - ) - .await + } } diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 2852884280..ebc002a877 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -189,6 +189,7 @@ impl NymTopology { pub fn find_node_key_by_mix_host( &self, mix_host: SocketAddr, + check_port: bool, ) -> Result, NymTopologyError> { for node in self.described_nodes.iter() { let (sphinx_key, socket_addresses, description) = match node { @@ -208,8 +209,16 @@ impl NymTopology { } }; if let Some(sock_addr) = socket_addresses { - let ip_addresses = sock_addr.iter().map(|addr| addr.ip()).collect::>(); - if ip_addresses.contains(&mix_host.ip()) { + let existing_node = if check_port { + //Initiator side, we know the port should be correct as well + sock_addr.contains(&mix_host) + } else { + //responder side, we don't know the port. + //SW This can lead to some troubles if two nodes shares the same IP and one support Noise but not the other. This in only for the progressive update though + let ip_addresses = sock_addr.iter().map(|addr| addr.ip()).collect::>(); + ip_addresses.contains(&mix_host.ip()) + }; + if existing_node { //we have our node if let Some(d) = description { if d.noise_information.supported {