d9d549fd0f
* Changed identity keypair to use ed25519 * Encryption key is now x25519 based + compatibiltiy with sphinx * Pathing and import fixes * Moved all asymmetric keys to sub-module in crypto * Extracted aes to separate module * kdf module in crypto * Ability to perform diffie hellman on encryption keys * ecdsa on identity keys * Extremely rough and incomplete registration handshake * Authentication primitives * Creating new random authenticationIV * Wrapper type for the derived shared key * Removed AuthToken in favour of using SharedKey for authentication * Gateway identity keys * Registration handshake without error mapping * Gateway address in client config * Added extra key for gateway presence * Updated pemstore to work on borrows instead * Gateway client trying to perform the handshake * Gateway changes to allow for handshake and shared key * Debug trait on sharedkey * native client using updated gateway client * Slightly updated gateway API * Minor cleanup * Fixed pemstore to correctly save multiple keypairs * Gateway actually deriving shared key during handshake * Gateway sending correct mid-handshake message * Missing quotation mark in client config template * Fixed template for correct shared key serialization * Fixed gateway authentication * Fixed tests * Using correct gateway key when converting to sphinx node * "get_all_clients" takes them from gateways as opposed to providers now * cargo fmt * Renamed pemstore methods * Unused import * Encryption of forward requests between client and gateway * Updated sphinx dependency to use public revision * Sending 'error' on handshake processing error * Removed some dead code * Dead code I forgot to remove before * Extracted AckAes128Key into a struct * Slight pemstore revamp allowing for symmetric key store * ibid. * PemStorableKey for SharedKey * Introduced single location responsible for key management for client * WIP * Sphinx version update * Stop using NodeAddressBytes for two distinct and confusing purposes * Abstracting away SocketAddr from sphinx forwarding * Passing the bool for reply surbs * Attack plan for replies + encryption * Comment + removed variable binding * ReplySURB usage * Topology import in nymsphinx * Sphinx version update * Changed 'Recipient' to contain client's encryption key * Message preparation taking shape! * reply surb also containing the encryption key * Very initial message receiver * Sphinx version update * A possibly working way of receiving surbs * Fixed incorrect field name in client config template * camel casing all request arguments * Renamed and moved `MessageMode` to more appropriate file * Restored reconstruction tests * Removed dead code from chunking * Made rust examples compilable * reply SURB key storage * Replies as an InputMessage * Forgotten commented code * No retransmission processing for cover or replies * Received reply processing * Renamed client pathfinder to something more appropriate * Made HasherOutputSize public * Added key store path to config * Reply surb attaching key digest when used * Changes due to previous renaming * Removed comment * Fixed insert_encryption_key * Assigning initial value of key store path * Computing key digest with correct algorithm * Initial and presumably temporary request serialization * hacky way of introducing 'FragmentIdentifier' for replies * Moved responsibility of reply encryption, padding, etc, to message preparer * Optional recipient in try_get_valid_topology_ref * Handling new reply surbs with acks and padding * Updated go and python examples to include replies in text and binary cases * Updated rust examples + binaryserverresponse * Helpers in rust examples * And updated JS example * Moved shared key generation function to crypto crate * Cover traffic encryption! * hmac computation in crypto * Updated aes imports due to new dependencies * hkdf made more generic * crypto cleanup + algorithms in params * Clippy cleanup pass * Generating encryption+mac shared keys between client and gateway * MACs attached to forward requests to gateway * Gateway messages encrypted and mac'd * Lowered logging level * compiler warning cleanup * Some minor cleanup * Generic stream cipher * Generic shared key derivation + algorithm definitions * Project-wide AES clean-up * Comment fix * Removed commented imports * Updated comments * Fixed topology test fixture
148 lines
5.3 KiB
Rust
148 lines
5.3 KiB
Rust
// Copyright 2020 Nym Technologies SA
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use crate::config::Config;
|
|
use crate::node::packet_processing::PacketProcessor;
|
|
use crypto::asymmetric::encryption;
|
|
use directory_client::DirectoryClient;
|
|
use futures::channel::mpsc;
|
|
use log::*;
|
|
use nymsphinx::{addressing::nodes::NymNodeRoutingAddress, SphinxPacket};
|
|
use tokio::runtime::Runtime;
|
|
|
|
mod listener;
|
|
mod metrics;
|
|
mod packet_forwarding;
|
|
pub(crate) mod packet_processing;
|
|
mod presence;
|
|
|
|
// the MixNode will live for whole duration of this program
|
|
pub struct MixNode {
|
|
runtime: Runtime,
|
|
config: Config,
|
|
sphinx_keypair: encryption::KeyPair,
|
|
}
|
|
|
|
impl MixNode {
|
|
pub fn new(config: Config, sphinx_keypair: encryption::KeyPair) -> Self {
|
|
MixNode {
|
|
runtime: Runtime::new().unwrap(),
|
|
config,
|
|
sphinx_keypair,
|
|
}
|
|
}
|
|
|
|
fn start_presence_notifier(&self) {
|
|
info!("Starting presence notifier...");
|
|
let notifier_config = presence::NotifierConfig::new(
|
|
self.config.get_location(),
|
|
self.config.get_presence_directory_server(),
|
|
self.config.get_announce_address(),
|
|
self.sphinx_keypair.public_key().to_base58_string(),
|
|
self.config.get_layer(),
|
|
self.config.get_presence_sending_delay(),
|
|
);
|
|
presence::Notifier::new(notifier_config).start(self.runtime.handle());
|
|
}
|
|
|
|
fn start_metrics_reporter(&self) -> metrics::MetricsReporter {
|
|
info!("Starting metrics reporter...");
|
|
metrics::MetricsController::new(
|
|
self.config.get_metrics_directory_server(),
|
|
self.sphinx_keypair.public_key().to_base58_string(),
|
|
self.config.get_metrics_sending_delay(),
|
|
self.config.get_metrics_running_stats_logging_delay(),
|
|
)
|
|
.start(self.runtime.handle())
|
|
}
|
|
|
|
fn start_socket_listener(
|
|
&self,
|
|
metrics_reporter: metrics::MetricsReporter,
|
|
forwarding_channel: mpsc::UnboundedSender<(NymNodeRoutingAddress, SphinxPacket)>,
|
|
) {
|
|
info!("Starting socket listener...");
|
|
// this is the only location where our private key is going to be copied
|
|
// it will be held in memory owned by `MixNode` and inside an Arc of `PacketProcessor`
|
|
let packet_processor =
|
|
PacketProcessor::new(self.sphinx_keypair.private_key().clone(), metrics_reporter);
|
|
|
|
listener::run_socket_listener(
|
|
self.runtime.handle(),
|
|
self.config.get_listening_address(),
|
|
packet_processor,
|
|
forwarding_channel,
|
|
);
|
|
}
|
|
|
|
fn start_packet_forwarder(
|
|
&mut self,
|
|
) -> mpsc::UnboundedSender<(NymNodeRoutingAddress, SphinxPacket)> {
|
|
info!("Starting packet forwarder...");
|
|
self.runtime
|
|
.enter(|| {
|
|
packet_forwarding::PacketForwarder::new(
|
|
self.config.get_packet_forwarding_initial_backoff(),
|
|
self.config.get_packet_forwarding_maximum_backoff(),
|
|
self.config.get_initial_connection_timeout(),
|
|
)
|
|
})
|
|
.start(self.runtime.handle())
|
|
}
|
|
|
|
fn check_if_same_ip_node_exists(&mut self) -> Option<String> {
|
|
let directory_client_config =
|
|
directory_client::Config::new(self.config.get_presence_directory_server());
|
|
let directory_client = directory_client::Client::new(directory_client_config);
|
|
let topology = self
|
|
.runtime
|
|
.block_on(directory_client.get_topology())
|
|
.ok()?;
|
|
let existing_mixes_presence = topology.mix_nodes;
|
|
existing_mixes_presence
|
|
.iter()
|
|
.find(|node| node.host == self.config.get_announce_address())
|
|
.map(|node| node.pub_key.clone())
|
|
}
|
|
|
|
pub fn run(&mut self) {
|
|
info!("Starting nym mixnode");
|
|
|
|
if let Some(duplicate_node_key) = self.check_if_same_ip_node_exists() {
|
|
error!(
|
|
"Our announce-host is identical to an existing node's announce-host! (its key is {:?}",
|
|
duplicate_node_key
|
|
);
|
|
return;
|
|
}
|
|
let forwarding_channel = self.start_packet_forwarder();
|
|
let metrics_reporter = self.start_metrics_reporter();
|
|
self.start_socket_listener(metrics_reporter, forwarding_channel);
|
|
self.start_presence_notifier();
|
|
|
|
info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!");
|
|
|
|
if let Err(e) = self.runtime.block_on(tokio::signal::ctrl_c()) {
|
|
error!(
|
|
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
|
|
e
|
|
);
|
|
}
|
|
|
|
println!(
|
|
"Received SIGINT - the mixnode will terminate now (threads are not YET nicely stopped)"
|
|
);
|
|
}
|
|
}
|