From 044251d60fc7281be411e8bb2343da1fbb658bda Mon Sep 17 00:00:00 2001 From: Simon Wicky Date: Fri, 21 Jul 2023 14:41:31 +0200 Subject: [PATCH] bring private key to the noise handshake. still does nothing though --- Cargo.lock | 1 + common/client-libs/mixnet-client/Cargo.toml | 1 + .../client-libs/mixnet-client/src/client.rs | 11 +++- .../mixnet-client/src/forwarder.rs | 4 +- common/nymnoise/src/lib.rs | 50 +++++++++++++------ common/topology/src/lib.rs | 17 +++++++ .../receiver/connection_handler.rs | 8 ++- gateway/src/node/mod.rs | 2 + .../node/listener/connection_handler/mod.rs | 7 ++- mixnode/src/node/mod.rs | 12 ++++- 10 files changed, 90 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3c07b4e20..2a4f9f9bd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4008,6 +4008,7 @@ dependencies = [ "futures", "log", "nym-client-core", + "nym-crypto", "nym-noise", "nym-sphinx", "nym-task", diff --git a/common/client-libs/mixnet-client/Cargo.toml b/common/client-libs/mixnet-client/Cargo.toml index 5a34648b5f..7918344699 100644 --- a/common/client-libs/mixnet-client/Cargo.toml +++ b/common/client-libs/mixnet-client/Cargo.toml @@ -17,3 +17,4 @@ nym-sphinx = { path = "../../nymsphinx" } nym-task = { path = "../../task" } nym-client-core = { path = "../../client-core" } nym-noise = { path = "../../nymnoise"} +nym-crypto = { path = "../../crypto" } diff --git a/common/client-libs/mixnet-client/src/client.rs b/common/client-libs/mixnet-client/src/client.rs index ec1a51f4bd..70ac5e1da7 100644 --- a/common/client-libs/mixnet-client/src/client.rs +++ b/common/client-libs/mixnet-client/src/client.rs @@ -5,6 +5,8 @@ use futures::channel::mpsc; use futures::StreamExt; use log::*; use nym_client_core::client::topology_control::accessor::TopologyAccessor; +use nym_crypto::asymmetric::identity; +use crate::client::identity::SECRET_KEY_LENGTH; use nym_noise::upgrade_noise_initiator; use nym_sphinx::addressing::nodes::NymNodeRoutingAddress; use nym_sphinx::framing::codec::NymCodec; @@ -62,6 +64,7 @@ pub struct Client { conn_new: HashMap, config: Config, topology_access: TopologyAccessor, + private_id_key : [u8; SECRET_KEY_LENGTH], } struct ConnectionSender { @@ -79,11 +82,12 @@ impl ConnectionSender { } impl Client { - pub fn new(config: Config, topology_access: TopologyAccessor) -> Client { + pub fn new(config: Config, topology_access: TopologyAccessor, private_id_key: &identity::PrivateKey) -> Client { Client { conn_new: HashMap::new(), config, topology_access, + private_id_key: private_id_key.to_bytes(), } } @@ -93,6 +97,7 @@ impl Client { connection_timeout: Duration, current_reconnection: &AtomicU32, topology_access: TopologyAccessor, + local_private_key: &[u8], ) { let connection_fut = TcpStream::connect(address); @@ -112,7 +117,7 @@ impl Client { } }; - let noise_stream = match upgrade_noise_initiator(stream, topology_ref) { + let noise_stream = match upgrade_noise_initiator(stream, topology_ref, local_private_key) { Ok(noise_stream) => noise_stream, Err(err) => { error!("Failed to perform Noise handshake with {address} - {err}"); @@ -198,6 +203,7 @@ impl Client { let initial_connection_timeout = self.config.initial_connection_timeout; let topology_access_clone = self.topology_access.clone(); + let local_private_key = self.private_id_key.clone(); tokio::spawn(async move { // before executing the manager, wait for what was specified, if anything @@ -212,6 +218,7 @@ impl Client { initial_connection_timeout, ¤t_reconnection_attempt, topology_access_clone, + &local_private_key, ) .await }); diff --git a/common/client-libs/mixnet-client/src/forwarder.rs b/common/client-libs/mixnet-client/src/forwarder.rs index 020c79bb97..0093f702f5 100644 --- a/common/client-libs/mixnet-client/src/forwarder.rs +++ b/common/client-libs/mixnet-client/src/forwarder.rs @@ -8,6 +8,7 @@ use log::*; use nym_client_core::client::topology_control::accessor::TopologyAccessor; use nym_sphinx::forwarding::packet::MixPacket; use std::time::Duration; +use nym_crypto::asymmetric::identity; pub type MixForwardingSender = mpsc::UnboundedSender; type MixForwardingReceiver = mpsc::UnboundedReceiver; @@ -28,6 +29,7 @@ impl PacketForwarder { maximum_connection_buffer_size: usize, use_legacy_version: bool, topology_access: TopologyAccessor, + private_id_key: &identity::PrivateKey, shutdown: nym_task::TaskClient, ) -> (PacketForwarder, MixForwardingSender) { let client_config = Config::new( @@ -42,7 +44,7 @@ impl PacketForwarder { ( PacketForwarder { - mixnet_client: Client::new(client_config, topology_access), + mixnet_client: Client::new(client_config, topology_access, private_id_key), packet_receiver, shutdown, }, diff --git a/common/nymnoise/src/lib.rs b/common/nymnoise/src/lib.rs index 28e4f31549..66b42e0a36 100644 --- a/common/nymnoise/src/lib.rs +++ b/common/nymnoise/src/lib.rs @@ -4,24 +4,19 @@ use log::*; use nym_topology::NymTopology; use pin_project::pin_project; +use snow::error::Prerequisite; +use snow::Builder; use snow::Error as NoiseError; -use snow::{params::NoiseParams, Builder, TransportState}; use std::pin::Pin; use tokio::{ io::{AsyncRead, AsyncWrite}, net::TcpStream, }; -const NOISE_HS_PATTERN: &str = "Noise_XK_25519_AESGCM_SHA256"; +const NOISE_HS_PATTERN: &str = "Noise_XKpsk3_25519_AESGCM_SHA256"; + +static SECRET: &[u8] = b"i don't care for fidget spinners"; -static PRIV_KEY: &[u8] = &[ - 208, 217, 103, 180, 100, 15, 242, 137, 184, 247, 248, 193, 21, 66, 177, 79, 90, 131, 15, 134, - 145, 4, 45, 37, 215, 253, 227, 172, 113, 73, 97, 125, -]; -static PUB_KEY: &[u8] = &[ - 126, 100, 176, 138, 253, 249, 136, 187, 191, 200, 120, 5, 62, 218, 218, 73, 220, 60, 1, 179, - 49, 92, 253, 43, 91, 109, 18, 6, 88, 235, 123, 78, -]; /// Wrapper around a TcpStream //TODO SW : add psk3 to the protocol, requires topology at the receiver #[pin_project] @@ -80,24 +75,47 @@ impl AsyncWrite for NoiseStream { pub fn upgrade_noise_initiator( conn: TcpStream, topology: &NymTopology, + local_private_key: &[u8], ) -> Result { debug!("Perform Noise Handshake, initiator side"); let builder = Builder::new(NOISE_HS_PATTERN.parse().unwrap()); //This cannot fail, hardcoded pattern must be correct + //Get init material + let responder_addr = match conn.peer_addr() { + Ok(addr) => addr, + Err(err) => { + error!("Unable to extract peer address from connection - {err}"); + return Err(Prerequisite::RemotePublicKey.into()); + } + }; + let remote_pub_key = match topology.find_node_key_by_mix_host(responder_addr) { + Some(pub_key) => pub_key.to_bytes(), + None => { + error!( + "Cannot find public key for node with address {:?}", + responder_addr + ); + return Err(Prerequisite::RemotePublicKey.into()); + } + }; + let mut _handshake = builder - .local_private_key(PRIV_KEY) - .remote_public_key(PUB_KEY) - //.psk(3, key) + .local_private_key(local_private_key) + .remote_public_key(&remote_pub_key) + .psk(3, SECRET) .build_initiator()?; Ok(NoiseStream::new(conn)) } -pub fn upgrade_noise_responder(conn: TcpStream) -> Result { +pub fn upgrade_noise_responder( + conn: TcpStream, + local_private_key: &[u8], +) -> Result { debug!("Perform Noise Handshake, responder side"); let builder = Builder::new(NOISE_HS_PATTERN.parse().unwrap()); //This cannot fail, hardcoded pattern must be correct let mut _handshake = builder - .local_private_key(PRIV_KEY) - //.psk(3, key) + .local_private_key(local_private_key) + .psk(3, SECRET) .build_responder()?; Ok(NoiseStream::new(conn)) } diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 45eb2d9d7d..517b3beaf4 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -3,6 +3,7 @@ use crate::filter::VersionFilterable; use log::warn; +use nym_crypto::asymmetric::identity; use nym_mixnet_contract_common::mixnode::MixNodeDetails; use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; use nym_sphinx_addressing::nodes::NodeIdentity; @@ -107,6 +108,22 @@ impl NymTopology { None } + pub fn find_node_key_by_mix_host(&self, mix_host: SocketAddr) -> Option<&identity::PublicKey> { + for node in self.gateways.iter() { + if node.mix_host == mix_host { + return Some(&node.identity_key); + } + } + for nodes in self.mixes.values() { + for node in nodes { + if node.mix_host == mix_host { + return Some(&node.identity_key); + } + } + } + None + } + pub fn find_gateway(&self, gateway_identity: IdentityKeyRef) -> Option<&gateway::Node> { self.gateways .iter() diff --git a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs index 7a1d9578fe..3c5d17c2d8 100644 --- a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs +++ b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs @@ -3,11 +3,13 @@ use crate::node::client_handling::active_clients::ActiveClientsStore; use crate::node::client_handling::websocket::message_receiver::MixMessageSender; +use crate::node::identity::SECRET_KEY_LENGTH; use crate::node::mixnet_handling::receiver::packet_processing::PacketProcessor; use crate::node::storage::error::StorageError; use crate::node::storage::Storage; use futures::StreamExt; use log::*; +use nym_crypto::asymmetric::identity; use nym_mixnet_client::forwarder::MixForwardingSender; use nym_mixnode_common::packet_processor::processor::ProcessedFinalHop; use nym_noise::upgrade_noise_responder; @@ -32,6 +34,7 @@ pub(crate) struct ConnectionHandler { active_clients_store: ActiveClientsStore, storage: St, ack_sender: MixForwardingSender, + private_identity_key: [u8; SECRET_KEY_LENGTH], } impl Clone for ConnectionHandler { @@ -50,6 +53,7 @@ impl Clone for ConnectionHandler { active_clients_store: self.active_clients_store.clone(), storage: self.storage.clone(), ack_sender: self.ack_sender.clone(), + private_identity_key: self.private_identity_key.clone(), } } } @@ -60,6 +64,7 @@ impl ConnectionHandler { storage: St, ack_sender: MixForwardingSender, active_clients_store: ActiveClientsStore, + private_identity_key: &identity::PrivateKey, ) -> Self { ConnectionHandler { packet_processor, @@ -67,6 +72,7 @@ impl ConnectionHandler { storage, active_clients_store, ack_sender, + private_identity_key: private_identity_key.to_bytes(), } } @@ -183,7 +189,7 @@ impl ConnectionHandler { ) { debug!("Starting connection handler for {:?}", remote); shutdown.mark_as_success(); - let noise_stream = match upgrade_noise_responder(conn) { + let noise_stream = match upgrade_noise_responder(conn, &self.private_identity_key) { Ok(noise_stream) => noise_stream, Err(err) => { error!("Failed to perform Noise handshake with {remote} - {err}"); diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 073d4def85..452287d476 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -144,6 +144,7 @@ impl Gateway { self.storage.clone(), ack_sender, active_clients_store, + self.identity_keypair.private_key(), ); let listening_address = SocketAddr::new( @@ -198,6 +199,7 @@ impl Gateway { self.config.debug.maximum_connection_buffer_size, self.config.debug.use_legacy_framed_packet_version, topology_access, + self.identity_keypair.private_key(), shutdown, ); diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index 1066b94086..72d6a794a3 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -1,12 +1,14 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::node::identity::SECRET_KEY_LENGTH; use crate::node::listener::connection_handler::packet_processing::{ MixProcessingResult, PacketProcessor, }; use crate::node::packet_delayforwarder::PacketDelayForwardSender; use crate::node::TaskClient; use futures::StreamExt; +use nym_crypto::asymmetric::identity; use nym_mixnode_common::measure; use nym_noise::upgrade_noise_responder; use nym_sphinx::forwarding::packet::MixPacket; @@ -26,16 +28,19 @@ pub(crate) mod packet_processing; pub(crate) struct ConnectionHandler { packet_processor: PacketProcessor, delay_forwarding_channel: PacketDelayForwardSender, + private_identity_key: [u8; SECRET_KEY_LENGTH], } impl ConnectionHandler { pub(crate) fn new( packet_processor: PacketProcessor, delay_forwarding_channel: PacketDelayForwardSender, + private_identity_key: &identity::PrivateKey, ) -> Self { ConnectionHandler { packet_processor, delay_forwarding_channel, + private_identity_key: private_identity_key.to_bytes(), } } @@ -88,7 +93,7 @@ impl ConnectionHandler { debug!("Starting connection handler for {:?}", remote); shutdown.mark_as_success(); - let noise_stream = match upgrade_noise_responder(conn) { + let noise_stream = match upgrade_noise_responder(conn, &self.private_identity_key) { Ok(noise_stream) => noise_stream, Err(err) => { error!("Failed to perform Noise handshake with {remote} - {err}"); diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 0ec3a5c8e2..11005b2ec2 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -159,7 +159,11 @@ impl MixNode { let packet_processor = PacketProcessor::new(self.sphinx_keypair.private_key(), node_stats_update_sender); - let connection_handler = ConnectionHandler::new(packet_processor, delay_forwarding_channel); + let connection_handler = ConnectionHandler::new( + packet_processor, + delay_forwarding_channel, + self.identity_keypair.private_key(), + ); let listening_address = SocketAddr::new( self.config.mixnode.listening_address, @@ -186,7 +190,11 @@ impl MixNode { ); let mut packet_forwarder = DelayForwarder::new( - nym_mixnet_client::Client::new(client_config, topology_access), + nym_mixnet_client::Client::new( + client_config, + topology_access, + self.identity_keypair.private_key(), + ), node_stats_update_sender, shutdown, );