Running CI also on windows and macOS (#512)

* Running CI also on windows and macOS

* Rust 2021 formatting

* clippy::upper_case_acronyms where appropriate

* Allowing unknown clippy lints

* Further clippy updates

* Building wasm client during CI

* wasm actions update

* added working directory to cargo jobs

* Temporarily disabled wasm test and clippy
This commit is contained in:
Jędrzej Stuczyński
2021-03-01 11:06:13 +00:00
committed by GitHub
parent 6f8ae53f0c
commit 83753af944
50 changed files with 339 additions and 287 deletions
+3 -5
View File
@@ -4,14 +4,12 @@ on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.rust == 'nightly' }}
strategy:
matrix:
rust:
- stable
- beta
- nightly
rust: [stable, beta, nightly]
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v2
+39
View File
@@ -0,0 +1,39 @@
name: Wasm Client
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
- uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
# - uses: actions-rs/cargo@v1
# with:
# command: test
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path clients/webassembly/Cargo.toml -- --check
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
# - uses: actions-rs/cargo@v1
# with:
# command: clippy
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
@@ -1,6 +1,6 @@
use futures::channel::mpsc;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
pub type InputMessageSender = mpsc::UnboundedSender<InputMessage>;
pub type InputMessageReceiver = mpsc::UnboundedReceiver<InputMessage>;
@@ -13,7 +13,7 @@ pub enum InputMessage {
with_reply_surb: bool,
},
Reply {
reply_surb: ReplySURB,
reply_surb: ReplySurb,
data: Vec<u8>,
},
}
@@ -27,7 +27,7 @@ impl InputMessage {
}
}
pub fn new_reply(reply_surb: ReplySURB, data: Vec<u8>) -> Self {
pub fn new_reply(reply_surb: ReplySurb, data: Vec<u8>) -> Self {
InputMessage::Reply { reply_surb, data }
}
}
@@ -22,7 +22,7 @@ use crate::client::{
};
use futures::StreamExt;
use log::*;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
use nymsphinx::preparer::MessagePreparer;
use nymsphinx::{acknowledgements::AckKey, addressing::clients::Recipient};
use rand::{CryptoRng, Rng};
@@ -75,7 +75,7 @@ where
}
// we require topology for replies to generate surb_acks
async fn handle_reply(&mut self, reply_surb: ReplySURB, data: Vec<u8>) -> Option<RealMessage> {
async fn handle_reply(&mut self, reply_surb: ReplySurb, data: Vec<u8>) -> Option<RealMessage> {
let topology_permit = self.topology_access.get_read_permit().await;
let topology = match topology_permit.try_get_valid_topology_ref(&self.ack_recipient, None) {
Some(topology_ref) => topology_ref,
@@ -21,8 +21,8 @@ use futures::lock::Mutex;
use futures::StreamExt;
use gateway_client::MixnetMessageReceiver;
use log::*;
use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SURBEncryptionKey};
use nymsphinx::params::{ReplySURBEncryptionAlgorithm, ReplySURBKeyDigestAlgorithm};
use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SurbEncryptionKey};
use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm};
use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
use std::collections::HashSet;
use std::sync::Arc;
@@ -191,11 +191,11 @@ impl ReceivedMessagesBuffer {
fn process_received_reply(
reply_ciphertext: &[u8],
reply_key: SURBEncryptionKey,
reply_key: SurbEncryptionKey,
) -> Option<ReconstructedMessage> {
let zero_iv = stream_cipher::zero_iv::<ReplySURBEncryptionAlgorithm>();
let zero_iv = stream_cipher::zero_iv::<ReplySurbEncryptionAlgorithm>();
let mut reply_msg = stream_cipher::decrypt::<ReplySURBEncryptionAlgorithm>(
let mut reply_msg = stream_cipher::decrypt::<ReplySurbEncryptionAlgorithm>(
&reply_key.inner(),
&zero_iv,
reply_ciphertext,
@@ -221,7 +221,7 @@ impl ReceivedMessagesBuffer {
let mut completed_messages = Vec::new();
let mut inner_guard = self.inner.lock().await;
let reply_surb_digest_size = ReplySURBKeyDigestAlgorithm::output_size();
let reply_surb_digest_size = ReplySurbKeyDigestAlgorithm::output_size();
// first check if this is a reply or a chunked message
// TODO: verify with @AP if this way of doing it is safe or whether it could
@@ -14,8 +14,8 @@
use log::*;
use nymsphinx::anonymous_replies::{
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SURBEncryptionKey,
SURBEncryptionKeySize,
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SurbEncryptionKey,
SurbEncryptionKeySize,
};
use std::path::Path;
@@ -49,24 +49,24 @@ impl ReplyKeyStorage {
Ok(ReplyKeyStorage { db })
}
fn read_encryption_key(&self, raw_key: sled::IVec) -> SURBEncryptionKey {
fn read_encryption_key(&self, raw_key: sled::IVec) -> SurbEncryptionKey {
let key_bytes_ref = raw_key.as_ref();
// if this fails it means we have some database corruption and we
// absolutely can't continue
if key_bytes_ref.len() != SURBEncryptionKeySize::to_usize() {
if key_bytes_ref.len() != SurbEncryptionKeySize::to_usize() {
error!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
panic!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
}
// this can only fail if the bytes have invalid length but we already asserted it
SURBEncryptionKey::try_from_bytes(key_bytes_ref).unwrap()
SurbEncryptionKey::try_from_bytes(key_bytes_ref).unwrap()
}
// TOOD: perhaps we could also store some part of original message here too?
pub fn insert_encryption_key(
&mut self,
encryption_key: SURBEncryptionKey,
encryption_key: SurbEncryptionKey,
) -> Result<(), ReplyKeyStorageError> {
let digest = encryption_key.compute_digest();
@@ -89,7 +89,7 @@ impl ReplyKeyStorage {
pub fn get_and_remove_encryption_key(
&self,
key_digest: EncryptionKeyDigest,
) -> Result<Option<SURBEncryptionKey>, ReplyKeyStorageError> {
) -> Result<Option<SurbEncryptionKey>, ReplyKeyStorageError> {
let removal_result = match self.db.remove(&key_digest.to_vec()) {
Err(e) => Err(ReplyKeyStorageError::DbReadError(e)),
Ok(existing_key) => {
+3 -3
View File
@@ -42,7 +42,7 @@ use gateway_client::{
use log::*;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
use nymsphinx::params::PacketMode;
use nymsphinx::receiver::ReconstructedMessage;
use tokio::runtime::Runtime;
@@ -132,7 +132,7 @@ impl NymClient {
mix_sender: BatchMixMessageSender,
) {
let packet_mode = if self.config.get_base().get_vpn_mode() {
PacketMode::VPN
PacketMode::Vpn
} else {
PacketMode::Mix
};
@@ -297,7 +297,7 @@ impl NymClient {
/// EXPERIMENTAL DIRECT RUST API
/// It's untested and there are absolutely no guarantees about it (but seems to have worked
/// well enough in local tests)
pub fn send_reply(&mut self, reply_surb: ReplySURB, message: Vec<u8>) {
pub fn send_reply(&mut self, reply_surb: ReplySurb, message: Vec<u8>) {
let input_msg = InputMessage::new_reply(reply_surb, message);
self.input_tx
+4 -4
View File
@@ -22,7 +22,7 @@ use futures::channel::mpsc;
use futures::{SinkExt, StreamExt};
use log::*;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
use nymsphinx::receiver::ReconstructedMessage;
use tokio::net::TcpStream;
use tokio_tungstenite::{
@@ -100,9 +100,9 @@ impl Handler {
None
}
fn handle_reply(&mut self, reply_surb: ReplySURB, message: Vec<u8>) -> Option<ServerResponse> {
if message.len() > ReplySURB::max_msg_len(Default::default()) {
return Some(ServerResponse::new_error(format!("too long message to put inside a reply SURB. Received: {} bytes and maximum is {} bytes", message.len(), ReplySURB::max_msg_len(Default::default()))));
fn handle_reply(&mut self, reply_surb: ReplySurb, message: Vec<u8>) -> Option<ServerResponse> {
if message.len() > ReplySurb::max_msg_len(Default::default()) {
return Some(ServerResponse::new_error(format!("too long message to put inside a reply SURB. Received: {} bytes and maximum is {} bytes", message.len(), ReplySurb::max_msg_len(Default::default()))));
}
let input_msg = InputMessage::new_reply(reply_surb, message);
@@ -18,7 +18,7 @@
use crate::error::{self, ErrorKind};
use crate::text::ClientRequestText;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
use std::convert::{TryFrom, TryInto};
use std::mem::size_of;
@@ -42,7 +42,7 @@ pub enum ClientRequest {
},
Reply {
message: Vec<u8>,
reply_surb: ReplySURB,
reply_surb: ReplySurb,
},
SelfAddress,
}
@@ -119,7 +119,7 @@ impl ClientRequest {
}
// REPLY_REQUEST_TAG || surb_len || surb || message_len || message
fn serialize_reply(message: Vec<u8>, reply_surb: ReplySURB) -> Vec<u8> {
fn serialize_reply(message: Vec<u8>, reply_surb: ReplySurb) -> Vec<u8> {
let reply_surb_bytes = reply_surb.to_bytes();
let surb_len_bytes = (reply_surb_bytes.len() as u64).to_be_bytes();
let message_len_bytes = (message.len() as u64).to_be_bytes();
@@ -164,7 +164,7 @@ impl ClientRequest {
let surb_bound = 1 + size_of::<u64>() + reply_surb_len as usize;
let reply_surb_bytes = &b[1 + size_of::<u64>()..surb_bound];
let reply_surb = match ReplySURB::from_bytes(reply_surb_bytes) {
let reply_surb = match ReplySurb::from_bytes(reply_surb_bytes) {
Ok(reply_surb) => reply_surb,
Err(err) => {
return Err(error::Error::new(
@@ -333,7 +333,7 @@ mod tests {
#[test]
fn reply_request_serialization_works() {
let reply_surb_string = "CjfVbHbfAjbC3W1BvNHGXmM8KNAnDNYGaHMLqVDxRYeo352csAihstup9bvqXam4dTWgfHak6KYwL9STaxWJ47E8XFZbSEvs7hEsfCkxr6K9WJuSBPK84GDDEvad8ZAuMCoaXsAd5S2Lj9a5eYyzG4SL1jHzhSMni55LyJwumxo1ZTGZNXggxw1RREosvyzNrW9Rsi3owyPqLCwXpiei2tHZty8w8midVvg8vDa7ZEJD842CLv8D4ohynSG7gDpqTrhkRaqYAuz7dzqNbMXLJRM7v823Jn16fA1L7YQxmcaUdUigyRSgTdb4i9ebiLGSyJ1iDe6Acz613PQZh6Ua3bZ2zVKq3dSycpDm9ngarRK4zJrAaUxRkdih8YzW3BY4nL9eqkfKA4N1TWCLaRU7zpSaf8yMEwrAZReU3d5zLV8c5KBfa2w8R5anhQeBojduZEGEad8kkHuKU52Zg93FeWHvH1qgZaEJMHH4nN7gKXz9mvWDhYwyF4vt3Uy2NhCHC3N5pL1gMme27YcoPcTEia1fxKZtnt6rtEozzTrAgCJGswigkFbkafiV5QaJwLKTUxtzhkZ57eEuLPte9UvJHzhhXUQ2CV7R2BUkJjYZy3Zsx6YYvdYWiAFFkWUwNEGA4QpShUHciBfsQVHQ7pN41YcyYUhbywQDFnTVgEmdUZ1XCBi3gyK5U3tDQmFzP1u9m3mWrUA8qB9mRDE7ptNDm5c3c1458L6uXLUth7sdMaa1Was5LCmCdmNDtvNpCDAEt1in6q6mrZFR85aCSU9b1baNGwZoCqPpPvydkVe63gXWoi8ebvdyxARrqACFrSB3ZdY3uJBw8CTMNkKK6MvcefMkSVVsbLd36TQAtYSCqrpiMc5dQuKcEu5QfciwvWYXYx8WFNAgKwP2mv49KCTvfozNDUCbjzDwSx92Zv5zjG8HbFpB13bY9UZGeyTPvv7gGxCzjGjJGbW6FRAheRQaaje5fUgCNM95Tv7wBmAMRHHFgWafeK1sdFH7dtCX9u898HucGTaboSKLsVh8J78gbbkHErwjMh7y9YRkceq5TTYS5da4kHnyNKYWSbxgZrmFg44XGKoeYcqoHB3XTZrdsf7F5fFeNwnihkmADvhAcaxXUmVqq4rQFZH84a1iC3WBWXYcqiZH2L7ujGWV7mMDT4HBEerDYjc8rNY4xGTPfivCrBCJW1i14aqW8xRdsdgTM88eTksvC3WPJLJ7iMzfKXeL7fMW1Ek6QGyQtLBW98vEESpdcDg6DeZ5rMz6VqjTGGqcCaFGfHoqtfxMDaBAEsyQ8h7XDX6dg1wq9wH6j4Tw7Tj1MEv1b8uj5NJkozZdzVdYA2QyE2Dp8vuurQG6uVdTDNww2d88RBQ8sVgjxN8gR45y4woJLhFAaNTAtrY6wDTxyXST13ni6oyqdYxjFVk9Am4v3DzH7Y2K8iRVSHfTk4FRbPULyaeK6wt2anvMJH1XdvVRgc14h67MnBxMgMD1UFk8AErN7CDj26fppe3c5G6KozJe4cSqQUGbBjVzBnrHCruqrfZBn5hNZHTV37bQiomqhRQXohxhuKEnNrGbAe1xNvJr9X";
let reply_surb = ReplySURB::from_base58_string(reply_surb_string).unwrap();
let reply_surb = ReplySurb::from_base58_string(reply_surb_string).unwrap();
let reply_request = ClientRequest::Reply {
message: b"foomp".to_vec(),
reply_surb,
@@ -18,7 +18,7 @@
use crate::error::{self, ErrorKind};
use crate::text::ServerResponseText;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
use nymsphinx::receiver::ReconstructedMessage;
use std::convert::TryInto;
use std::mem::size_of;
@@ -111,7 +111,7 @@ impl ServerResponse {
let surb_bound = 2 + size_of::<u64>() + reply_surb_len as usize;
let reply_surb_bytes = &b[2 + size_of::<u64>()..surb_bound];
let reply_surb = match ReplySURB::from_bytes(reply_surb_bytes) {
let reply_surb = match ReplySurb::from_bytes(reply_surb_bytes) {
Ok(reply_surb) => reply_surb,
Err(err) => {
return Err(error::Error::new(
@@ -339,7 +339,7 @@ mod tests {
let received_with_surb = ServerResponse::Received(ReconstructedMessage {
message: b"foomp".to_vec(),
reply_surb: Some(ReplySURB::from_base58_string(reply_surb_string).unwrap()),
reply_surb: Some(ReplySurb::from_base58_string(reply_surb_string).unwrap()),
});
let bytes = received_with_surb.serialize();
let recovered = ServerResponse::deserialize(&bytes).unwrap();
@@ -16,7 +16,7 @@ use crate::error::ErrorKind;
use crate::requests::ClientRequest;
use crate::responses::ServerResponse;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::ReplySURB;
use nymsphinx::anonymous_replies::ReplySurb;
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
@@ -75,7 +75,7 @@ impl TryInto<ClientRequest> for ClientRequestText {
reply_surb,
} => {
let message_bytes = message.into_bytes();
let reply_surb = ReplySURB::from_base58_string(reply_surb).map_err(|err| {
let reply_surb = ReplySurb::from_base58_string(reply_surb).map_err(|err| {
Self::Error::new(ErrorKind::MalformedRequest, err.to_string())
})?;
+1 -1
View File
@@ -120,7 +120,7 @@ impl NymClient {
mix_sender: BatchMixMessageSender,
) {
let packet_mode = if self.config.get_base().get_vpn_mode() {
PacketMode::VPN
PacketMode::Vpn
} else {
PacketMode::Mix
};
+1 -1
View File
@@ -34,7 +34,7 @@ pub(crate) mod received_processor;
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(200);
const DEFAULT_AVERAGE_ACK_DELAY: Duration = Duration::from_millis(200);
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_millis(1_500);
const DEFAULT_PACKET_MODE: PacketMode = PacketMode::VPN;
const DEFAULT_PACKET_MODE: PacketMode = PacketMode::Vpn;
const DEFAULT_VPN_KEY_REUSE_LIMIT: usize = 1000;
#[wasm_bindgen]
@@ -50,10 +50,10 @@ impl PacketRouter {
// remember: gateway removes final layer of sphinx encryption and from the unwrapped
// data he takes the SURB-ACK and first hop address.
// currently SURB-ACKs are attached in EVERY packet, even cover, so this is always true
let ack_overhead = PacketSize::ACKPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
let ack_overhead = PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
for received_packet in unwrapped_packets {
if received_packet.len() == PacketSize::ACKPacket.plaintext_size() {
if received_packet.len() == PacketSize::AckPacket.plaintext_size() {
received_acks.push(received_packet);
} else if received_packet.len()
== PacketSize::RegularPacket.plaintext_size() - ack_overhead
+21 -21
View File
@@ -18,8 +18,8 @@ use crate::models::mixnode::MixRegistrationInfo;
use crate::models::topology::Topology;
use crate::rest_requests::{
ActiveTopologyGet, ActiveTopologyGetResponse, BatchMixStatusPost, GatewayRegisterPost,
MixRegisterPost, MixStatusPost, NodeUnregisterDelete, RESTRequest, RESTRequestError,
ReputationPatch, TopologyGet, TopologyGetResponse,
MixRegisterPost, MixStatusPost, NodeUnregisterDelete, ReputationPatch, RestRequest,
RestRequestError, TopologyGet, TopologyGetResponse,
};
use serde::Deserialize;
use std::fmt::{self, Display, Formatter};
@@ -66,22 +66,22 @@ struct OkResponse {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub(crate) enum DefaultRESTResponse {
pub(crate) enum DefaultRestResponse {
Ok(OkResponse),
Error(ErrorResponses),
}
#[derive(Debug)]
pub enum ValidatorClientError {
RESTRequestError(RESTRequestError),
RestRequestError(RestRequestError),
ReqwestClientError(reqwest::Error),
ValidatorError(String),
UnexpectedResponse(String),
}
impl From<RESTRequestError> for ValidatorClientError {
fn from(err: RESTRequestError) -> Self {
ValidatorClientError::RESTRequestError(err)
impl From<RestRequestError> for ValidatorClientError {
fn from(err: RestRequestError) -> Self {
ValidatorClientError::RestRequestError(err)
}
}
@@ -94,7 +94,7 @@ impl From<reqwest::Error> for ValidatorClientError {
impl Display for ValidatorClientError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ValidatorClientError::RESTRequestError(err) => {
ValidatorClientError::RestRequestError(err) => {
write!(f, "could not prepare the REST request - {}", err)
}
ValidatorClientError::ReqwestClientError(err) => {
@@ -151,7 +151,7 @@ impl Client {
}
}
async fn make_rest_request<R: RESTRequest>(
async fn make_rest_request<R: RestRequest>(
&self,
request: R,
) -> Result<R::ExpectedJsonResponse> {
@@ -174,8 +174,8 @@ impl Client {
Some(mix_registration_info),
)?;
match self.make_rest_request(req).await? {
DefaultRESTResponse::Ok(_) => Ok(()),
DefaultRESTResponse::Error(err) => Err(err.into()),
DefaultRestResponse::Ok(_) => Ok(()),
DefaultRestResponse::Error(err) => Err(err.into()),
}
}
@@ -190,7 +190,7 @@ impl Client {
Some(gateway_registration_info),
)?;
match self.make_rest_request(req).await? {
DefaultRESTResponse::Ok(ok_res) => {
DefaultRestResponse::Ok(ok_res) => {
if ok_res.ok {
Ok(())
} else {
@@ -199,7 +199,7 @@ impl Client {
))
}
}
DefaultRESTResponse::Error(err) => Err(err.into()),
DefaultRestResponse::Error(err) => Err(err.into()),
}
}
@@ -208,7 +208,7 @@ impl Client {
NodeUnregisterDelete::new(&self.config.base_url, Some(vec![node_id]), None, None)?;
match self.make_rest_request(req).await? {
DefaultRESTResponse::Ok(ok_res) => {
DefaultRestResponse::Ok(ok_res) => {
if ok_res.ok {
Ok(())
} else {
@@ -217,7 +217,7 @@ impl Client {
))
}
}
DefaultRESTResponse::Error(err) => Err(err.into()),
DefaultRestResponse::Error(err) => Err(err.into()),
}
}
@@ -238,7 +238,7 @@ impl Client {
None,
)?;
match self.make_rest_request(req).await? {
DefaultRESTResponse::Ok(ok_res) => {
DefaultRestResponse::Ok(ok_res) => {
if ok_res.ok {
Ok(())
} else {
@@ -247,7 +247,7 @@ impl Client {
))
}
}
DefaultRESTResponse::Error(err) => Err(err.into()),
DefaultRestResponse::Error(err) => Err(err.into()),
}
}
@@ -270,7 +270,7 @@ impl Client {
pub async fn post_mixmining_status(&self, status: MixStatus) -> Result<()> {
let req = MixStatusPost::new(&self.config.base_url, None, None, Some(status))?;
match self.make_rest_request(req).await? {
DefaultRESTResponse::Ok(ok_res) => {
DefaultRestResponse::Ok(ok_res) => {
if ok_res.ok {
Ok(())
} else {
@@ -279,14 +279,14 @@ impl Client {
))
}
}
DefaultRESTResponse::Error(err) => Err(err.into()),
DefaultRestResponse::Error(err) => Err(err.into()),
}
}
pub async fn post_batch_mixmining_status(&self, batch_status: BatchMixStatus) -> Result<()> {
let req = BatchMixStatusPost::new(&self.config.base_url, None, None, Some(batch_status))?;
match self.make_rest_request(req).await? {
DefaultRESTResponse::Ok(ok_res) => {
DefaultRestResponse::Ok(ok_res) => {
if ok_res.ok {
Ok(())
} else {
@@ -295,7 +295,7 @@ impl Client {
))
}
}
DefaultRESTResponse::Error(err) => Err(err.into()),
DefaultRestResponse::Error(err) => Err(err.into()),
}
}
}
@@ -13,7 +13,7 @@
// limitations under the License.
use crate::models::topology::Topology;
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::ErrorResponses;
use reqwest::{Method, Url};
use serde::Deserialize;
@@ -29,7 +29,7 @@ pub(crate) enum Response {
Error(ErrorResponses),
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::GET;
const RELATIVE_PATH: &'static str = "/api/mixmining/topology/active";
@@ -41,9 +41,9 @@ impl RESTRequest for Request {
_: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
_: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
) -> Result<Self, RestRequestError> {
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url })
}
@@ -13,8 +13,8 @@
// limitations under the License.
use crate::models::gateway::GatewayRegistrationInfo;
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::DefaultRESTResponse;
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::DefaultRestResponse;
use reqwest::{Method, Url};
pub struct Request {
@@ -22,22 +22,22 @@ pub struct Request {
payload: GatewayRegistrationInfo,
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::POST;
const RELATIVE_PATH: &'static str = "/api/mixmining/register/gateway";
type JsonPayload = GatewayRegistrationInfo;
type ExpectedJsonResponse = DefaultRESTResponse;
type ExpectedJsonResponse = DefaultRestResponse;
fn new(
base_url: &str,
_: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
body_payload: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
) -> Result<Self, RestRequestError> {
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url, payload })
}
@@ -1,6 +1,6 @@
use crate::models::mixmining::BatchMixStatus;
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::DefaultRESTResponse;
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::DefaultRestResponse;
use reqwest::{Method, Url};
pub struct Request {
@@ -8,21 +8,21 @@ pub struct Request {
payload: BatchMixStatus,
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::POST;
const RELATIVE_PATH: &'static str = "/api/mixmining/batch";
type JsonPayload = BatchMixStatus;
type ExpectedJsonResponse = DefaultRESTResponse;
type ExpectedJsonResponse = DefaultRestResponse;
fn new(
base_url: &str,
_: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
body_payload: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
) -> Result<Self, RestRequestError> {
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url, payload })
}
@@ -1,6 +1,6 @@
use crate::models::mixmining::MixStatus;
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::DefaultRESTResponse;
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::DefaultRestResponse;
use reqwest::{Method, Url};
pub struct Request {
@@ -8,21 +8,21 @@ pub struct Request {
payload: MixStatus,
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::POST;
const RELATIVE_PATH: &'static str = "/api/mixmining";
type JsonPayload = MixStatus;
type ExpectedJsonResponse = DefaultRESTResponse;
type ExpectedJsonResponse = DefaultRestResponse;
fn new(
base_url: &str,
_: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
body_payload: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
) -> Result<Self, RestRequestError> {
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url, payload })
}
@@ -13,8 +13,8 @@
// limitations under the License.
use crate::models::mixnode::MixRegistrationInfo;
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::DefaultRESTResponse;
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::DefaultRestResponse;
use reqwest::{Method, Url};
pub struct Request {
@@ -22,22 +22,22 @@ pub struct Request {
payload: MixRegistrationInfo,
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::POST;
const RELATIVE_PATH: &'static str = "/api/mixmining/register/mix";
type JsonPayload = MixRegistrationInfo;
type ExpectedJsonResponse = DefaultRESTResponse;
type ExpectedJsonResponse = DefaultRestResponse;
fn new(
base_url: &str,
_: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
body_payload: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
) -> Result<Self, RestRequestError> {
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url, payload })
}
@@ -40,35 +40,35 @@ type PathParam<'a> = &'a str;
type QueryParam<'a> = (&'a str, &'a str);
#[derive(Debug)]
pub enum RESTRequestError {
pub enum RestRequestError {
InvalidPathParams,
InvalidQueryParams,
NoPayloadProvided,
MalformedUrl(String),
}
impl Display for RESTRequestError {
impl Display for RestRequestError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
RESTRequestError::InvalidPathParams => write!(
RestRequestError::InvalidPathParams => write!(
f,
"invalid number of path parameters was provided or they were malformed"
),
RESTRequestError::InvalidQueryParams => write!(
RestRequestError::InvalidQueryParams => write!(
f,
"invalid number of query parameters was provided or they were malformed"
),
RESTRequestError::NoPayloadProvided => {
RestRequestError::NoPayloadProvided => {
write!(f, "no request payload was provided while it was expected")
}
RESTRequestError::MalformedUrl(url) => {
RestRequestError::MalformedUrl(url) => {
write!(f, "tried to make request to malformed url ({})", url)
}
}
}
}
pub(crate) trait RESTRequest {
pub(crate) trait RestRequest {
// 'GET', 'POST', 'DELETE', etc.
const METHOD: Method;
const RELATIVE_PATH: &'static str;
@@ -81,7 +81,7 @@ pub(crate) trait RESTRequest {
path_params: Option<Vec<PathParam>>,
query_params: Option<Vec<QueryParam>>,
body_payload: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError>
) -> Result<Self, RestRequestError>
where
Self: Sized;
@@ -12,36 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::DefaultRESTResponse;
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::DefaultRestResponse;
use reqwest::{Method, Url};
pub struct Request {
url: Url,
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::DELETE;
const RELATIVE_PATH: &'static str = "/api/mixmining/register";
type JsonPayload = ();
type ExpectedJsonResponse = DefaultRESTResponse;
type ExpectedJsonResponse = DefaultRestResponse;
fn new(
base_url: &str,
path_params: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
_: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
) -> Result<Self, RestRequestError> {
// node unregister requires single path param - the node id
let path_params = path_params.ok_or(RESTRequestError::InvalidPathParams)?;
let path_params = path_params.ok_or(RestRequestError::InvalidPathParams)?;
if path_params.len() != 1 {
return Err(RESTRequestError::InvalidPathParams);
return Err(RestRequestError::InvalidPathParams);
}
// <base_url>/api/mixmining/register/{id}
let base = format!("{}{}/{}", base_url, Self::RELATIVE_PATH, path_params[0]);
let url =
Url::parse(&base).map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
Url::parse(&base).map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url })
}
@@ -12,43 +12,43 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::DefaultRESTResponse;
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::DefaultRestResponse;
use reqwest::{Method, Url};
pub struct Request {
url: Url,
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::PATCH;
const RELATIVE_PATH: &'static str = "/api/mixmining/reputation";
type JsonPayload = ();
type ExpectedJsonResponse = DefaultRESTResponse;
type ExpectedJsonResponse = DefaultRestResponse;
fn new(
base_url: &str,
path_params: Option<Vec<PathParam>>,
query_params: Option<Vec<QueryParam>>,
_: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
) -> Result<Self, RestRequestError> {
// set reputation requires single path param - the node id
// and single query param - what reputation should it be set to
let path_params = path_params.ok_or(RESTRequestError::InvalidPathParams)?;
let path_params = path_params.ok_or(RestRequestError::InvalidPathParams)?;
if path_params.len() != 1 {
return Err(RESTRequestError::InvalidPathParams);
return Err(RestRequestError::InvalidPathParams);
}
let query_params = query_params.ok_or(RESTRequestError::InvalidQueryParams)?;
let query_params = query_params.ok_or(RestRequestError::InvalidQueryParams)?;
if query_params.len() != 1 {
return Err(RESTRequestError::InvalidQueryParams);
return Err(RestRequestError::InvalidQueryParams);
}
// <base_url>/api/mixmining/reputation/{id}
let base = format!("{}{}/{}", base_url, Self::RELATIVE_PATH, path_params[0]);
let url = Url::parse_with_params(&base, query_params)
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url })
}
@@ -13,7 +13,7 @@
// limitations under the License.
use crate::models::topology::Topology;
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
use crate::ErrorResponses;
use reqwest::{Method, Url};
use serde::Deserialize;
@@ -29,7 +29,7 @@ pub(crate) enum Response {
Error(ErrorResponses),
}
impl RESTRequest for Request {
impl RestRequest for Request {
const METHOD: Method = Method::GET;
const RELATIVE_PATH: &'static str = "/api/mixmining/topology";
@@ -41,9 +41,9 @@ impl RESTRequest for Request {
_: Option<Vec<PathParam>>,
_: Option<Vec<QueryParam>>,
_: Option<Self::JsonPayload>,
) -> Result<Self, RESTRequestError> {
) -> Result<Self, RestRequestError> {
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
Ok(Request { url })
}
@@ -1,3 +1,9 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![allow(renamed_and_removed_lints)]
#![allow(unknown_lints)] // beta-nightly
#![allow(clippy::unknown_clippy_lints)] // `clippy::upper_case_acronyms` does not exist on stable just yet
use generic_array::{typenum::Unsigned, GenericArray};
use rand::{CryptoRng, RngCore};
use stream_cipher::{Nonce, StreamCipher, SyncStreamCipher};
@@ -12,6 +18,9 @@ pub use stream_cipher::{Key, NewStreamCipher};
// means that for, for example, 128-bit security, after generating 2^64 IVs
// we are going to have 50% chance of collision. But perhaps that's fine?
// TODO2: ask @AP if what I wrote here even makes sense in the context of what we're doing.
// I think 'IV' looks better than 'Iv', feel free to change that.
#[allow(clippy::upper_case_acronyms)]
pub type IV<C> = Nonce<C>;
pub fn generate_key<C, R>(rng: &mut R) -> Key<C>
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use nymsphinx_acknowledgements::surb_ack::SURBAckRecoveryError;
use nymsphinx_acknowledgements::surb_ack::SurbAckRecoveryError;
use nymsphinx_addressing::nodes::NymNodeRoutingAddressError;
use nymsphinx_types::Error as SphinxError;
use std::fmt::{self, Display, Formatter};
@@ -21,8 +21,8 @@ use std::fmt::{self, Display, Formatter};
pub enum MixProcessingError {
SphinxProcessingError(SphinxError),
InvalidHopAddress(NymNodeRoutingAddressError),
NoSURBAckInFinalHop,
MalformedSURBAck(SURBAckRecoveryError),
NoSurbAckInFinalHop,
MalformedSurbAck(SurbAckRecoveryError),
}
impl From<SphinxError> for MixProcessingError {
@@ -42,11 +42,11 @@ impl From<NymNodeRoutingAddressError> for MixProcessingError {
}
}
impl From<SURBAckRecoveryError> for MixProcessingError {
fn from(err: SURBAckRecoveryError) -> Self {
impl From<SurbAckRecoveryError> for MixProcessingError {
fn from(err: SurbAckRecoveryError) -> Self {
use MixProcessingError::*;
MalformedSURBAck(err)
MalformedSurbAck(err)
}
}
@@ -59,10 +59,10 @@ impl Display for MixProcessingError {
MixProcessingError::InvalidHopAddress(address_err) => {
write!(f, "Invalid Hop Address - {:?}", address_err)
}
MixProcessingError::NoSURBAckInFinalHop => {
MixProcessingError::NoSurbAckInFinalHop => {
write!(f, "No SURBAck present in the final hop data")
}
MixProcessingError::MalformedSURBAck(surb_ack_err) => {
MixProcessingError::MalformedSurbAck(surb_ack_err) => {
write!(f, "Malformed SURBAck - {:?}", surb_ack_err)
}
}
@@ -15,7 +15,7 @@
use crate::cached_packet_processor::cache::KeyCache;
use crate::cached_packet_processor::error::MixProcessingError;
use log::*;
use nymsphinx_acknowledgements::surb_ack::SURBAck;
use nymsphinx_acknowledgements::surb_ack::SurbAck;
use nymsphinx_addressing::nodes::NymNodeRoutingAddress;
use nymsphinx_forwarding::packet::MixPacket;
use nymsphinx_framing::packet::FramedSphinxPacket;
@@ -181,11 +181,11 @@ impl CachedPacketProcessor {
) -> Result<(Vec<u8>, Vec<u8>), MixProcessingError> {
// in theory it's impossible for this to fail since it managed to go into correct `match`
// branch at the caller
if extracted_data.len() < SURBAck::len() {
return Err(MixProcessingError::NoSURBAckInFinalHop);
if extracted_data.len() < SurbAck::len() {
return Err(MixProcessingError::NoSurbAckInFinalHop);
}
let message = extracted_data.split_off(SURBAck::len());
let message = extracted_data.split_off(SurbAck::len());
let ack_data = extracted_data;
Ok((ack_data, message))
}
@@ -199,14 +199,14 @@ impl CachedPacketProcessor {
packet_mode: PacketMode,
) -> Result<(Option<MixPacket>, Vec<u8>), MixProcessingError> {
match packet_size {
PacketSize::ACKPacket => {
PacketSize::AckPacket => {
trace!("received an ack packet!");
Ok((None, data))
}
PacketSize::RegularPacket | PacketSize::ExtendedPacket => {
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)?;
let (ack_first_hop, ack_packet) = SurbAck::try_recover_first_hop_packet(&ack_data)?;
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_mode);
Ok((Some(forward_ack), message))
}
@@ -403,7 +403,7 @@ mod tests {
assert!(processor.vpn_key_cache.is_empty());
let final_hop = make_valid_final_sphinx_packet(Default::default(), local_keys.1);
let framed = FramedSphinxPacket::new(final_hop, PacketMode::VPN);
let framed = FramedSphinxPacket::new(final_hop, PacketMode::Vpn);
processor.perform_initial_unwrapping(framed).unwrap();
assert_eq!(processor.vpn_key_cache.len(), 1);
@@ -416,7 +416,7 @@ mod tests {
assert!(processor.vpn_key_cache.is_empty());
let forward_hop = make_valid_forward_sphinx_packet(Default::default(), local_keys.1);
let framed = FramedSphinxPacket::new(forward_hop, PacketMode::VPN);
let framed = FramedSphinxPacket::new(forward_hop, PacketMode::Vpn);
processor.perform_initial_unwrapping(framed).unwrap();
assert_eq!(processor.vpn_key_cache.len(), 1);
@@ -457,28 +457,28 @@ mod tests {
.split_hop_data_into_ack_and_message(short_data)
.is_err());
let sufficient_data = vec![42u8; SURBAck::len()];
let sufficient_data = vec![42u8; SurbAck::len()];
let (ack, data) = processor
.split_hop_data_into_ack_and_message(sufficient_data.clone())
.unwrap();
assert_eq!(sufficient_data, ack);
assert!(data.is_empty());
let long_data = vec![42u8; SURBAck::len() * 5];
let long_data = vec![42u8; SurbAck::len() * 5];
let (ack, data) = processor
.split_hop_data_into_ack_and_message(long_data)
.unwrap();
assert_eq!(ack.len(), SURBAck::len());
assert_eq!(data.len(), SURBAck::len() * 4)
assert_eq!(ack.len(), SurbAck::len());
assert_eq!(data.len(), SurbAck::len() * 4)
}
#[tokio::test]
async fn splitting_into_ack_and_message_returns_whole_data_for_ack() {
let processor = fixture();
let data = vec![42u8; SURBAck::len() + 10];
let data = vec![42u8; SurbAck::len() + 10];
let (ack, message) = processor
.split_into_ack_and_message(data.clone(), PacketSize::ACKPacket, Default::default())
.split_into_ack_and_message(data.clone(), PacketSize::AckPacket, Default::default())
.unwrap();
assert!(ack.is_none());
assert_eq!(data, message)
@@ -41,7 +41,7 @@ pub fn recover_identifier(
) -> Option<SerializedFragmentIdentifier> {
// The content of an 'ACK' packet consists of AckEncryptionAlgorithm::IV followed by
// serialized FragmentIdentifier
if iv_id_ciphertext.len() != PacketSize::ACKPacket.plaintext_size() {
if iv_id_ciphertext.len() != PacketSize::AckPacket.plaintext_size() {
return None;
}
@@ -28,21 +28,20 @@ use std::convert::TryFrom;
use std::time;
use topology::{NymTopology, NymTopologyError};
#[allow(non_snake_case)]
pub struct SURBAck {
pub struct SurbAck {
surb_ack_packet: SphinxPacket,
first_hop_address: NymNodeRoutingAddress,
expected_total_delay: Delay,
}
#[derive(Debug)]
pub enum SURBAckRecoveryError {
pub enum SurbAckRecoveryError {
InvalidPacketSize,
InvalidAddress,
InvalidSphinxPacket,
}
impl SURBAck {
impl SurbAck {
pub fn construct<R>(
rng: &mut R,
recipient: &Recipient,
@@ -63,7 +62,7 @@ impl SURBAck {
let surb_ack_payload = prepare_identifier(rng, ack_key, marshaled_fragment_id);
let mut surb_builder =
SphinxPacketBuilder::new().with_payload_size(PacketSize::ACKPacket.payload_size());
SphinxPacketBuilder::new().with_payload_size(PacketSize::AckPacket.payload_size());
if let Some(initial_secret) = initial_sphinx_secret {
surb_builder = surb_builder.with_initial_secret(initial_secret);
}
@@ -77,7 +76,7 @@ impl SURBAck {
let first_hop_address =
NymNodeRoutingAddress::try_from(route.first().unwrap().address).unwrap();
Ok(SURBAck {
Ok(SurbAck {
surb_ack_packet,
first_hop_address,
expected_total_delay,
@@ -87,7 +86,7 @@ impl SURBAck {
pub fn len() -> usize {
// TODO: this will be variable once/if we decide to introduce optimization described
// in common/nymsphinx/chunking/src/lib.rs:available_plaintext_size()
PacketSize::ACKPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN
PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN
}
pub fn prepare_for_sending(self) -> (Delay, Vec<u8>) {
@@ -104,13 +103,13 @@ impl SURBAck {
// partial reciprocal of `prepare_for_sending` performed by the gateway
pub fn try_recover_first_hop_packet(
b: &[u8],
) -> Result<(NymNodeRoutingAddress, SphinxPacket), SURBAckRecoveryError> {
) -> Result<(NymNodeRoutingAddress, SphinxPacket), SurbAckRecoveryError> {
if b.len() != Self::len() {
Err(SURBAckRecoveryError::InvalidPacketSize)
Err(SurbAckRecoveryError::InvalidPacketSize)
} else {
let address = match NymNodeRoutingAddress::try_from_bytes(&b) {
Ok(address) => address,
Err(_) => return Err(SURBAckRecoveryError::InvalidAddress),
Err(_) => return Err(SurbAckRecoveryError::InvalidAddress),
};
// TODO: this will be variable once/if we decide to introduce optimization described
@@ -118,7 +117,7 @@ impl SURBAck {
let address_offset = MAX_NODE_ADDRESS_UNPADDED_LEN;
let packet = match SphinxPacket::from_bytes(&b[address_offset..]) {
Ok(packet) => packet,
Err(_) => return Err(SURBAckRecoveryError::InvalidSphinxPacket),
Err(_) => return Err(SurbAckRecoveryError::InvalidSphinxPacket),
};
Ok((address, packet))
+2 -2
View File
@@ -34,7 +34,7 @@ pub const MAX_NODE_ADDRESS_UNPADDED_LEN: usize = 19;
#[derive(Debug)]
pub enum NymNodeRoutingAddressError {
InsufficientNumberOfBytesAvailableError,
InvalidIPVersion,
InvalidIpVersion,
}
/// Current representation of Node routing information used in Nym system.
@@ -114,7 +114,7 @@ impl NymNodeRoutingAddress {
address_octets.copy_from_slice(&b[3..19]);
IpAddr::V6(Ipv6Addr::from(address_octets))
}
_ => return Err(NymNodeRoutingAddressError::InvalidIPVersion),
_ => return Err(NymNodeRoutingAddressError::InvalidIpVersion),
};
Ok(Self(SocketAddr::new(ip, port)))
@@ -19,52 +19,52 @@ use crypto::{
symmetric::stream_cipher::{generate_key, Key, NewStreamCipher},
Digest,
};
use nymsphinx_params::{ReplySURBEncryptionAlgorithm, ReplySURBKeyDigestAlgorithm};
use nymsphinx_params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm};
use rand::{CryptoRng, RngCore};
use std::fmt::{self, Display, Formatter};
pub type EncryptionKeyDigest =
GenericArray<u8, <ReplySURBKeyDigestAlgorithm as Digest>::OutputSize>;
GenericArray<u8, <ReplySurbKeyDigestAlgorithm as Digest>::OutputSize>;
pub type SURBEncryptionKeySize = <ReplySURBEncryptionAlgorithm as NewStreamCipher>::KeySize;
pub type SurbEncryptionKeySize = <ReplySurbEncryptionAlgorithm as NewStreamCipher>::KeySize;
#[derive(Clone, Debug)]
pub struct SURBEncryptionKey(Key<ReplySURBEncryptionAlgorithm>);
pub struct SurbEncryptionKey(Key<ReplySurbEncryptionAlgorithm>);
#[derive(Debug)]
pub enum SURBEncryptionKeyError {
pub enum SurbEncryptionKeyError {
BytesOfInvalidLengthError,
}
impl Display for SURBEncryptionKeyError {
impl Display for SurbEncryptionKeyError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SURBEncryptionKeyError::BytesOfInvalidLengthError => {
SurbEncryptionKeyError::BytesOfInvalidLengthError => {
write!(f, "provided bytes have invalid length")
}
}
}
}
impl std::error::Error for SURBEncryptionKeyError {}
impl std::error::Error for SurbEncryptionKeyError {}
impl SURBEncryptionKey {
impl SurbEncryptionKey {
/// Generates fresh pseudorandom key that is going to be used by the recipient of the message
/// to encrypt payload of the reply. It is only generated when reply-SURB is attached.
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
SURBEncryptionKey(generate_key::<ReplySURBEncryptionAlgorithm, _>(rng))
SurbEncryptionKey(generate_key::<ReplySurbEncryptionAlgorithm, _>(rng))
}
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SURBEncryptionKeyError> {
if bytes.len() != SURBEncryptionKeySize::to_usize() {
return Err(SURBEncryptionKeyError::BytesOfInvalidLengthError);
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SurbEncryptionKeyError> {
if bytes.len() != SurbEncryptionKeySize::to_usize() {
return Err(SurbEncryptionKeyError::BytesOfInvalidLengthError);
}
Ok(SURBEncryptionKey(GenericArray::clone_from_slice(bytes)))
Ok(SurbEncryptionKey(GenericArray::clone_from_slice(bytes)))
}
pub fn compute_digest(&self) -> EncryptionKeyDigest {
crypto_hash::compute_digest::<ReplySURBKeyDigestAlgorithm>(&self.0)
crypto_hash::compute_digest::<ReplySurbKeyDigestAlgorithm>(&self.0)
}
pub fn to_bytes(&self) -> Vec<u8> {
@@ -75,7 +75,7 @@ impl SURBEncryptionKey {
self.0.as_ref()
}
pub fn inner(&self) -> &Key<ReplySURBEncryptionAlgorithm> {
pub fn inner(&self) -> &Key<ReplySurbEncryptionAlgorithm> {
&self.0
}
}
@@ -15,5 +15,5 @@
pub mod encryption_key;
pub mod reply_surb;
pub use encryption_key::{SURBEncryptionKey, SURBEncryptionKeySize};
pub use reply_surb::{ReplySURB, ReplySURBError};
pub use encryption_key::{SurbEncryptionKey, SurbEncryptionKeySize};
pub use reply_surb::{ReplySurb, ReplySurbError};
@@ -13,13 +13,13 @@
// limitations under the License.
use crate::encryption_key::{
SURBEncryptionKey, SURBEncryptionKeyError, SURBEncryptionKeySize, Unsigned,
SurbEncryptionKey, SurbEncryptionKeyError, SurbEncryptionKeySize, Unsigned,
};
use crypto::Digest;
use nymsphinx_addressing::clients::Recipient;
use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
use nymsphinx_params::packet_sizes::PacketSize;
use nymsphinx_params::{ReplySURBKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
use nymsphinx_params::{ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
use nymsphinx_types::{delays, Error as SphinxError, SURBMaterial, SphinxPacket, SURB};
use rand::{CryptoRng, RngCore};
use serde::de::{Error as SerdeError, Visitor};
@@ -30,26 +30,26 @@ use std::time;
use topology::{NymTopology, NymTopologyError};
#[derive(Debug)]
pub enum ReplySURBError {
pub enum ReplySurbError {
UnpaddedMessageError,
MalformedStringError(bs58::decode::Error),
RecoveryError(SphinxError),
InvalidEncryptionKeyData(SURBEncryptionKeyError),
InvalidEncryptionKeyData(SurbEncryptionKeyError),
}
impl fmt::Display for ReplySURBError {
impl fmt::Display for ReplySurbError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
match self {
ReplySURBError::UnpaddedMessageError => {
ReplySurbError::UnpaddedMessageError => {
write!(f, "tried to use reply SURB with an unpadded message")
}
ReplySURBError::MalformedStringError(decode_err) => {
ReplySurbError::MalformedStringError(decode_err) => {
write!(f, "reply SURB is incorrectly formatted: {}", decode_err)
}
ReplySURBError::RecoveryError(sphinx_err) => {
ReplySurbError::RecoveryError(sphinx_err) => {
write!(f, "failed to recover reply SURB from bytes: {}", sphinx_err)
}
ReplySURBError::InvalidEncryptionKeyData(surb_key_err) => write!(
ReplySurbError::InvalidEncryptionKeyData(surb_key_err) => write!(
f,
"failed to recover reply SURB encryption key from bytes: {}",
surb_key_err
@@ -59,23 +59,23 @@ impl fmt::Display for ReplySURBError {
}
// since we have Debug and Display might as well slap Error on top of it too
impl std::error::Error for ReplySURBError {}
impl std::error::Error for ReplySurbError {}
impl From<SURBEncryptionKeyError> for ReplySURBError {
fn from(err: SURBEncryptionKeyError) -> Self {
ReplySURBError::InvalidEncryptionKeyData(err)
impl From<SurbEncryptionKeyError> for ReplySurbError {
fn from(err: SurbEncryptionKeyError) -> Self {
ReplySurbError::InvalidEncryptionKeyData(err)
}
}
#[derive(Debug)]
pub struct ReplySURB {
pub struct ReplySurb {
surb: SURB,
encryption_key: SURBEncryptionKey,
encryption_key: SurbEncryptionKey,
}
// Serialize + Deserialize is not really used anymore (it was for a CBOR experiment)
// however, if we decided we needed it again, it's already here
impl Serialize for ReplySURB {
impl Serialize for ReplySurb {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
@@ -84,15 +84,15 @@ impl Serialize for ReplySURB {
}
}
impl<'de> Deserialize<'de> for ReplySURB {
impl<'de> Deserialize<'de> for ReplySurb {
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
struct ReplySURBVisitor;
struct ReplySurbVisitor;
impl<'de> Visitor<'de> for ReplySURBVisitor {
type Value = ReplySURB;
impl<'de> Visitor<'de> for ReplySurbVisitor {
type Value = ReplySurb;
fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(formatter, "A replySURB must contain a valid symmetric encryption key and a correctly formed sphinx header")
@@ -102,20 +102,20 @@ impl<'de> Deserialize<'de> for ReplySURB {
where
E: SerdeError,
{
ReplySURB::from_bytes(bytes)
ReplySurb::from_bytes(bytes)
.map_err(|_| SerdeError::invalid_length(bytes.len(), &self))
}
}
deserializer.deserialize_bytes(ReplySURBVisitor)
deserializer.deserialize_bytes(ReplySurbVisitor)
}
}
impl ReplySURB {
impl ReplySurb {
pub fn max_msg_len(packet_size: PacketSize) -> usize {
// For detailed explanation (of ack overhead) refer to common\nymsphinx\src\preparer.rs::available_plaintext_per_packet()
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::ACKPacket.size();
packet_size.plaintext_size() - ack_overhead - ReplySURBKeyDigestAlgorithm::output_size() - 1
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::AckPacket.size();
packet_size.plaintext_size() - ack_overhead - ReplySurbKeyDigestAlgorithm::output_size() - 1
}
// TODO: should this return `ReplySURBError` for consistency sake
@@ -137,9 +137,9 @@ impl ReplySURB {
let surb_material = SURBMaterial::new(route, delays, destination);
// this can't fail as we know we have a valid route to gateway and have correct number of delays
Ok(ReplySURB {
Ok(ReplySurb {
surb: surb_material.construct_SURB().unwrap(),
encryption_key: SURBEncryptionKey::new(rng),
encryption_key: SurbEncryptionKey::new(rng),
})
}
@@ -150,13 +150,13 @@ impl ReplySURB {
// the SURB itself consists of SURB_header, first hop address and set of payload keys
// (note extra 1 for the gateway)
SURBEncryptionKeySize::to_usize()
SurbEncryptionKeySize::to_usize()
+ HEADER_SIZE
+ NODE_ADDRESS_LENGTH
+ (1 + mix_hops as usize) * PAYLOAD_KEY_SIZE
}
pub fn encryption_key(&self) -> &SURBEncryptionKey {
pub fn encryption_key(&self) -> &SurbEncryptionKey {
&self.encryption_key
}
@@ -169,16 +169,16 @@ impl ReplySURB {
.collect()
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ReplySURBError> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ReplySurbError> {
let encryption_key =
SURBEncryptionKey::try_from_bytes(&bytes[..SURBEncryptionKeySize::to_usize()])?;
SurbEncryptionKey::try_from_bytes(&bytes[..SurbEncryptionKeySize::to_usize()])?;
let surb = match SURB::from_bytes(&bytes[SURBEncryptionKeySize::to_usize()..]) {
Err(err) => return Err(ReplySURBError::RecoveryError(err)),
let surb = match SURB::from_bytes(&bytes[SurbEncryptionKeySize::to_usize()..]) {
Err(err) => return Err(ReplySurbError::RecoveryError(err)),
Ok(surb) => surb,
};
Ok(ReplySURB {
Ok(ReplySurb {
surb,
encryption_key,
})
@@ -188,10 +188,10 @@ impl ReplySURB {
bs58::encode(&self.to_bytes()).into_string()
}
pub fn from_base58_string<S: Into<String>>(val: S) -> Result<Self, ReplySURBError> {
pub fn from_base58_string<S: Into<String>>(val: S) -> Result<Self, ReplySurbError> {
let bytes = match bs58::decode(val.into()).into_vec() {
Ok(decoded) => decoded,
Err(err) => return Err(ReplySURBError::MalformedStringError(err)),
Err(err) => return Err(ReplySurbError::MalformedStringError(err)),
};
Self::from_bytes(&bytes)
}
@@ -206,11 +206,11 @@ impl ReplySURB {
self,
message: &[u8],
packet_size: Option<PacketSize>,
) -> Result<(SphinxPacket, NymNodeRoutingAddress), ReplySURBError> {
) -> Result<(SphinxPacket, NymNodeRoutingAddress), ReplySurbError> {
let packet_size = packet_size.unwrap_or_else(Default::default);
if message.len() != packet_size.plaintext_size() {
return Err(ReplySURBError::UnpaddedMessageError);
return Err(ReplySurbError::UnpaddedMessageError);
}
// this can realistically only fail on too long messages and we just checked for that
+1 -1
View File
@@ -453,7 +453,7 @@ mod fragment_tests {
use rand::{thread_rng, RngCore};
fn max_plaintext_size() -> usize {
PacketSize::default().plaintext_size() - PacketSize::ACKPacket.size()
PacketSize::default().plaintext_size() - PacketSize::AckPacket.size()
}
#[test]
+1 -1
View File
@@ -147,7 +147,7 @@ mod tests {
// plaintext len should not affect this at all, but let's test it with something tiny
// and reasonable
let used_plaintext_len = PacketSize::default().plaintext_size()
- PacketSize::ACKPacket.size()
- PacketSize::AckPacket.size()
- MAX_NODE_ADDRESS_UNPADDED_LEN;
let plaintext_lens = vec![17, used_plaintext_len, 20, 42, 10000];
+1 -1
View File
@@ -311,7 +311,7 @@ mod tests {
use nymsphinx_params::packet_sizes::PacketSize;
fn max_plaintext_size() -> usize {
PacketSize::default().plaintext_size() - PacketSize::ACKPacket.size()
PacketSize::default().plaintext_size() - PacketSize::AckPacket.size()
}
fn verify_unlinked_set_payload(mut set: FragmentSet, payload: &[u8]) {
+3 -3
View File
@@ -14,7 +14,7 @@
use crypto::shared_key::new_ephemeral_shared_key;
use crypto::symmetric::stream_cipher;
use nymsphinx_acknowledgements::surb_ack::SURBAck;
use nymsphinx_acknowledgements::surb_ack::SurbAck;
use nymsphinx_acknowledgements::AckKey;
use nymsphinx_addressing::clients::Recipient;
use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
@@ -66,11 +66,11 @@ pub fn generate_loop_cover_surb_ack<R>(
ack_key: &AckKey,
full_address: &Recipient,
average_ack_delay: time::Duration,
) -> Result<SURBAck, CoverMessageError>
) -> Result<SurbAck, CoverMessageError>
where
R: RngCore + CryptoRng,
{
Ok(SURBAck::construct(
Ok(SurbAck::construct(
rng,
full_address,
ack_key,
+1 -1
View File
@@ -37,7 +37,7 @@ impl Display for MixPacketFormattingError {
write!(
f,
"received request had invalid size. (actual: {}, but expected one of: {} (ACK), {} (REGULAR), {} (EXTENDED))",
actual, PacketSize::ACKPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
actual, PacketSize::AckPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
),
MalformedSphinxPacket => write!(f, "received sphinx packet was malformed"),
InvalidPacketMode => write!(f, "provided packet mode is invalid")
+6 -6
View File
@@ -86,7 +86,7 @@ impl Decoder for SphinxCodec {
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::SIZE + PacketSize::ACKPacket.size());
src.reserve(Header::SIZE + PacketSize::AckPacket.size());
return Ok(None);
}
@@ -139,7 +139,7 @@ impl Decoder for SphinxCodec {
let next_frame_len = next_packet_len.size() + Header::SIZE;
src.reserve(next_frame_len - 1);
} else {
src.reserve(Header::SIZE + PacketSize::ACKPacket.size());
src.reserve(Header::SIZE + PacketSize::AckPacket.size());
}
Ok(Some(nymsphinx_packet))
@@ -218,7 +218,7 @@ mod packet_encoding {
assert!(SphinxCodec.decode(&mut empty_bytes).unwrap().is_none());
assert_eq!(
empty_bytes.capacity(),
Header::SIZE + PacketSize::ACKPacket.size()
Header::SIZE + PacketSize::AckPacket.size()
);
}
@@ -226,7 +226,7 @@ mod packet_encoding {
fn for_bytes_with_header() {
// if header gets decoded there should be enough bytes for the entire frame
let packet_sizes = vec![
PacketSize::ACKPacket,
PacketSize::AckPacket,
PacketSize::RegularPacket,
PacketSize::ExtendedPacket,
];
@@ -256,7 +256,7 @@ mod packet_encoding {
assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some());
assert_eq!(
bytes.capacity(),
Header::SIZE + PacketSize::ACKPacket.size()
Header::SIZE + PacketSize::AckPacket.size()
);
}
@@ -264,7 +264,7 @@ mod packet_encoding {
fn for_full_frame_with_extra_byte() {
// if there was at least 1 byte left, there should be enough space for entire next frame
let packet_sizes = vec![
PacketSize::ACKPacket,
PacketSize::AckPacket,
PacketSize::RegularPacket,
PacketSize::ExtendedPacket,
];
+1 -1
View File
@@ -147,7 +147,7 @@ mod header_encoding {
#[test]
fn header_encoding_reserves_enough_bytes_for_full_sphinx_packet() {
let packet_sizes = vec![
PacketSize::ACKPacket,
PacketSize::AckPacket,
PacketSize::RegularPacket,
PacketSize::ExtendedPacket,
];
+2 -2
View File
@@ -40,7 +40,7 @@ pub type PacketHkdfAlgorithm = blake3::Hasher;
pub type GatewaySharedKeyHkdfAlgorithm = blake3::Hasher;
/// Hashing algorithm used when computing digest of a reply SURB encryption key.
pub type ReplySURBKeyDigestAlgorithm = blake3::Hasher;
pub type ReplySurbKeyDigestAlgorithm = blake3::Hasher;
/// Hashing algorithm used when computing integrity (H)Mac for message exchanged between client and gateway.
// TODO: if updated, the pem type defined in gateway\gateway-requests\src\registration\handshake\shared_key
@@ -67,4 +67,4 @@ pub type PacketEncryptionAlgorithm = Aes128Ctr;
/// Encryption algorithm used for end-to-end encryption of reply messages constructed using ReplySURBs.
// TODO: I don't see any reason for it to be different than what is used for regular packets. Perhaps
// it could be potentially insecure to use anything else?
pub type ReplySURBEncryptionAlgorithm = PacketEncryptionAlgorithm;
pub type ReplySurbEncryptionAlgorithm = PacketEncryptionAlgorithm;
+3 -3
View File
@@ -26,7 +26,7 @@ pub enum PacketMode {
/// Represents a VPN packet that should not be delayed and ideally cached pre-computed keys
/// should be used for unwrapping data. Note that it does not offer the same level of anonymity.
VPN = 1,
Vpn = 1,
}
impl PacketMode {
@@ -35,7 +35,7 @@ impl PacketMode {
}
pub fn is_vpn(self) -> bool {
self == PacketMode::VPN
self == PacketMode::Vpn
}
}
@@ -45,7 +45,7 @@ impl TryFrom<u8> for PacketMode {
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
match value {
_ if value == (PacketMode::Mix as u8) => Ok(Self::Mix),
_ if value == (PacketMode::VPN as u8) => Ok(Self::VPN),
_ if value == (PacketMode::Vpn as u8) => Ok(Self::Vpn),
_ => Err(InvalidPacketMode),
}
}
+5 -5
View File
@@ -38,7 +38,7 @@ pub enum PacketSize {
RegularPacket = 1,
// for sending SURB-ACKs
ACKPacket = 2,
AckPacket = 2,
// for example for streaming fast and furious in uncompressed 10bit 4K HDR quality
ExtendedPacket = 3,
@@ -50,7 +50,7 @@ impl TryFrom<u8> for PacketSize {
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
match value {
_ if value == (PacketSize::RegularPacket as u8) => Ok(Self::RegularPacket),
_ if value == (PacketSize::ACKPacket as u8) => Ok(Self::ACKPacket),
_ if value == (PacketSize::AckPacket as u8) => Ok(Self::AckPacket),
_ if value == (PacketSize::ExtendedPacket as u8) => Ok(Self::ExtendedPacket),
_ => Err(InvalidPacketSize),
}
@@ -61,7 +61,7 @@ impl PacketSize {
pub fn size(self) -> usize {
match self {
PacketSize::RegularPacket => REGULAR_PACKET_SIZE,
PacketSize::ACKPacket => ACK_PACKET_SIZE,
PacketSize::AckPacket => ACK_PACKET_SIZE,
PacketSize::ExtendedPacket => EXTENDED_PACKET_SIZE,
}
}
@@ -77,8 +77,8 @@ impl PacketSize {
pub fn get_type(size: usize) -> std::result::Result<Self, InvalidPacketSize> {
if PacketSize::RegularPacket.size() == size {
Ok(PacketSize::RegularPacket)
} else if PacketSize::ACKPacket.size() == size {
Ok(PacketSize::ACKPacket)
} else if PacketSize::AckPacket.size() == size {
Ok(PacketSize::AckPacket)
} else if PacketSize::ExtendedPacket.size() == size {
Ok(PacketSize::ExtendedPacket)
} else {
+21 -21
View File
@@ -12,24 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use self::vpn_manager::VPNManager;
use self::vpn_manager::VpnManager;
use crate::chunking;
use crypto::asymmetric::encryption;
use crypto::shared_key::new_ephemeral_shared_key;
use crypto::symmetric::stream_cipher;
use crypto::Digest;
use nymsphinx_acknowledgements::surb_ack::SURBAck;
use nymsphinx_acknowledgements::surb_ack::SurbAck;
use nymsphinx_acknowledgements::AckKey;
use nymsphinx_addressing::clients::Recipient;
use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
use nymsphinx_anonymous_replies::encryption_key::SURBEncryptionKey;
use nymsphinx_anonymous_replies::reply_surb::ReplySURB;
use nymsphinx_anonymous_replies::encryption_key::SurbEncryptionKey;
use nymsphinx_anonymous_replies::reply_surb::ReplySurb;
use nymsphinx_chunking::fragment::{Fragment, FragmentIdentifier};
use nymsphinx_forwarding::packet::MixPacket;
use nymsphinx_params::packet_sizes::PacketSize;
use nymsphinx_params::{
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketMode, ReplySURBEncryptionAlgorithm,
ReplySURBKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS,
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketMode, ReplySurbEncryptionAlgorithm,
ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS,
};
use nymsphinx_types::builder::SphinxPacketBuilder;
use nymsphinx_types::{delays, Delay};
@@ -95,7 +95,7 @@ pub struct MessagePreparer<R: CryptoRng + Rng> {
/// If the VPN mode is activated, this underlying secret will be used for multiple sphinx
/// packets created.
vpn_manager: Option<VPNManager>,
vpn_manager: Option<VpnManager>,
}
impl<R> MessagePreparer<R>
@@ -111,7 +111,7 @@ where
vpn_key_reuse_limit: Option<usize>,
) -> Self {
let vpn_manager = if mode.is_vpn() {
Some(VPNManager::new(
Some(VpnManager::new(
&mut rng,
vpn_key_reuse_limit.expect("No key reuse limit provided in vpn mode!"),
))
@@ -159,7 +159,7 @@ where
// and only then perform the chunking with `available_plaintext_size` being called per chunk.
// However this will probably introduce bunch of complexity
// for relatively not a lot of gain, so it shouldn't be done just yet.
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::ACKPacket.size();
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::AckPacket.size();
let ephemeral_public_key_overhead = encryption::PUBLIC_KEY_SIZE;
self.packet_size.plaintext_size() - ack_overhead - ephemeral_public_key_overhead
@@ -192,9 +192,9 @@ where
message: Vec<u8>,
should_attach: bool,
topology: &NymTopology,
) -> Result<(Vec<u8>, Option<SURBEncryptionKey>), PreparationError> {
) -> Result<(Vec<u8>, Option<SurbEncryptionKey>), PreparationError> {
if should_attach {
let reply_surb = ReplySURB::construct(
let reply_surb = ReplySurb::construct(
&mut self.rng,
&self.sender_address,
self.average_packet_delay,
@@ -343,10 +343,10 @@ where
fragment_id: FragmentIdentifier,
topology: &NymTopology,
ack_key: &AckKey,
) -> Result<SURBAck, NymTopologyError> {
) -> Result<SurbAck, NymTopologyError> {
if let Some(vpn_manager) = self.vpn_manager.as_mut() {
let initial_secret = vpn_manager.use_secret(&mut self.rng).await;
SURBAck::construct(
SurbAck::construct(
&mut self.rng,
&self.sender_address,
ack_key,
@@ -356,7 +356,7 @@ where
Some(&initial_secret),
)
} else {
SURBAck::construct(
SurbAck::construct(
&mut self.rng,
&self.sender_address,
ack_key,
@@ -376,7 +376,7 @@ where
message: Vec<u8>,
with_reply_surb: bool,
topology: &NymTopology,
) -> Result<(Vec<Fragment>, Option<SURBEncryptionKey>), PreparationError> {
) -> Result<(Vec<Fragment>, Option<SurbEncryptionKey>), PreparationError> {
let (message, reply_key) =
self.optionally_attach_reply_surb(message, with_reply_surb, topology)?;
@@ -389,7 +389,7 @@ where
pub async fn prepare_reply_for_use(
&mut self,
message: Vec<u8>,
reply_surb: ReplySURB,
reply_surb: ReplySurb,
topology: &NymTopology,
ack_key: &AckKey,
) -> Result<(MixPacket, FragmentIdentifier), PreparationError> {
@@ -398,11 +398,11 @@ where
// and need 1 byte to indicate padding length (this is not the case for 'normal' messages
// as there the padding is added for the whole message)
// so before doing any processing, let's see if we have enough space for it all
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::ACKPacket.size();
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::AckPacket.size();
if message.len()
> self.packet_size.plaintext_size()
- ack_overhead
- ReplySURBKeyDigestAlgorithm::output_size()
- ReplySurbKeyDigestAlgorithm::output_size()
- 1
{
return Err(PreparationError::TooLongReplyMessageError);
@@ -422,7 +422,7 @@ where
let zero_pad_len = self.packet_size.plaintext_size()
- message.len()
- ack_overhead
- ReplySURBKeyDigestAlgorithm::output_size()
- ReplySurbKeyDigestAlgorithm::output_size()
- 1;
// create reply message that will reach the recipient:
@@ -433,8 +433,8 @@ where
.collect();
// encrypt the reply message
let zero_iv = stream_cipher::zero_iv::<ReplySURBEncryptionAlgorithm>();
stream_cipher::encrypt_in_place::<ReplySURBEncryptionAlgorithm>(
let zero_iv = stream_cipher::zero_iv::<ReplySurbEncryptionAlgorithm>();
stream_cipher::encrypt_in_place::<ReplySurbEncryptionAlgorithm>(
reply_surb.encryption_key().inner(),
&zero_iv,
&mut reply_content,
+4 -4
View File
@@ -27,7 +27,7 @@ pub(super) type SpinhxKeyRef<'a> = RwLockReadGuard<'a, EphemeralSecret>;
pub(super) type SpinhxKeyRef<'a> = &'a EphemeralSecret;
#[cfg_attr(not(target_arch = "wasm32"), derive(Clone))]
pub(super) struct VPNManager {
pub(super) struct VpnManager {
#[cfg(not(target_arch = "wasm32"))]
inner: Arc<Inner>,
@@ -55,14 +55,14 @@ struct Inner {
packets_with_current_secret: AtomicUsize,
}
impl VPNManager {
impl VpnManager {
#[cfg(not(target_arch = "wasm32"))]
pub(super) fn new<R>(mut rng: R, secret_reuse_limit: usize) -> Self
where
R: CryptoRng + Rng,
{
let initial_secret = EphemeralSecret::new_with_rng(&mut rng);
VPNManager {
VpnManager {
inner: Arc::new(Inner {
secret_reuse_limit,
current_initial_secret: RwLock::new(initial_secret),
@@ -77,7 +77,7 @@ impl VPNManager {
R: CryptoRng + Rng,
{
let initial_secret = EphemeralSecret::new_with_rng(&mut rng);
VPNManager {
VpnManager {
inner: Inner {
secret_reuse_limit,
current_initial_secret: initial_secret,
+10 -10
View File
@@ -15,7 +15,7 @@
use crypto::asymmetric::encryption;
use crypto::shared_key::recompute_shared_key;
use crypto::symmetric::stream_cipher;
use nymsphinx_anonymous_replies::reply_surb::{ReplySURB, ReplySURBError};
use nymsphinx_anonymous_replies::reply_surb::{ReplySurb, ReplySurbError};
use nymsphinx_chunking::fragment::Fragment;
use nymsphinx_chunking::reconstruction::MessageReconstructor;
use nymsphinx_params::{PacketEncryptionAlgorithm, PacketHkdfAlgorithm, DEFAULT_NUM_MIX_HOPS};
@@ -27,13 +27,13 @@ pub struct ReconstructedMessage {
pub message: Vec<u8>,
/// Optional ReplySURB to allow for an anonymous reply to the sender.
pub reply_surb: Option<ReplySURB>,
pub reply_surb: Option<ReplySurb>,
}
#[derive(Debug)]
pub enum MessageRecoveryError {
InvalidSurbPrefixError,
MalformedSURBError(ReplySURBError),
MalformedSurbError(ReplySurbError),
InvalidRemoteEphemeralKey(encryption::KeyRecoveryError),
MalformedFragmentError,
InvalidMessagePaddingError,
@@ -41,9 +41,9 @@ pub enum MessageRecoveryError {
TooShortMessageError,
}
impl From<ReplySURBError> for MessageRecoveryError {
fn from(err: ReplySURBError) -> Self {
MessageRecoveryError::MalformedSURBError(err)
impl From<ReplySurbError> for MessageRecoveryError {
fn from(err: ReplySurbError) -> Self {
MessageRecoveryError::MalformedSurbError(err)
}
}
@@ -78,17 +78,17 @@ impl MessageReceiver {
fn recover_reply_surb_from_message(
&self,
message: &mut Vec<u8>,
) -> Result<Option<ReplySURB>, MessageRecoveryError> {
) -> Result<Option<ReplySurb>, MessageRecoveryError> {
match message[0] {
n if n == false as u8 => {
message.remove(0);
Ok(None)
}
n if n == true as u8 => {
let surb_len: usize = ReplySURB::serialized_len(self.num_mix_hops);
let surb_len: usize = ReplySurb::serialized_len(self.num_mix_hops);
// note the extra +1 (due to 0/1 message prefix)
let surb_bytes = &message[1..1 + surb_len];
let reply_surb = ReplySURB::from_bytes(surb_bytes)?;
let reply_surb = ReplySurb::from_bytes(surb_bytes)?;
*message = message.drain(1 + surb_len..).collect();
Ok(Some(reply_surb))
@@ -304,7 +304,7 @@ mod message_receiver {
let topology = topology_fixture();
let reply_surb =
ReplySURB::construct(&mut OsRng, &dummy_recipient, average_delay, &topology).unwrap();
ReplySurb::construct(&mut OsRng, &dummy_recipient, average_delay, &topology).unwrap();
let reply_surb_bytes = reply_surb.to_bytes();
@@ -1,6 +1,9 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![allow(renamed_and_removed_lints)]
#![allow(unknown_lints)] // beta-nightly
#![allow(clippy::unknown_clippy_lints)] // `clippy::upper_case_acronyms` does not exist on stable just yet
use crypto::generic_array::{typenum::Unsigned, GenericArray};
use crypto::symmetric::stream_cipher::{random_iv, NewStreamCipher, IV};
use nymsphinx::params::GatewayEncryptionAlgorithm;
@@ -8,9 +11,13 @@ use rand::{CryptoRng, RngCore};
type NonceSize = <GatewayEncryptionAlgorithm as NewStreamCipher>::NonceSize;
// I think 'IV' looks better than 'Iv', feel free to change that.
#[allow(clippy::upper_case_acronyms)]
pub struct AuthenticationIV(IV<GatewayEncryptionAlgorithm>);
#[derive(Debug)]
// I think 'IV' looks better than 'Iv', feel free to change that.
#[allow(clippy::upper_case_acronyms)]
pub enum IVConversionError {
DecodeError(bs58::decode::Error),
BytesOfInvalidLengthError,
+5 -5
View File
@@ -58,7 +58,7 @@ impl TryInto<String> for RegistrationHandshake {
#[derive(Debug)]
pub enum GatewayRequestsError {
TooShortRequest,
InvalidMAC,
InvalidMac,
IncorrectlyEncodedAddress,
RequestOfInvalidSize(usize),
MalformedSphinxPacket,
@@ -72,13 +72,13 @@ impl fmt::Display for GatewayRequestsError {
use GatewayRequestsError::*;
match self {
TooShortRequest => write!(f, "the request is too short"),
InvalidMAC => write!(f, "provided MAC is invalid"),
InvalidMac => write!(f, "provided MAC is invalid"),
IncorrectlyEncodedAddress => write!(f, "address field was incorrectly encoded"),
RequestOfInvalidSize(actual) =>
write!(
f,
"received request had invalid size. (actual: {}, but expected one of: {} (ACK), {} (REGULAR), {} (EXTENDED))",
actual, PacketSize::ACKPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
actual, PacketSize::AckPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
),
MalformedSphinxPacket => write!(f, "received sphinx packet was malformed"),
MalformedEncryption => write!(f, "the received encrypted data was malformed"),
@@ -226,7 +226,7 @@ impl BinaryRequest {
message_bytes,
mac_tag,
) {
return Err(GatewayRequestsError::InvalidMAC);
return Err(GatewayRequestsError::InvalidMac);
}
// couldn't have made the first borrow mutable as you can't have an immutable borrow
@@ -291,7 +291,7 @@ impl BinaryResponse {
message_bytes,
mac_tag,
) {
return Err(GatewayRequestsError::InvalidMAC);
return Err(GatewayRequestsError::InvalidMac);
}
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
@@ -37,7 +37,7 @@ use tokio_tungstenite::{
//// but as byproduct this might (or might not) break the clean "SocketStream" enum here
enum SocketStream<S> {
RawTCP(S),
RawTcp(S),
UpgradedWebSocket(WebSocketStream<S>),
Invalid,
}
@@ -78,7 +78,7 @@ where
shared_key: None,
clients_handler_sender,
outbound_mix_sender,
socket_connection: SocketStream::RawTCP(conn),
socket_connection: SocketStream::RawTcp(conn),
local_identity,
}
}
@@ -89,7 +89,7 @@ where
{
self.socket_connection =
match std::mem::replace(&mut self.socket_connection, SocketStream::Invalid) {
SocketStream::RawTCP(conn) => {
SocketStream::RawTcp(conn) => {
// TODO: perhaps in the future, rather than panic here (and uncleanly shut tcp stream)
// return a result with an error?
let ws_stream = match tokio_tungstenite::accept_async(conn).await {
+1 -1
View File
@@ -35,7 +35,7 @@ impl Gateway {
identity: identity::KeyPair,
) -> Self {
let registered_clients_ledger = match ClientLedger::load(config.get_clients_ledger_path()) {
Err(e) => panic!(format!("Failed to load the ledger - {:?}", e)),
Err(e) => panic!("Failed to load the ledger - {:?}", e),
Ok(ledger) => ledger,
};
let client_inbox_storage = inboxes::ClientStorage::new(