From a06ae48e2f2c7a1f4d910176534e36e91a67c8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 20 May 2024 10:22:28 +0200 Subject: [PATCH] Add methods to MixnetClient to sign messages (#4602) --- .../client-core/src/client/base_client/mod.rs | 5 ++++- sdk/rust/nym-sdk/src/mixnet/client.rs | 2 ++ sdk/rust/nym-sdk/src/mixnet/native_client.rs | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/common/client-core/src/client/base_client/mod.rs b/common/client-core/src/client/base_client/mod.rs index 42adcf2da4..ec8026d076 100644 --- a/common/client-core/src/client/base_client/mod.rs +++ b/common/client-core/src/client/base_client/mod.rs @@ -39,7 +39,7 @@ use log::{debug, error, info, warn}; use nym_bandwidth_controller::BandwidthController; use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore}; use nym_credential_storage::storage::Storage as CredentialStorage; -use nym_crypto::asymmetric::encryption; +use nym_crypto::asymmetric::{encryption, identity}; use nym_gateway_client::{ AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter, }; @@ -670,6 +670,7 @@ where let self_address = Self::mix_address(&init_res); let ack_key = init_res.client_keys.ack_key(); let encryption_keys = init_res.client_keys.encryption_keypair(); + let identity_keys = init_res.client_keys.identity_keypair(); // the components are started in very specific order. Unless you know what you are doing, // do not change that. @@ -792,6 +793,7 @@ where Ok(BaseClient { address: self_address, + identity_keys, client_input: ClientInputStatus::AwaitingProducer { client_input: ClientInput { connection_command_sender: client_connection_tx, @@ -816,6 +818,7 @@ where pub struct BaseClient { pub address: Recipient, + pub identity_keys: Arc, pub client_input: ClientInputStatus, pub client_output: ClientOutputStatus, pub client_state: ClientState, diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index cfcc6b3f45..f6239d62ff 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -742,10 +742,12 @@ where let mut client_output = started_client.client_output.register_consumer(); let client_state = started_client.client_state; + let identity_keys = started_client.identity_keys.clone(); let reconstructed_receiver = client_output.register_receiver()?; Ok(MixnetClient::new( nym_address, + identity_keys, client_input, client_output, client_state, diff --git a/sdk/rust/nym-sdk/src/mixnet/native_client.rs b/sdk/rust/nym-sdk/src/mixnet/native_client.rs index c4e4c13739..ad514d6513 100644 --- a/sdk/rust/nym-sdk/src/mixnet/native_client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/native_client.rs @@ -10,6 +10,7 @@ use nym_client_core::client::{ inbound_messages::InputMessage, received_buffer::ReconstructedMessagesReceiver, }; +use nym_crypto::asymmetric::identity; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::{params::PacketType, receiver::ReconstructedMessage}; use nym_task::{ @@ -18,6 +19,7 @@ use nym_task::{ }; use nym_topology::NymTopology; use std::pin::Pin; +use std::sync::Arc; use std::task::{Context, Poll}; /// Client connected to the Nym mixnet. @@ -25,6 +27,8 @@ pub struct MixnetClient { /// The nym address of this connected client. pub(crate) nym_address: Recipient, + pub(crate) identity_keys: Arc, + /// Input to the client from the users perspective. This can be either data to send or control /// messages. pub(crate) client_input: ClientInput, @@ -50,8 +54,10 @@ pub struct MixnetClient { } impl MixnetClient { + #[allow(clippy::too_many_arguments)] pub(crate) fn new( nym_address: Recipient, + identity_keys: Arc, client_input: ClientInput, client_output: ClientOutput, client_state: ClientState, @@ -61,6 +67,7 @@ impl MixnetClient { ) -> Self { Self { nym_address, + identity_keys, client_input, client_output, client_state, @@ -98,6 +105,17 @@ impl MixnetClient { &self.nym_address } + /// Sign a message with the client's private identity key. + pub fn sign(&self, data: &[u8]) -> identity::Signature { + self.identity_keys.private_key().sign(data) + } + + /// Sign a message with the client's private identity key and return it as a base58 encoded + /// signature. + pub fn sign_text(&self, text: &str) -> String { + self.identity_keys.private_key().sign_text(text) + } + /// Get gateway connection information, like the file descriptor of the WebSocket pub fn gateway_connection(&self) -> GatewayConnection { self.client_state.gateway_connection