diff --git a/Cargo.lock b/Cargo.lock index e63779d97f..1bdd0c2207 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4092,6 +4092,7 @@ name = "nym-sphinx-params" version = "0.1.0" dependencies = [ "nym-crypto", + "nym-outfox", "nym-sphinx-types", "serde", "thiserror", @@ -4104,6 +4105,7 @@ dependencies = [ "nym-outfox", "serde", "sphinx-packet", + "thiserror", ] [[package]] diff --git a/common/client-libs/mixnet-client/src/client.rs b/common/client-libs/mixnet-client/src/client.rs index 62e37bca90..6d43a5f436 100644 --- a/common/client-libs/mixnet-client/src/client.rs +++ b/common/client-libs/mixnet-client/src/client.rs @@ -4,10 +4,11 @@ use futures::channel::mpsc; use futures::StreamExt; use log::*; -use nym_sphinx::framing::codec::SphinxCodec; -use nym_sphinx::framing::packet::FramedSphinxPacket; +use nym_sphinx::addressing::nodes::NymNodeRoutingAddress; +use nym_sphinx::framing::codec::NymCodec; +use nym_sphinx::framing::packet::FramedNymPacket; use nym_sphinx::params::PacketMode; -use nym_sphinx::{addressing::nodes::NymNodeRoutingAddress, SphinxPacket}; +use nym_sphinx::NymPacket; use std::collections::HashMap; use std::io; use std::net::SocketAddr; @@ -50,7 +51,7 @@ pub trait SendWithoutResponse { fn send_without_response( &mut self, address: NymNodeRoutingAddress, - packet: SphinxPacket, + packet: NymPacket, packet_mode: PacketMode, ) -> io::Result<()>; } @@ -61,12 +62,12 @@ pub struct Client { } struct ConnectionSender { - channel: mpsc::Sender, + channel: mpsc::Sender, current_reconnection_attempt: Arc, } impl ConnectionSender { - fn new(channel: mpsc::Sender) -> Self { + fn new(channel: mpsc::Sender) -> Self { ConnectionSender { channel, current_reconnection_attempt: Arc::new(AtomicU32::new(0)), @@ -84,7 +85,7 @@ impl Client { async fn manage_connection( address: SocketAddr, - receiver: mpsc::Receiver, + receiver: mpsc::Receiver, connection_timeout: Duration, current_reconnection: &AtomicU32, ) { @@ -96,7 +97,7 @@ impl Client { debug!("Managed to establish connection to {}", address); // if we managed to connect, reset the reconnection count (whatever it might have been) current_reconnection.store(0, Ordering::Release); - Framed::new(stream, SphinxCodec) + Framed::new(stream, NymCodec) } Err(err) => { debug!( @@ -148,11 +149,7 @@ impl Client { } } - fn make_connection( - &mut self, - address: NymNodeRoutingAddress, - pending_packet: FramedSphinxPacket, - ) { + fn make_connection(&mut self, address: NymNodeRoutingAddress, pending_packet: FramedNymPacket) { let (mut sender, receiver) = mpsc::channel(self.config.maximum_connection_buffer_size); // this CAN'T fail because we just created the channel which has a non-zero capacity @@ -200,12 +197,12 @@ impl SendWithoutResponse for Client { fn send_without_response( &mut self, address: NymNodeRoutingAddress, - packet: SphinxPacket, + packet: NymPacket, packet_mode: PacketMode, ) -> io::Result<()> { trace!("Sending packet to {:?}", address); let framed_packet = - FramedSphinxPacket::new(packet, packet_mode, self.config.use_legacy_version); + FramedNymPacket::new(packet, packet_mode, self.config.use_legacy_version); if let Some(sender) = self.conn_new.get_mut(&address) { if let Err(err) = sender.channel.try_send(framed_packet) { diff --git a/common/client-libs/mixnet-client/src/forwarder.rs b/common/client-libs/mixnet-client/src/forwarder.rs index cefae1fc30..4defb056d7 100644 --- a/common/client-libs/mixnet-client/src/forwarder.rs +++ b/common/client-libs/mixnet-client/src/forwarder.rs @@ -6,6 +6,7 @@ use futures::channel::mpsc; use futures::StreamExt; use log::*; use nym_sphinx::forwarding::packet::MixPacket; +use nym_sphinx::NymPacket; use std::time::Duration; pub type MixForwardingSender = mpsc::UnboundedSender; @@ -66,7 +67,7 @@ impl PacketForwarder { if let Err(err) = self.mixnet_client - .send_without_response(next_hop, sphinx_packet, packet_mode) + .send_without_response(next_hop, NymPacket::Sphinx(sphinx_packet), packet_mode) { debug!("failed to forward the packet - {err}") } diff --git a/common/mixnode-common/src/packet_processor/error.rs b/common/mixnode-common/src/packet_processor/error.rs index 99d3a2d2f2..9c0c1e5ab0 100644 --- a/common/mixnode-common/src/packet_processor/error.rs +++ b/common/mixnode-common/src/packet_processor/error.rs @@ -3,12 +3,15 @@ use nym_sphinx_acknowledgements::surb_ack::SurbAckRecoveryError; use nym_sphinx_addressing::nodes::NymNodeRoutingAddressError; -use nym_sphinx_types::Error as SphinxError; +use nym_sphinx_types::{NymPacketError, SphinxError}; use thiserror::Error; #[derive(Error, Debug)] pub enum MixProcessingError { #[error("failed to process received packet: {0}")] + NymPacketProcessingError(#[from] NymPacketError), + + #[error("failed to process received sphinx packet: {0}")] SphinxProcessingError(#[from] SphinxError), #[error("the forward hop address was malformed: {0}")] diff --git a/common/mixnode-common/src/packet_processor/processor.rs b/common/mixnode-common/src/packet_processor/processor.rs index 98847d8983..c0295e2894 100644 --- a/common/mixnode-common/src/packet_processor/processor.rs +++ b/common/mixnode-common/src/packet_processor/processor.rs @@ -7,11 +7,11 @@ use log::*; use nym_sphinx_acknowledgements::surb_ack::SurbAck; use nym_sphinx_addressing::nodes::NymNodeRoutingAddress; use nym_sphinx_forwarding::packet::MixPacket; -use nym_sphinx_framing::packet::FramedSphinxPacket; +use nym_sphinx_framing::packet::FramedNymPacket; use nym_sphinx_params::{PacketMode, PacketSize}; use nym_sphinx_types::{ - Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, Payload, PrivateKey, - ProcessedPacket, SphinxPacket, + Delay as SphinxDelay, DestinationAddressBytes, NodeAddressBytes, NymPacket, Payload, + PrivateKey, ProcessedPacket, SphinxPacket, }; use std::convert::TryFrom; use std::sync::Arc; @@ -55,12 +55,12 @@ impl SphinxPacketProcessor { )] fn perform_initial_sphinx_packet_processing( &self, - packet: SphinxPacket, + packet: NymPacket, ) -> Result { measure!({ packet.process(&self.sphinx_key).map_err(|err| { debug!("Failed to unwrap Sphinx packet: {err}"); - MixProcessingError::SphinxProcessingError(err) + MixProcessingError::NymPacketProcessingError(err) }) }) } @@ -72,17 +72,17 @@ impl SphinxPacketProcessor { )] fn perform_initial_unwrapping( &self, - received: FramedSphinxPacket, + received: FramedNymPacket, ) -> Result { measure!({ let packet_mode = received.packet_mode(); - let sphinx_packet = received.into_inner(); + let packet = received.into_inner(); if packet_mode.is_old_vpn() { return Err(MixProcessingError::ReceivedOldTypeVpnPacket); } - self.perform_initial_sphinx_packet_processing(sphinx_packet) + self.perform_initial_sphinx_packet_processing(packet) }) } @@ -127,14 +127,18 @@ impl SphinxPacketProcessor { packet_mode: PacketMode, ) -> Result<(Option, Vec), MixProcessingError> { match packet_size { - PacketSize::AckPacket => { + PacketSize::AckPacket | PacketSize::OutfoxAckPacket => { trace!("received an ack packet!"); Ok((None, data)) } PacketSize::RegularPacket | PacketSize::ExtendedPacket8 | PacketSize::ExtendedPacket16 - | PacketSize::ExtendedPacket32 => { + | PacketSize::ExtendedPacket32 + | PacketSize::OutfoxRegularPacket + | PacketSize::OutfoxExtendedPacket8 + | PacketSize::OutfoxExtendedPacket16 + | PacketSize::OutfoxExtendedPacket32 => { trace!("received a normal packet!"); let (ack_data, message) = self.split_hop_data_into_ack_and_message(data)?; let (ack_first_hop, ack_packet) = SurbAck::try_recover_first_hop_packet(&ack_data)?; @@ -192,7 +196,7 @@ impl SphinxPacketProcessor { )] pub fn process_received( &self, - received: FramedSphinxPacket, + received: FramedNymPacket, ) -> Result { // explicit packet size will help to correctly parse final hop measure!({ diff --git a/common/nymsphinx/acknowledgements/src/surb_ack.rs b/common/nymsphinx/acknowledgements/src/surb_ack.rs index 5df36e1f0b..9331fbb26f 100644 --- a/common/nymsphinx/acknowledgements/src/surb_ack.rs +++ b/common/nymsphinx/acknowledgements/src/surb_ack.rs @@ -10,7 +10,7 @@ use nym_sphinx_addressing::nodes::{ use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::DEFAULT_NUM_MIX_HOPS; use nym_sphinx_types::builder::SphinxPacketBuilder; -use nym_sphinx_types::Error as SphinxError; +use nym_sphinx_types::SphinxError; use nym_sphinx_types::{ delays::{self, Delay}, SphinxPacket, diff --git a/common/nymsphinx/anonymous-replies/src/reply_surb.rs b/common/nymsphinx/anonymous-replies/src/reply_surb.rs index 66642720e5..e501623a81 100644 --- a/common/nymsphinx/anonymous-replies/src/reply_surb.rs +++ b/common/nymsphinx/anonymous-replies/src/reply_surb.rs @@ -7,7 +7,7 @@ use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN}; use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::{ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS}; -use nym_sphinx_types::{delays, Error as SphinxError, SURBMaterial, SphinxPacket, SURB}; +use nym_sphinx_types::{delays, SURBMaterial, SphinxError, SphinxPacket, SURB}; use nym_topology::{NymTopology, NymTopologyError}; use rand::{CryptoRng, RngCore}; use serde::de::{Error as SerdeError, Visitor}; diff --git a/common/nymsphinx/cover/src/lib.rs b/common/nymsphinx/cover/src/lib.rs index 19e6e96e09..608ef1a1ae 100644 --- a/common/nymsphinx/cover/src/lib.rs +++ b/common/nymsphinx/cover/src/lib.rs @@ -14,7 +14,7 @@ use nym_sphinx_params::{ PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketMode, DEFAULT_NUM_MIX_HOPS, }; use nym_sphinx_types::builder::SphinxPacketBuilder; -use nym_sphinx_types::{delays, Error as SphinxError}; +use nym_sphinx_types::{delays, SphinxError}; use nym_topology::{NymTopology, NymTopologyError}; use rand::{CryptoRng, RngCore}; use std::convert::TryFrom; diff --git a/common/nymsphinx/framing/src/codec.rs b/common/nymsphinx/framing/src/codec.rs index 515623180b..9cfc47103b 100644 --- a/common/nymsphinx/framing/src/codec.rs +++ b/common/nymsphinx/framing/src/codec.rs @@ -5,14 +5,14 @@ use crate::packet::{FramedNymPacket, Header}; use bytes::{Buf, BufMut, BytesMut}; use nym_sphinx_params::packet_modes::InvalidPacketMode; use nym_sphinx_params::packet_sizes::{InvalidPacketSize, PacketSize}; -use nym_sphinx_types::{Error as SphinxError, NymPacket}; -use nym_sphinx_types::{OutfoxError, SphinxPacket}; +use nym_sphinx_types::SphinxPacket; +use nym_sphinx_types::{NymPacket, NymPacketError, SphinxError}; use std::io; use thiserror::Error; use tokio_util::codec::{Decoder, Encoder}; #[derive(Error, Debug)] -pub enum SphinxCodecError { +pub enum NymCodecError { #[error("the packet size information was malformed - {0}")] InvalidPacketSize(#[from] InvalidPacketSize), @@ -25,6 +25,9 @@ pub enum SphinxCodecError { #[error("encountered an IO error - {0}")] IoError(#[from] io::Error), + #[error("encountered a packet error - {0}")] + NymPacket(#[from] NymPacketError), + #[error("could not convert to bytes")] ToBytes, @@ -32,68 +35,67 @@ pub enum SphinxCodecError { FromBytes, } -#[derive(Error, Debug)] -pub enum OutfoxCodecError { - #[error("the packet size information was malformed - {0}")] - InvalidPacketSize(#[from] InvalidPacketSize), - - #[error("the packet mode information was malformed - {0}")] - InvalidPacketMode(#[from] InvalidPacketMode), - - #[error("the actual sphinx packet was malformed - {0}")] - MalformedSphinxPacket(#[from] SphinxError), - - #[error("encountered an IO error - {0}")] - IoError(#[from] io::Error), - - #[error("outfox error - {0}")] - Outfox(#[from] OutfoxError), -} - -pub struct OutfoxCodec; - -impl Encoder for OutfoxCodec { - type Error = OutfoxCodecError; - - fn encode(&mut self, item: FramedNymPacket, dst: &mut BytesMut) -> Result<(), Self::Error> { - dst.put( - bincode::serialize(&item) - .map_err(|_| OutfoxError::Bincode)? - .as_slice(), - ); - Ok(()) - } -} - // TODO: in the future it could be extended to have state containing symmetric encryption key // so that all data could be encrypted easily (alternatively we could just slap TLS) -pub struct SphinxCodec; +pub struct NymCodec; -impl Encoder for SphinxCodec { - type Error = SphinxCodecError; +impl Encoder for NymCodec { + type Error = NymCodecError; + + // fn encode_serde(&mut self, item: FramedNymPacket, dst: &mut BytesMut) -> Result<(), Self::Error> { + // let encoded_size = bincode::serialized_size(&item).unwrap() as u32; + // dst.put_u32(encoded_size); + // dst.put( + // bincode::serialize(&item) + // .map_err(|_| NymCodecError::ToBytes)? + // .as_slice(), + // ); + // Ok(()) + // } fn encode(&mut self, item: FramedNymPacket, dst: &mut BytesMut) -> Result<(), Self::Error> { - let encoded_size = bincode::serialized_size(&item).unwrap() as u32; - dst.put_u32(encoded_size); - dst.put( - bincode::serialize(&item) - .map_err(|_| SphinxCodecError::ToBytes)? - .as_slice(), - ); - // item.header().encode(dst); - // dst.put( - // item.packet - // .to_bytes() - // .map_err(|_e| SphinxCodecError::ToBytes)? - // .as_ref(), - // ); + item.header.encode(dst); + dst.put(item.packet.to_bytes()?.as_slice()); Ok(()) } } -impl Decoder for SphinxCodec { +impl Decoder for NymCodec { type Item = FramedNymPacket; - type Error = SphinxCodecError; + type Error = NymCodecError; + + // fn decode_serde(&mut self, src: &mut BytesMut) -> Result, Self::Error> { + // if src.is_empty() { + // // can't do anything if we have no bytes, but let's reserve enough for the most + // // conservative case, i.e. receiving an ack packet + // src.reserve(Header::LEGACY_SIZE + PacketSize::AckPacket.size()); + // return Ok(None); + // } + + // let next_size = if let Some(size) = src.get(..4) { + // u32::from_be_bytes(size.try_into().unwrap()) as usize + // } else { + // 0 + // }; + + // if next_size == 0 { + // return Ok(None); + // } + + // if let Some(next_packet) = src.get(4..next_size + 4) { + // match bincode::deserialize::(next_packet) { + // Ok(packet) => { + // src.advance(next_size + 4); + // return Ok(Some(packet)); + // } + // Err(_) => { + // println!("Could not decode packet"); + // return Ok(None); + // } + // } + // } + // Ok(None) + // } fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { if src.is_empty() { @@ -103,58 +105,33 @@ impl Decoder for SphinxCodec { return Ok(None); } - let next_size = if let Some(size) = src.get(..4) { - u32::from_be_bytes(size.try_into().unwrap()) as usize - } else { - 0 + // because header is so small and simple it makes no point in trying to cache + // this result. It will be just simpler to re-decode it + let header = match Header::decode(src)? { + Some(header) => header, + None => return Ok(None), // we have some data but not enough to get header back }; - // let next_size = src.get_u64() as usize; - if next_size == 0 { + let packet_size = header.packet_size.size(); + let frame_len = header.size() + packet_size; + + if src.len() < frame_len { + // we don't have enough bytes to read the rest of frame + src.reserve(packet_size); return Ok(None); } - if let Some(next_packet) = src.get(4..next_size + 4) { - match bincode::deserialize::(next_packet) { - Ok(packet) => { - src.advance(next_size + 4); - return Ok(Some(packet)); - } - Err(_) => { - println!("Could not decode packet"); - return Ok(None); - } - } - } - Ok(None) - - // because header is so small and simple it makes no point in trying to cache - // this result. It will be just simpler to re-decode it - // let header = match Header::decode(src)? { - // Some(header) => header, - // None => return Ok(None), // we have some data but not enough to get header back - // }; - - // let sphinx_packet_size = framed_packet.header.packet_size.size(); - // let frame_len = framed_packet.header.size() + sphinx_packet_size; - - // if src.len() < frame_len { - // // we don't have enough bytes to read the rest of frame - // src.reserve(sphinx_packet_size); - // return Ok(None); - // } - // advance buffer past the header - at this point we have enough bytes - // src.advance(header.size()); - // let sphinx_packet_bytes = src.split_to(sphinx_packet_size); + src.advance(header.size()); + let sphinx_packet_bytes = src.split_to(packet_size); // here it could be debatable whether stream is corrupt or not, // but let's go with the safer approach and assume it is. - // let packet = SphinxPacket::from_bytes(&sphinx_packet_bytes)?; - // let nymsphinx_packet = FramedNymPacket { - // header, - // packet: NymPacket::Sphinx(packet), - // }; + let packet = SphinxPacket::from_bytes(&sphinx_packet_bytes)?; + let nymsphinx_packet = FramedNymPacket { + header, + packet: NymPacket::Sphinx(packet), + }; // As per docs: // Before returning from the function, implementations should ensure that the buffer @@ -166,24 +143,24 @@ impl Decoder for SphinxCodec { // reserve for that. // we also assume the next packet coming from the same client will use exactly the same versioning // as the current packet - // let mut allocate_for_next_packet = framed_packet.header.size() + PacketSize::AckPacket.size(); - // if !src.is_empty() { - // match Header::decode(src) { - // Ok(Some(next_header)) => { - // allocate_for_next_packet = next_header.size() + next_header.packet_size.size(); - // } - // Ok(None) => { - // // we don't have enough information to know how much to reserve, fallback to the ack case - // } + let mut allocate_for_next_packet = header.size() + PacketSize::AckPacket.size(); + if !src.is_empty() { + match Header::decode(src) { + Ok(Some(next_header)) => { + allocate_for_next_packet = next_header.size() + next_header.packet_size.size(); + } + Ok(None) => { + // we don't have enough information to know how much to reserve, fallback to the ack case + } - // // the next frame will be malformed but let's leave handling the error to the next - // // call to 'decode', as presumably, the current sphinx packet is still valid - // Err(_) => return Ok(Some(framed_packet)), - // }; - // } - // src.reserve(allocate_for_next_packet); + // the next frame will be malformed but let's leave handling the error to the next + // call to 'decode', as presumably, the current sphinx packet is still valid + Err(_) => return Ok(Some(nymsphinx_packet)), + }; + } + src.reserve(allocate_for_next_packet); - // Ok(Some(framed_packet)) + Ok(Some(nymsphinx_packet)) } } @@ -237,15 +214,15 @@ mod packet_encoding { let packet = FramedNymPacket { header, - packet: Some(NymPacket::Sphinx(sphinx_packet)), + packet: NymPacket::Sphinx(sphinx_packet), }; let mut bytes = BytesMut::new(); - SphinxCodec.encode(packet, &mut bytes).unwrap(); - let decoded = SphinxCodec.decode(&mut bytes).unwrap().unwrap(); + NymCodec.encode(packet, &mut bytes).unwrap(); + let decoded = NymCodec.decode(&mut bytes).unwrap().unwrap(); assert_eq!(decoded.header, header); - assert_eq!(decoded.packet.unwrap().to_bytes().unwrap(), sphinx_bytes) + assert_eq!(decoded.packet.to_bytes().unwrap(), sphinx_bytes) } #[cfg(test)] @@ -258,7 +235,7 @@ mod packet_encoding { fn for_empty_bytes() { // empty bytes should allocate for header + ack packet let mut empty_bytes = BytesMut::new(); - assert!(SphinxCodec.decode(&mut empty_bytes).unwrap().is_none()); + assert!(NymCodec.decode(&mut empty_bytes).unwrap().is_none()); assert_eq!( empty_bytes.capacity(), Header::LEGACY_SIZE + PacketSize::AckPacket.size() @@ -279,11 +256,11 @@ mod packet_encoding { let header = Header { packet_version: PacketVersion::Legacy, packet_size, - packet_mode: Default::default(), + ..Default::default() }; let mut bytes = BytesMut::new(); header.encode(&mut bytes); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_none()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_none()); assert_eq!(bytes.capacity(), Header::LEGACY_SIZE + packet_size.size()) } @@ -303,11 +280,11 @@ mod packet_encoding { let header = Header { packet_version: PacketVersion::Versioned(123), packet_size, - packet_mode: Default::default(), + ..Default::default() }; let mut bytes = BytesMut::new(); header.encode(&mut bytes); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_none()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_none()); assert_eq!( bytes.capacity(), @@ -322,21 +299,18 @@ mod packet_encoding { let packet = FramedNymPacket { header: Header { packet_version: PacketVersion::Legacy, - packet_size: Default::default(), - packet_mode: Default::default(), + ..Default::default() }, - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let mut bytes = BytesMut::new(); - SphinxCodec.encode(packet, &mut bytes).unwrap(); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); - // assert_eq!( - // bytes.capacity(), - // Header::LEGACY_SIZE + PacketSize::AckPacket.size() - // ); + NymCodec.encode(packet, &mut bytes).unwrap(); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); + assert_eq!( + bytes.capacity(), + Header::LEGACY_SIZE + PacketSize::AckPacket.size() + ); } #[test] @@ -344,18 +318,16 @@ mod packet_encoding { // if full frame is used exactly, there should be enough space for header + ack packet let packet = FramedNymPacket { header: Header::default(), - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let mut bytes = BytesMut::new(); - SphinxCodec.encode(packet, &mut bytes).unwrap(); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); - // assert_eq!( - // bytes.capacity(), - // Header::VERSIONED_SIZE + PacketSize::AckPacket.size() - // ); + NymCodec.encode(packet, &mut bytes).unwrap(); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); + assert_eq!( + bytes.capacity(), + Header::VERSIONED_SIZE + PacketSize::AckPacket.size() + ); } #[test] @@ -373,21 +345,18 @@ mod packet_encoding { let first_packet = FramedNymPacket { header: Header { packet_version: PacketVersion::Legacy, - packet_size: Default::default(), - packet_mode: Default::default(), + ..Default::default() }, - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let mut bytes = BytesMut::new(); - SphinxCodec.encode(first_packet, &mut bytes).unwrap(); + NymCodec.encode(first_packet, &mut bytes).unwrap(); bytes.put_u8(packet_size as u8); bytes.put_u8(PacketMode::default() as u8); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); - // assert!(bytes.capacity() >= Header::LEGACY_SIZE + packet_size.size()) + assert!(bytes.capacity() >= Header::LEGACY_SIZE + packet_size.size()) } } @@ -405,17 +374,15 @@ mod packet_encoding { for packet_size in packet_sizes { let first_packet = FramedNymPacket { header: Header::default(), - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let mut bytes = BytesMut::new(); - SphinxCodec.encode(first_packet, &mut bytes).unwrap(); + NymCodec.encode(first_packet, &mut bytes).unwrap(); bytes.put_u8(PacketVersion::new_versioned(123).as_u8().unwrap()); bytes.put_u8(packet_size as u8); bytes.put_u8(PacketMode::default() as u8); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); // assert!(bytes.capacity() >= Header::VERSIONED_SIZE + packet_size.size()) } @@ -426,65 +393,50 @@ mod packet_encoding { fn can_decode_two_packets_immediately() { let packet1 = FramedNymPacket { header: Header::default(), - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let packet2 = FramedNymPacket { header: Header::default(), - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let mut bytes = BytesMut::new(); - SphinxCodec.encode(packet1, &mut bytes).unwrap(); - SphinxCodec.encode(packet2, &mut bytes).unwrap(); + NymCodec.encode(packet1, &mut bytes).unwrap(); + NymCodec.encode(packet2, &mut bytes).unwrap(); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_none()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_none()); } #[test] fn can_decode_two_packets_in_separate_calls() { let packet1 = FramedNymPacket { header: Header::default(), - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let packet2 = FramedNymPacket { header: Header::default(), - packet: Some(NymPacket::Sphinx(make_valid_sphinx_packet( - Default::default(), - ))), + packet: NymPacket::Sphinx(make_valid_sphinx_packet(Default::default())), }; let mut bytes = BytesMut::new(); let mut bytes_tmp = BytesMut::new(); - println!("{}", bytes.len()); - SphinxCodec.encode(packet1, &mut bytes).unwrap(); - println!("{}", bytes.len()); - SphinxCodec.encode(packet2, &mut bytes_tmp).unwrap(); - println!("{}", bytes.len()); + NymCodec.encode(packet1, &mut bytes).unwrap(); + NymCodec.encode(packet2, &mut bytes_tmp).unwrap(); let tmp = bytes_tmp.split_off(100); bytes.put(bytes_tmp); - println!("{}", bytes.len()); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); - println!("{}", bytes.len()); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_none()); - println!("{}", bytes.len()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_none()); bytes.put(tmp); - println!("{}", bytes.len()); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some()); - assert!(SphinxCodec.decode(&mut bytes).unwrap().is_none()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_some()); + assert!(NymCodec.decode(&mut bytes).unwrap().is_none()); } } diff --git a/common/nymsphinx/framing/src/packet.rs b/common/nymsphinx/framing/src/packet.rs index 126cff5748..2ed3f16e1b 100644 --- a/common/nymsphinx/framing/src/packet.rs +++ b/common/nymsphinx/framing/src/packet.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::codec::SphinxCodecError; +use crate::codec::NymCodecError; use bytes::{BufMut, BytesMut}; use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::packet_version::PacketVersion; @@ -16,7 +16,7 @@ pub struct FramedNymPacket { pub(crate) header: Header, /// The actual SphinxPacket being sent. - pub(crate) packet: Option, + pub(crate) packet: NymPacket, } impl FramedNymPacket { @@ -31,7 +31,7 @@ impl FramedNymPacket { packet_size, packet_mode, }, - packet: Some(packet), + packet, } } @@ -48,7 +48,7 @@ impl FramedNymPacket { } pub fn into_inner(self) -> NymPacket { - self.packet.unwrap() + self.packet } } @@ -101,7 +101,7 @@ impl Header { dst.reserve(self.packet_size.size()); } - pub(crate) fn decode(src: &mut BytesMut) -> Result, SphinxCodecError> { + pub(crate) fn decode(src: &mut BytesMut) -> Result, NymCodecError> { if src.len() < Self::LEGACY_SIZE { // can't do anything if we don't have enough bytes - but reserve enough for the next call src.reserve(Self::LEGACY_SIZE); @@ -197,7 +197,7 @@ mod header_encoding { let header = Header { packet_version: PacketVersion::Legacy, packet_size, - packet_mode: Default::default(), + ..Default::default() }; let mut bytes = BytesMut::new(); header.encode(&mut bytes); @@ -218,7 +218,7 @@ mod header_encoding { let header = Header { packet_version: PacketVersion::Versioned(123), packet_size, - packet_mode: Default::default(), + ..Default::default() }; let mut bytes = BytesMut::new(); header.encode(&mut bytes); diff --git a/common/nymsphinx/params/Cargo.toml b/common/nymsphinx/params/Cargo.toml index bc9b40b9a8..7242935eac 100644 --- a/common/nymsphinx/params/Cargo.toml +++ b/common/nymsphinx/params/Cargo.toml @@ -13,3 +13,4 @@ serde = { workspace = true, features = ["derive"] } nym-crypto = { path = "../../crypto", features = ["hashing", "symmetric"] } nym-sphinx-types = { path = "../types" } +nym-outfox = { "path" = "../../../nym-outfox" } diff --git a/common/nymsphinx/params/src/packet_sizes.rs b/common/nymsphinx/params/src/packet_sizes.rs index 0e636e54b3..40f30af9e0 100644 --- a/common/nymsphinx/params/src/packet_sizes.rs +++ b/common/nymsphinx/params/src/packet_sizes.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::FRAG_ID_LEN; +use nym_outfox::packet::OUTFOX_PACKET_OVERHEAD; use nym_sphinx_types::header::HEADER_SIZE; use nym_sphinx_types::PAYLOAD_OVERHEAD_SIZE; use serde::{Deserialize, Serialize}; @@ -12,20 +13,27 @@ use std::str::FromStr; use thiserror::Error; // each sphinx packet contains mandatory header and payload padding + markers -const PACKET_OVERHEAD: usize = HEADER_SIZE + PAYLOAD_OVERHEAD_SIZE; +const SPHINX_PACKET_OVERHEAD: usize = HEADER_SIZE + PAYLOAD_OVERHEAD_SIZE; // it's up to the smart people to figure those values out : ) -const REGULAR_PACKET_SIZE: usize = 2 * 1024 + PACKET_OVERHEAD; + // TODO: even though we have 16B IV, is having just 5B (FRAG_ID_LEN) of the ID possibly insecure? // TODO: I'm not entirely sure if we can easily extract `::NonceSize` // into a const usize before relevant stuff is stabilised in rust... const ACK_IV_SIZE: usize = 16; -const ACK_PACKET_SIZE: usize = ACK_IV_SIZE + FRAG_ID_LEN + PACKET_OVERHEAD; -const EXTENDED_PACKET_SIZE_8: usize = 8 * 1024 + PACKET_OVERHEAD; -const EXTENDED_PACKET_SIZE_16: usize = 16 * 1024 + PACKET_OVERHEAD; -const EXTENDED_PACKET_SIZE_32: usize = 32 * 1024 + PACKET_OVERHEAD; +const ACK_PACKET_SIZE: usize = ACK_IV_SIZE + FRAG_ID_LEN + SPHINX_PACKET_OVERHEAD; +const REGULAR_PACKET_SIZE: usize = 2 * 1024 + SPHINX_PACKET_OVERHEAD; +const EXTENDED_PACKET_SIZE_8: usize = 8 * 1024 + SPHINX_PACKET_OVERHEAD; +const EXTENDED_PACKET_SIZE_16: usize = 16 * 1024 + SPHINX_PACKET_OVERHEAD; +const EXTENDED_PACKET_SIZE_32: usize = 32 * 1024 + SPHINX_PACKET_OVERHEAD; + +const OUTFOX_ACK_PACKET_SIZE: usize = ACK_IV_SIZE + FRAG_ID_LEN + OUTFOX_PACKET_OVERHEAD; +const OUTFOX_REGULAR_PACKET_SIZE: usize = 2 * 1024 + OUTFOX_PACKET_OVERHEAD; +const OUTFOX_EXTENDED_PACKET_SIZE_8: usize = 8 * 1024 + OUTFOX_PACKET_OVERHEAD; +const OUTFOX_EXTENDED_PACKET_SIZE_16: usize = 16 * 1024 + OUTFOX_PACKET_OVERHEAD; +const OUTFOX_EXTENDED_PACKET_SIZE_32: usize = 32 * 1024 + OUTFOX_PACKET_OVERHEAD; #[derive(Debug, Error)] pub enum InvalidPacketSize { @@ -62,6 +70,25 @@ pub enum PacketSize { // for example for streaming fast and furious in compressed XviD quality #[serde(rename = "extended16")] ExtendedPacket16 = 5, + + #[serde(rename = "outfox_regular")] + OutfoxRegularPacket = 6, + + // for sending SURB-ACKs + #[serde(rename = "outfox_ack")] + OutfoxAckPacket = 7, + + // for example for streaming fast and furious in uncompressed 10bit 4K HDR quality + #[serde(rename = "outfox_extended32")] + OutfoxExtendedPacket32 = 8, + + // for example for streaming fast and furious in heavily compressed lossy RealPlayer quality + #[serde(rename = "outfox_extended8")] + OutfoxExtendedPacket8 = 9, + + // for example for streaming fast and furious in compressed XviD quality + #[serde(rename = "outfox_extended16")] + OutfoxExtendedPacket16 = 10, } impl PartialOrd for PacketSize { @@ -88,6 +115,11 @@ impl FromStr for PacketSize { "extended8" => Ok(Self::ExtendedPacket8), "extended16" => Ok(Self::ExtendedPacket16), "extended32" => Ok(Self::ExtendedPacket32), + "outfox_regular" => Ok(Self::OutfoxRegularPacket), + "outfox_ack" => Ok(Self::OutfoxAckPacket), + "outfox_extended8" => Ok(Self::OutfoxExtendedPacket8), + "outfox_extended16" => Ok(Self::OutfoxExtendedPacket16), + "outfox_extended32" => Ok(Self::OutfoxExtendedPacket32), s => Err(InvalidPacketSize::UnknownExtendedPacketVariant { received: s.to_string(), }), @@ -103,6 +135,11 @@ impl Display for PacketSize { PacketSize::ExtendedPacket32 => write!(f, "extended32"), PacketSize::ExtendedPacket8 => write!(f, "extended8"), PacketSize::ExtendedPacket16 => write!(f, "extended16"), + PacketSize::OutfoxRegularPacket => write!(f, "outfox_regular"), + PacketSize::OutfoxAckPacket => write!(f, "outfox_ack"), + PacketSize::OutfoxExtendedPacket32 => write!(f, "outfox_extended32"), + PacketSize::OutfoxExtendedPacket8 => write!(f, "outfox_extended8"), + PacketSize::OutfoxExtendedPacket16 => write!(f, "outfox_extended16"), } } } @@ -140,6 +177,11 @@ impl PacketSize { PacketSize::ExtendedPacket8 => EXTENDED_PACKET_SIZE_8, PacketSize::ExtendedPacket16 => EXTENDED_PACKET_SIZE_16, PacketSize::ExtendedPacket32 => EXTENDED_PACKET_SIZE_32, + PacketSize::OutfoxRegularPacket => OUTFOX_REGULAR_PACKET_SIZE, + PacketSize::OutfoxAckPacket => OUTFOX_ACK_PACKET_SIZE, + PacketSize::OutfoxExtendedPacket8 => OUTFOX_EXTENDED_PACKET_SIZE_8, + PacketSize::OutfoxExtendedPacket16 => OUTFOX_EXTENDED_PACKET_SIZE_16, + PacketSize::OutfoxExtendedPacket32 => OUTFOX_EXTENDED_PACKET_SIZE_32, } } @@ -169,10 +211,16 @@ impl PacketSize { pub fn is_extended_size(&self) -> bool { match self { - PacketSize::RegularPacket | PacketSize::AckPacket => false, + PacketSize::RegularPacket + | PacketSize::AckPacket + | PacketSize::OutfoxAckPacket + | PacketSize::OutfoxRegularPacket => false, PacketSize::ExtendedPacket8 | PacketSize::ExtendedPacket16 - | PacketSize::ExtendedPacket32 => true, + | PacketSize::ExtendedPacket32 + | PacketSize::OutfoxExtendedPacket8 + | PacketSize::OutfoxExtendedPacket16 + | PacketSize::OutfoxExtendedPacket32 => true, } } @@ -185,7 +233,7 @@ impl PacketSize { } pub fn get_type_from_plaintext(plaintext_size: usize) -> Result { - let packet_size = plaintext_size + PACKET_OVERHEAD; + let packet_size = plaintext_size + SPHINX_PACKET_OVERHEAD; Self::get_type(packet_size) } } diff --git a/common/nymsphinx/params/src/packet_version.rs b/common/nymsphinx/params/src/packet_version.rs index 2c2f021118..c8c6ce3fc6 100644 --- a/common/nymsphinx/params/src/packet_version.rs +++ b/common/nymsphinx/params/src/packet_version.rs @@ -1,7 +1,7 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use crate::{PacketSize, CURRENT_PACKET_VERSION_NUMBER}; diff --git a/common/nymsphinx/types/Cargo.toml b/common/nymsphinx/types/Cargo.toml index 2adaefaf81..cc9e9aab10 100644 --- a/common/nymsphinx/types/Cargo.toml +++ b/common/nymsphinx/types/Cargo.toml @@ -11,6 +11,7 @@ repository = { workspace = true } sphinx-packet = { version = "0.1.0" } serde = "1" nym-outfox = { path = "../../../nym-outfox" } +thiserror = "1" [patch.crates-io] sphinx-packet = { path = "../../../../sphinx" } diff --git a/common/nymsphinx/types/src/lib.rs b/common/nymsphinx/types/src/lib.rs index 7a4443e861..fa4bb95f85 100644 --- a/common/nymsphinx/types/src/lib.rs +++ b/common/nymsphinx/types/src/lib.rs @@ -15,9 +15,20 @@ pub use sphinx_packet::{ payload::{Payload, PAYLOAD_OVERHEAD_SIZE}, route::{Destination, DestinationAddressBytes, Node, NodeAddressBytes, SURBIdentifier}, surb::{SURBMaterial, SURB}, - Error, ProcessedPacket, SphinxPacket, + Error as SphinxError, ProcessedPacket, SphinxPacket, }; +use thiserror::Error; +#[derive(Error, Debug)] +pub enum NymPacketError { + #[error("Sphinx error: {0}")] + Sphinx(#[from] sphinx_packet::Error), + + #[error("Outfox error: {0}")] + Outfox(#[from] nym_outfox::error::OutfoxError), +} + +#[allow(clippy::large_enum_variant)] pub enum NymPacket { Sphinx(SphinxPacket), Outfox(OutfoxPacket), @@ -50,10 +61,17 @@ impl NymPacket { self.len() == 0 } - pub fn to_bytes(&self) -> Result, OutfoxError> { + pub fn to_bytes(&self) -> Result, NymPacketError> { match self { NymPacket::Sphinx(packet) => Ok(packet.to_bytes()), - NymPacket::Outfox(packet) => packet.to_bytes(), + NymPacket::Outfox(packet) => Ok(packet.to_bytes()?), + } + } + + pub fn process(self, node_secret_key: &PrivateKey) -> Result { + match self { + NymPacket::Sphinx(packet) => Ok(packet.process(node_secret_key)?), + NymPacket::Outfox(_packet) => todo!(), } } } diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index 8be2ce1711..2a6be45d4a 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.6", +] + [[package]] name = "aes" version = "0.7.5" @@ -9,7 +19,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if", - "cipher", + "cipher 0.3.0", "cpufeatures", "ctr", "opaque-debug 0.3.0", @@ -38,6 +48,12 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "autocfg" version = "1.1.0" @@ -68,6 +84,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -86,6 +111,20 @@ dependencies = [ "opaque-debug 0.2.3", ] +[[package]] +name = "blake3" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.6", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -95,6 +134,15 @@ dependencies = [ "generic-array 0.14.6", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.6", +] + [[package]] name = "bs58" version = "0.4.0" @@ -150,6 +198,30 @@ dependencies = [ "keystream", ] +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher 0.4.4", + "poly1305", + "zeroize", +] + [[package]] name = "cipher" version = "0.3.0" @@ -159,6 +231,17 @@ dependencies = [ "generic-array 0.14.6", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "coconut-test" version = "0.1.0" @@ -190,6 +273,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" +[[package]] +name = "constant_time_eq" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" + [[package]] name = "cosmwasm-crypto" version = "1.0.0" @@ -258,6 +347,49 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -276,6 +408,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.6", + "rand_core 0.6.4", + "typenum", +] + [[package]] name = "crypto-mac" version = "0.7.0" @@ -302,14 +445,14 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] name = "curve25519-dalek" -version = "3.2.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", "digest 0.9.0", @@ -501,6 +644,17 @@ dependencies = [ "generic-array 0.14.6", ] +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle 2.4.1", +] + [[package]] name = "dyn-clone" version = "1.0.11" @@ -701,8 +855,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -750,6 +906,15 @@ dependencies = [ "ahash", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.1" @@ -808,6 +973,15 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.6", +] + [[package]] name = "instant" version = "0.1.12" @@ -823,7 +997,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "libc", "windows-sys 0.45.0", ] @@ -949,6 +1123,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -959,6 +1142,16 @@ dependencies = [ "libm", ] +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + [[package]] name = "nym-coconut-bandwidth" version = "0.1.0" @@ -1105,6 +1298,23 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nym-outfox" +version = "0.1.0" +dependencies = [ + "bincode", + "blake3", + "chacha20", + "chacha20poly1305", + "curve25519-dalek", + "getrandom 0.2.8", + "rayon", + "serde", + "sphinx-packet", + "thiserror", + "zeroize", +] + [[package]] name = "nym-pemstore" version = "0.2.0" @@ -1143,7 +1353,10 @@ dependencies = [ name = "nym-sphinx-types" version = "0.2.0" dependencies = [ + "nym-outfox", + "serde", "sphinx-packet", + "thiserror", ] [[package]] @@ -1232,6 +1445,17 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1379,6 +1603,28 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -1485,6 +1731,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "sec1" version = "0.2.1" @@ -1572,7 +1824,7 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", "digest 0.9.0", @@ -1804,6 +2056,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle 2.4.1", +] + [[package]] name = "url" version = "2.3.1" @@ -2024,9 +2286,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "x25519-dalek" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" dependencies = [ "curve25519-dalek", "rand_core 0.5.1", @@ -2035,9 +2297,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" dependencies = [ "zeroize_derive", ] diff --git a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs index 148dbc2579..dd2bc5d402 100644 --- a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs +++ b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs @@ -11,8 +11,8 @@ use log::*; use nym_mixnet_client::forwarder::MixForwardingSender; use nym_mixnode_common::packet_processor::processor::ProcessedFinalHop; use nym_sphinx::forwarding::packet::MixPacket; -use nym_sphinx::framing::codec::SphinxCodec; -use nym_sphinx::framing::packet::FramedSphinxPacket; +use nym_sphinx::framing::codec::NymCodec; +use nym_sphinx::framing::packet::FramedNymPacket; use nym_sphinx::DestinationAddressBytes; use nym_task::TaskClient; use std::collections::HashMap; @@ -155,7 +155,7 @@ impl ConnectionHandler { self.forward_ack(forward_ack, client_address); } - async fn handle_received_packet(&mut self, framed_sphinx_packet: FramedSphinxPacket) { + async fn handle_received_packet(&mut self, framed_sphinx_packet: FramedNymPacket) { // // TODO: here be replay attack detection - it will require similar key cache to the one in // packet processor for vpn packets, @@ -182,7 +182,7 @@ impl ConnectionHandler { ) { debug!("Starting connection handler for {:?}", remote); shutdown.mark_as_success(); - let mut framed_conn = Framed::new(conn, SphinxCodec); + let mut framed_conn = Framed::new(conn, NymCodec); while !shutdown.is_shutdown() { tokio::select! { biased; diff --git a/gateway/src/node/mixnet_handling/receiver/packet_processing.rs b/gateway/src/node/mixnet_handling/receiver/packet_processing.rs index cf5e5e8e18..e7416c415c 100644 --- a/gateway/src/node/mixnet_handling/receiver/packet_processing.rs +++ b/gateway/src/node/mixnet_handling/receiver/packet_processing.rs @@ -5,7 +5,7 @@ use nym_crypto::asymmetric::encryption; use nym_mixnode_common::packet_processor::error::MixProcessingError; pub use nym_mixnode_common::packet_processor::processor::MixProcessingResult; use nym_mixnode_common::packet_processor::processor::{ProcessedFinalHop, SphinxPacketProcessor}; -use nym_sphinx::framing::packet::FramedSphinxPacket; +use nym_sphinx::framing::packet::FramedNymPacket; use thiserror::Error; #[derive(Error, Debug)] @@ -32,7 +32,7 @@ impl PacketProcessor { pub(crate) fn process_received( &self, - received: FramedSphinxPacket, + received: FramedNymPacket, ) -> Result { match self.inner_processor.process_received(received)? { MixProcessingResult::ForwardHop(..) => { diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index ed08d8c407..d812c60e89 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -9,8 +9,8 @@ use crate::node::TaskClient; use futures::StreamExt; use nym_mixnode_common::measure; use nym_sphinx::forwarding::packet::MixPacket; -use nym_sphinx::framing::codec::SphinxCodec; -use nym_sphinx::framing::packet::FramedSphinxPacket; +use nym_sphinx::framing::codec::NymCodec; +use nym_sphinx::framing::packet::FramedNymPacket; use nym_sphinx::Delay as SphinxDelay; use std::net::SocketAddr; use tokio::net::TcpStream; @@ -54,7 +54,7 @@ impl ConnectionHandler { feature = "cpucycles", instrument(skip(self, framed_sphinx_packet), fields(cpucycles)) )] - fn handle_received_packet(&self, framed_sphinx_packet: FramedSphinxPacket) { + fn handle_received_packet(&self, framed_sphinx_packet: FramedNymPacket) { // // TODO: here be replay attack detection - it will require similar key cache to the one in // packet processor for vpn packets, @@ -86,7 +86,7 @@ impl ConnectionHandler { ) { debug!("Starting connection handler for {:?}", remote); shutdown.mark_as_success(); - let mut framed_conn = Framed::new(conn, SphinxCodec); + let mut framed_conn = Framed::new(conn, NymCodec); while !shutdown.is_shutdown() { tokio::select! { biased; diff --git a/mixnode/src/node/listener/connection_handler/packet_processing.rs b/mixnode/src/node/listener/connection_handler/packet_processing.rs index 9ecf8ad435..1d52602b1d 100644 --- a/mixnode/src/node/listener/connection_handler/packet_processing.rs +++ b/mixnode/src/node/listener/connection_handler/packet_processing.rs @@ -6,7 +6,7 @@ use nym_crypto::asymmetric::encryption; use nym_mixnode_common::packet_processor::error::MixProcessingError; pub use nym_mixnode_common::packet_processor::processor::MixProcessingResult; use nym_mixnode_common::packet_processor::processor::SphinxPacketProcessor; -use nym_sphinx::framing::packet::FramedSphinxPacket; +use nym_sphinx::framing::packet::FramedNymPacket; // PacketProcessor contains all data required to correctly unwrap and forward sphinx packets #[derive(Clone)] @@ -31,7 +31,7 @@ impl PacketProcessor { pub(crate) fn process_received( &self, - received: FramedSphinxPacket, + received: FramedNymPacket, ) -> Result { self.node_stats_update_sender.report_received(); self.inner_processor.process_received(received) diff --git a/mixnode/src/node/packet_delayforwarder.rs b/mixnode/src/node/packet_delayforwarder.rs index 41a3e7e0fa..bcf2a6b669 100644 --- a/mixnode/src/node/packet_delayforwarder.rs +++ b/mixnode/src/node/packet_delayforwarder.rs @@ -5,7 +5,7 @@ use crate::node::node_statistics::UpdateSender; use futures::channel::mpsc; use futures::StreamExt; use nym_nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue}; -use nym_sphinx::forwarding::packet::MixPacket; +use nym_sphinx::{forwarding::packet::MixPacket, NymPacket}; use std::io; use tokio::time::Instant; @@ -61,10 +61,11 @@ where let packet_mode = packet.packet_mode(); let sphinx_packet = packet.into_sphinx_packet(); - if let Err(err) = - self.mixnet_client - .send_without_response(next_hop, sphinx_packet, packet_mode) - { + if let Err(err) = self.mixnet_client.send_without_response( + next_hop, + NymPacket::Sphinx(sphinx_packet), + packet_mode, + ) { if err.kind() == io::ErrorKind::WouldBlock { // we only know for sure if we dropped a packet if our sending queue was full // in any other case the connection might still be re-established (or created for the first time) @@ -147,14 +148,14 @@ mod tests { #[derive(Default)] struct TestClient { - pub packets_sent: Arc>>, + pub packets_sent: Arc>>, } impl nym_mixnet_client::SendWithoutResponse for TestClient { fn send_without_response( &mut self, address: NymNodeRoutingAddress, - packet: SphinxPacket, + packet: NymPacket, packet_mode: PacketMode, ) -> io::Result<()> { self.packets_sent diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 2079832135..dccdd85593 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -217,6 +217,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bip32" version = "0.3.0" @@ -3191,7 +3200,7 @@ dependencies = [ [[package]] name = "nym-bin-common" -version = "0.4.0" +version = "0.5.0" dependencies = [ "atty", "clap", @@ -3560,13 +3569,15 @@ dependencies = [ name = "nym-outfox" version = "0.1.0" dependencies = [ + "bincode", "blake3", "chacha20", "chacha20poly1305", "curve25519-dalek", "getrandom 0.2.8", "rayon", - "sphinx-packet 0.1.0 (git+https://github.com/nymtech/sphinx.git)", + "serde", + "sphinx-packet", "thiserror", "zeroize", ] @@ -3747,9 +3758,11 @@ dependencies = [ name = "nym-sphinx-framing" version = "0.1.0" dependencies = [ + "bincode", "bytes", "nym-sphinx-params", "nym-sphinx-types", + "serde", "thiserror", "tokio-util", ] @@ -3759,6 +3772,7 @@ name = "nym-sphinx-params" version = "0.1.0" dependencies = [ "nym-crypto", + "nym-outfox", "nym-sphinx-types", "serde", "thiserror", @@ -3768,7 +3782,10 @@ dependencies = [ name = "nym-sphinx-types" version = "0.2.0" dependencies = [ - "sphinx-packet 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nym-outfox", + "serde", + "sphinx-packet", + "thiserror", ] [[package]] @@ -3841,7 +3858,7 @@ dependencies = [ [[package]] name = "nym-vesting-contract" -version = "1.3.0" +version = "1.3.1" dependencies = [ "cosmwasm-derive", "cosmwasm-std", @@ -3859,7 +3876,7 @@ dependencies = [ [[package]] name = "nym-vesting-contract-common" -version = "0.4.0" +version = "0.5.0" dependencies = [ "cosmwasm-std", "nym-contracts-common", @@ -5377,29 +5394,6 @@ dependencies = [ "subtle 2.4.1", ] -[[package]] -name = "sphinx-packet" -version = "0.1.0" -source = "git+https://github.com/nymtech/sphinx.git#ca107d94360cdf8bbfbdb12fe5320ed74f80e40c" -dependencies = [ - "aes 0.7.5", - "arrayref", - "blake2", - "bs58", - "byteorder", - "chacha", - "curve25519-dalek", - "digest 0.9.0", - "hkdf 0.11.0", - "hmac 0.11.0", - "lioness", - "log", - "rand 0.7.3", - "rand_distr", - "sha2 0.9.9", - "subtle 2.4.1", -] - [[package]] name = "spin" version = "0.5.2" diff --git a/nym-outfox/src/format.rs b/nym-outfox/src/format.rs index cf9e68d3d9..89778b9eb3 100644 --- a/nym-outfox/src/format.rs +++ b/nym-outfox/src/format.rs @@ -68,21 +68,23 @@ use sphinx_packet::route::Node; use std::convert::TryInto; -const GROUPELEMENTBYTES: usize = 32; -const TAGBYTES: usize = 16; +pub const GROUPELEMENTBYTES: usize = 32; +pub const TAGBYTES: usize = 16; use std::ops::Range; use std::u8; use crate::error::OutfoxError; use crate::lion::*; +use crate::packet::DEFAULT_ROUTING_INFO_SIZE; /// A structure that holds mix packet construction parameters. These incluse the length /// of the routing information at each hop, the number of hops, and the payload length. #[derive(Serialize, Deserialize)] pub struct MixCreationParameters { /// The routing length is inner first, so \[0\] is the innermost routing length, etc (in bytes) - pub routing_information_length_by_stage: Vec, + /// In our stratified topology this will always be 3 + pub routing_information_length_by_stage: [usize; 3], /// The payload length (in bytes) pub payload_length_bytes: usize, } @@ -91,16 +93,16 @@ impl MixCreationParameters { /// Create a set of parameters for a mix packet format. pub fn new(payload_length_bytes: usize) -> MixCreationParameters { MixCreationParameters { - routing_information_length_by_stage: Vec::new(), + routing_information_length_by_stage: [DEFAULT_ROUTING_INFO_SIZE; 3], payload_length_bytes, } } /// Add another outer layer containing some byte length of routing data. - pub fn add_outer_layer(&mut self, routing_information_length_bytes: usize) { - self.routing_information_length_by_stage - .push(routing_information_length_bytes); - } + // pub fn add_outer_layer(&mut self, routing_information_length_bytes: usize) { + // self.routing_information_length_by_stage + // .push(routing_information_length_bytes); + // } /// The length of the buffer needed to build a packet. pub fn total_packet_length(&self) -> usize { diff --git a/nym-outfox/src/packet.rs b/nym-outfox/src/packet.rs index 810d3a6ac4..aed90bf7bf 100644 --- a/nym-outfox/src/packet.rs +++ b/nym-outfox/src/packet.rs @@ -3,11 +3,14 @@ use std::ops::Range; use crate::{ error::OutfoxError, - format::{MixCreationParameters, MixStageParameters}, + format::{MixCreationParameters, MixStageParameters, GROUPELEMENTBYTES, TAGBYTES}, }; use sphinx_packet::{packet::builder::DEFAULT_PAYLOAD_SIZE, route::Node}; +pub const OUTFOX_PACKET_OVERHEAD: usize = + 3 * DEFAULT_ROUTING_INFO_SIZE + GROUPELEMENTBYTES + TAGBYTES; + #[derive(Serialize, Deserialize)] pub struct OutfoxPacket { mix_params: MixCreationParameters, @@ -18,15 +21,20 @@ pub const DEFAULT_ROUTING_INFO_SIZE: usize = 32; impl OutfoxPacket { pub fn len(&self) -> usize { - self.mix_params().total_packet_length() + self.mix_params().total_packet_length() + self.payload.len() } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + // TODO: Replace with lightweight methods pub fn to_bytes(&self) -> Result, OutfoxError> { bincode::serialize(self).map_err(|_e| OutfoxError::Bincode) } pub fn from_bytes(v: &[u8]) -> Result { - Ok(bincode::deserialize(v).map_err(|_| OutfoxError::Bincode)?) + bincode::deserialize(v).map_err(|_| OutfoxError::Bincode) } pub fn build( @@ -34,11 +42,11 @@ impl OutfoxPacket { route: &[Node; 3], user_secret_key: &[u8], ) -> Result { - let mut mix_params = MixCreationParameters::new(DEFAULT_PAYLOAD_SIZE); + let mix_params = MixCreationParameters::new(DEFAULT_PAYLOAD_SIZE); - for node in route.iter() { - mix_params.add_outer_layer(node.address.as_bytes_ref().len()); - } + // for node in route.iter() { + // mix_params.add_outer_layer(node.address.as_bytes_ref().len()); + // } let padding = mix_params.total_packet_length() - payload.len(); let mut buffer = vec![0; padding]; diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 7e496f41d8..e79a3c4184 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -23,6 +23,16 @@ dependencies = [ "generic-array 0.14.6", ] +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.6", +] + [[package]] name = "aes" version = "0.7.5" @@ -30,7 +40,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if", - "cipher", + "cipher 0.3.0", "cpufeatures", "ctr", "opaque-debug 0.3.0", @@ -42,9 +52,9 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" dependencies = [ - "aead", + "aead 0.4.3", "aes", - "cipher", + "cipher 0.3.0", "ctr", "ghash", "subtle 2.4.1", @@ -119,6 +129,12 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "async-trait" version = "0.1.64" @@ -211,6 +227,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bip32" version = "0.3.0" @@ -288,6 +313,20 @@ dependencies = [ "digest 0.10.6", ] +[[package]] +name = "blake3" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.6", +] + [[package]] name = "block" version = "0.1.6" @@ -496,6 +535,30 @@ dependencies = [ "keystream", ] +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead 0.5.2", + "chacha20", + "cipher 0.4.4", + "poly1305", + "zeroize", +] + [[package]] name = "cipher" version = "0.3.0" @@ -505,6 +568,17 @@ dependencies = [ "generic-array 0.14.6", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clap" version = "4.1.4" @@ -636,6 +710,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" +[[package]] +name = "constant_time_eq" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" + [[package]] name = "convert_case" version = "0.4.0" @@ -782,6 +862,30 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.8.0", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -816,6 +920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.6", + "rand_core 0.6.4", "typenum", ] @@ -891,7 +996,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] @@ -1342,7 +1447,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" dependencies = [ - "memoffset", + "memoffset 0.6.5", "rustc_version 0.3.3", ] @@ -2239,6 +2344,15 @@ dependencies = [ "cfb", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.6", +] + [[package]] name = "instant" version = "0.1.12" @@ -2573,6 +2687,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -2959,6 +3082,23 @@ dependencies = [ "url", ] +[[package]] +name = "nym-outfox" +version = "0.1.0" +dependencies = [ + "bincode", + "blake3", + "chacha20", + "chacha20poly1305", + "curve25519-dalek", + "getrandom 0.2.8", + "rayon", + "serde", + "sphinx-packet", + "thiserror", + "zeroize", +] + [[package]] name = "nym-pemstore" version = "0.2.0" @@ -2970,7 +3110,10 @@ dependencies = [ name = "nym-sphinx-types" version = "0.2.0" dependencies = [ + "nym-outfox", + "serde", "sphinx-packet", + "thiserror", ] [[package]] @@ -3642,6 +3785,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.5.0", +] + [[package]] name = "polyval" version = "0.5.3" @@ -3651,7 +3805,7 @@ dependencies = [ "cfg-if", "cpufeatures", "opaque-debug 0.3.0", - "universal-hash", + "universal-hash 0.4.1", ] [[package]] @@ -3894,6 +4048,28 @@ dependencies = [ "cty", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -5441,6 +5617,16 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle 2.4.1", +] + [[package]] name = "untrusted" version = "0.7.1"