added support for aead in nym-crypto

This commit is contained in:
Jędrzej Stuczyński
2024-09-13 11:54:12 +01:00
parent 9213e02b43
commit 8756763875
34 changed files with 366 additions and 140 deletions
Generated
+17
View File
@@ -86,6 +86,21 @@ dependencies = [
"subtle 2.5.0",
]
[[package]]
name = "aes-gcm-siv"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"polyval",
"subtle 2.5.0",
"zeroize",
]
[[package]]
name = "ahash"
version = "0.7.8"
@@ -4770,7 +4785,9 @@ dependencies = [
name = "nym-crypto"
version = "0.4.0"
dependencies = [
"aead",
"aes",
"aes-gcm-siv",
"blake3",
"bs58",
"cipher",
+2
View File
@@ -169,6 +169,8 @@ readme = "README.md"
addr = "0.15.6"
aes = "0.8.1"
aes-gcm = "0.10.1"
aes-gcm-siv = "0.11.1"
aead = "0.5.2"
anyhow = "1.0.89"
argon2 = "0.5.0"
async-trait = "0.1.82"
+1 -1
View File
@@ -18,7 +18,7 @@ nym-ecash-time = { path = "../ecash-time" }
nym-credential-storage = { path = "../credential-storage" }
nym-credentials = { path = "../credentials" }
nym-credentials-interface = { path = "../credentials-interface" }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "stream_cipher", "aes", "hashing"] }
nym-network-defaults = { path = "../network-defaults" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use nym_crypto::asymmetric::identity::Ed25519RecoveryError;
use nym_gateway_requests::registration::handshake::shared_key::SharedKeyConversionError;
use nym_gateway_requests::registration::handshake::SharedKeyConversionError;
use thiserror::Error;
#[derive(Debug, Error)]
@@ -4,7 +4,7 @@
use crate::BadGateway;
use cosmrs::AccountId;
use nym_crypto::asymmetric::identity;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
@@ -64,7 +64,7 @@ impl From<GatewayDetails> for GatewayRegistration {
impl GatewayDetails {
pub fn new_remote(
gateway_id: identity::PublicKey,
derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
derived_aes128_ctr_blake3_hmac_keys: Arc<LegacySharedKeys>,
gateway_owner_address: Option<AccountId>,
gateway_listener: Url,
) -> Self {
@@ -87,7 +87,7 @@ impl GatewayDetails {
}
}
pub fn shared_key(&self) -> Option<&SharedKeys> {
pub fn shared_key(&self) -> Option<&LegacySharedKeys> {
match self {
GatewayDetails::Remote(details) => Some(&details.derived_aes128_ctr_blake3_hmac_keys),
GatewayDetails::Custom(_) => None,
@@ -185,11 +185,13 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
})?;
let derived_aes128_ctr_blake3_hmac_keys = Arc::new(
SharedKeys::try_from_base58_string(&value.derived_aes128_ctr_blake3_hmac_keys_bs58)
.map_err(|source| BadGateway::MalformedSharedKeys {
gateway_id: value.gateway_id_bs58.clone(),
source,
})?,
LegacySharedKeys::try_from_base58_string(
&value.derived_aes128_ctr_blake3_hmac_keys_bs58,
)
.map_err(|source| BadGateway::MalformedSharedKeys {
gateway_id: value.gateway_id_bs58.clone(),
source,
})?,
);
let gateway_owner_address = value
@@ -242,7 +244,7 @@ pub struct RemoteGatewayDetails {
// note: `SharedKeys` implement ZeroizeOnDrop, meaning when `RemoteGatewayDetails` is dropped,
// the keys will be zeroized
pub derived_aes128_ctr_blake3_hmac_keys: Arc<SharedKeys>,
pub derived_aes128_ctr_blake3_hmac_keys: Arc<LegacySharedKeys>,
pub gateway_owner_address: Option<AccountId>,
@@ -13,7 +13,7 @@ pub mod v1_1_33 {
use nym_client_core_gateways_storage::{
CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails,
};
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use serde::{Deserialize, Serialize};
use sha2::{digest::Digest, Sha256};
use std::ops::Deref;
@@ -58,7 +58,7 @@ pub mod v1_1_33 {
}
impl PersistedGatewayConfig {
fn verify(&self, shared_key: &SharedKeys) -> bool {
fn verify(&self, shared_key: &LegacySharedKeys) -> bool {
let key_bytes = Zeroizing::new(shared_key.to_bytes());
let mut key_hasher = Sha256::new();
@@ -74,7 +74,7 @@ pub mod v1_1_33 {
gateway_id: String,
}
fn load_shared_key<P: AsRef<Path>>(path: P) -> Result<SharedKeys, ClientCoreError> {
fn load_shared_key<P: AsRef<Path>>(path: P) -> Result<LegacySharedKeys, ClientCoreError> {
// the shared key was a simple pem file
Ok(nym_pemstore::load_key(path)?)
}
@@ -83,7 +83,7 @@ pub mod v1_1_33 {
gateway_id: String,
gateway_owner: String,
gateway_listener: String,
gateway_shared_key: SharedKeys,
gateway_shared_key: LegacySharedKeys,
) -> Result<GatewayDetails, ClientCoreError> {
Ok(GatewayDetails::Remote(RemoteGatewayDetails {
gateway_id: gateway_id
@@ -3,7 +3,7 @@
use crate::client::key_manager::persistence::KeyStore;
use nym_crypto::asymmetric::{encryption, identity};
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use nym_sphinx::acknowledgements::AckKey;
use rand::{CryptoRng, RngCore};
use std::sync::Arc;
@@ -84,5 +84,5 @@ fn _assert_keys_zeroize_on_drop() {
_assert_zeroize_on_drop::<identity::KeyPair>();
_assert_zeroize_on_drop::<encryption::KeyPair>();
_assert_zeroize_on_drop::<AckKey>();
_assert_zeroize_on_drop::<SharedKeys>();
_assert_zeroize_on_drop::<LegacySharedKeys>();
}
+2 -2
View File
@@ -11,7 +11,7 @@ use nym_client_core_gateways_storage::{
};
use nym_crypto::asymmetric::identity;
use nym_gateway_client::client::InitGatewayClient;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use nym_sphinx::addressing::clients::Recipient;
use nym_topology::gateway;
use nym_validator_client::client::IdentityKey;
@@ -104,7 +104,7 @@ impl SelectedGateway {
/// - shared keys derived between ourselves and the node
/// - an authenticated handle of an ephemeral handle created for the purposes of registration
pub struct RegistrationResult {
pub shared_keys: Arc<SharedKeys>,
pub shared_keys: Arc<LegacySharedKeys>,
pub authenticated_ephemeral_client: InitGatewayClient,
}
@@ -19,7 +19,7 @@ use nym_credentials::CredentialSpendingData;
use nym_crypto::asymmetric::identity;
use nym_gateway_requests::authentication::encrypted_address::EncryptedAddressBytes;
use nym_gateway_requests::iv::IV;
use nym_gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use nym_gateway_requests::registration::handshake::{client_handshake, LegacySharedKeys};
use nym_gateway_requests::{
BinaryRequest, ClientControlRequest, ServerResponse, CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION,
CURRENT_PROTOCOL_VERSION,
@@ -80,7 +80,7 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
gateway_address: String,
gateway_identity: identity::PublicKey,
local_identity: Arc<identity::KeyPair>,
shared_key: Option<Arc<SharedKeys>>,
shared_key: Option<Arc<LegacySharedKeys>>,
connection: SocketState,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
@@ -98,7 +98,7 @@ impl<C, St> GatewayClient<C, St> {
gateway_config: GatewayConfig,
local_identity: Arc<identity::KeyPair>,
// TODO: make it mandatory. if you don't want to pass it, use `new_init`
shared_key: Option<Arc<SharedKeys>>,
shared_key: Option<Arc<LegacySharedKeys>>,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
task_client: TaskClient,
@@ -450,7 +450,7 @@ impl<C, St> GatewayClient<C, St> {
async fn authenticate(
&mut self,
shared_key: Option<SharedKeys>,
shared_key: Option<LegacySharedKeys>,
) -> Result<(), GatewayClientError> {
if shared_key.is_none() && self.shared_key.is_none() {
return Err(GatewayClientError::NoSharedKeyAvailable);
@@ -508,7 +508,13 @@ impl<C, St> GatewayClient<C, St> {
/// Helper method to either call register or authenticate based on self.shared_key value
pub async fn perform_initial_authentication(
&mut self,
) -> Result<Arc<SharedKeys>, GatewayClientError> {
) -> Result<Arc<LegacySharedKeys>, GatewayClientError> {
// 1. check gateway's protocol version
// 2. if error or new handshake unsupported => fallback to the old registration/authentication
// 3. otherwise continue with the updated key derivation
// ?. if new protocol is supported and we have an old key, upgrade it to aes-gcm-siv
if self.authenticated {
debug!("Already authenticated");
return if let Some(shared_key) = &self.shared_key {
@@ -833,7 +839,9 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
pub async fn authenticate_and_start(
&mut self,
) -> Result<Arc<LegacySharedKeys>, GatewayClientError>
where
C: DkgQueryClient + Send + Sync,
St: CredentialStorage,
+2 -2
View File
@@ -7,7 +7,7 @@ use nym_gateway_requests::BinaryResponse;
use tungstenite::{protocol::Message, Error as WsError};
pub use client::{config::GatewayClientConfig, GatewayClient, GatewayConfig};
pub use nym_gateway_requests::registration::handshake::SharedKeys;
pub use nym_gateway_requests::registration::handshake::LegacySharedKeys;
pub use packet_router::{
AcknowledgementReceiver, AcknowledgementSender, MixnetMessageReceiver, MixnetMessageSender,
PacketRouter,
@@ -45,7 +45,7 @@ pub(crate) fn cleanup_socket_messages(
pub(crate) fn try_decrypt_binary_message(
bin_msg: Vec<u8>,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
) -> Option<Vec<u8>> {
match BinaryResponse::try_from_encrypted_tagged_bytes(bin_msg, shared_keys) {
Ok(bin_response) => match bin_response {
@@ -10,7 +10,7 @@ use futures::channel::oneshot;
use futures::stream::{SplitSink, SplitStream};
use futures::{SinkExt, StreamExt};
use log::*;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use nym_gateway_requests::{ServerResponse, SimpleGatewayRequestsError};
use nym_task::TaskClient;
use std::os::raw::c_int as RawFd;
@@ -62,7 +62,7 @@ pub(crate) struct PartiallyDelegatedHandle {
struct PartiallyDelegatedRouter {
packet_router: PacketRouter,
shared_key: Arc<SharedKeys>,
shared_key: Arc<LegacySharedKeys>,
client_bandwidth: ClientBandwidth,
stream_return: SplitStreamSender,
@@ -72,7 +72,7 @@ struct PartiallyDelegatedRouter {
impl PartiallyDelegatedRouter {
fn new(
packet_router: PacketRouter,
shared_key: Arc<SharedKeys>,
shared_key: Arc<LegacySharedKeys>,
client_bandwidth: ClientBandwidth,
stream_return: SplitStreamSender,
stream_return_requester: oneshot::Receiver<()>,
@@ -247,7 +247,7 @@ impl PartiallyDelegatedHandle {
pub(crate) fn split_and_listen_for_mixnet_messages(
conn: WsConn,
packet_router: PacketRouter,
shared_key: Arc<SharedKeys>,
shared_key: Arc<LegacySharedKeys>,
client_bandwidth: ClientBandwidth,
shutdown: TaskClient,
) -> Self {
+4 -1
View File
@@ -8,7 +8,9 @@ license = { workspace = true }
repository = { workspace = true }
[dependencies]
aes-gcm-siv = { workspace = true, optional = true }
aes = { workspace = true, optional = true }
aead = { workspace = true, optional = true }
bs58 = { workspace = true }
blake3 = { workspace = true, features = ["traits-preview"], optional = true }
ctr = { workspace = true, optional = true }
@@ -35,9 +37,10 @@ rand_chacha = { workspace = true }
[features]
default = ["sphinx"]
aead = ["dep:aead", "aead/std", "aes-gcm-siv", "generic-array"]
serde = ["dep:serde", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"]
asymmetric = ["x25519-dalek", "ed25519-dalek", "zeroize"]
hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array"]
symmetric = ["aes", "ctr", "cipher", "generic-array"]
stream_cipher = ["aes", "ctr", "cipher", "generic-array"]
sphinx = ["nym-sphinx-types/sphinx"]
outfox = ["nym-sphinx-types/outfox"]
+6 -5
View File
@@ -10,21 +10,22 @@ pub mod crypto_hash;
pub mod hkdf;
#[cfg(feature = "hashing")]
pub mod hmac;
#[cfg(all(feature = "asymmetric", feature = "hashing", feature = "symmetric"))]
#[cfg(all(feature = "asymmetric", feature = "hashing", feature = "stream_cipher"))]
pub mod shared_key;
#[cfg(feature = "symmetric")]
pub mod symmetric;
#[cfg(feature = "hashing")]
pub use digest::{Digest, OutputSizeUser};
#[cfg(any(feature = "hashing", feature = "symmetric"))]
#[cfg(any(feature = "hashing", feature = "stream_cipher", feature = "aead"))]
pub use generic_array;
// with the below my idea was to try to introduce having a single place of importing all hashing, encryption,
// etc. algorithms and import them elsewhere as needed via common/crypto
#[cfg(feature = "symmetric")]
#[cfg(feature = "stream_cipher")]
pub use aes;
#[cfg(feature = "aead")]
pub use aes_gcm_siv::{Aes128GcmSiv, Aes256GcmSiv};
#[cfg(feature = "hashing")]
pub use blake3;
#[cfg(feature = "symmetric")]
#[cfg(feature = "stream_cipher")]
pub use ctr;
+83
View File
@@ -0,0 +1,83 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use aead::{Aead, AeadCore, AeadInPlace, Buffer, KeyInit, Payload};
#[cfg(feature = "rand")]
use rand::{CryptoRng, RngCore};
pub use aead::{Error as AeadError, Key as AeadKey, KeySizeUser, Nonce, Tag};
#[cfg(feature = "rand")]
pub fn generate_key<A, R>(rng: &mut R) -> AeadKey<A>
where
A: KeyInit,
R: RngCore + CryptoRng,
{
let mut key = AeadKey::<A>::default();
rng.fill_bytes(&mut key);
key
}
#[cfg(feature = "rand")]
pub fn random_nonce<A, R>(rng: &mut R) -> Nonce<A>
where
A: AeadCore,
R: RngCore + CryptoRng,
{
<A as AeadCore>::generate_nonce(rng)
}
#[inline]
pub fn encrypt<'msg, 'aad, A>(
key: &AeadKey<A>,
nonce: &Nonce<A>,
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, AeadError>
where
A: Aead + KeyInit,
{
let cipher = A::new(key);
cipher.encrypt(nonce, plaintext)
}
#[inline]
pub fn decrypt<'msg, 'aad, A>(
key: &AeadKey<A>,
nonce: &Nonce<A>,
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, AeadError>
where
A: Aead + KeyInit,
{
let cipher = A::new(key);
cipher.decrypt(nonce, ciphertext)
}
#[inline]
pub fn encrypt_in_place<A>(
key: &AeadKey<A>,
nonce: &Nonce<A>,
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), AeadError>
where
A: AeadInPlace + KeyInit,
{
let cipher = A::new(key);
cipher.encrypt_in_place(nonce, associated_data, buffer)
}
#[inline]
pub fn decrypt_in_place<A>(
key: &AeadKey<A>,
nonce: &Nonce<A>,
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), AeadError>
where
A: AeadInPlace + KeyInit,
{
let cipher = A::new(key);
cipher.decrypt_in_place(nonce, associated_data, buffer)
}
+3
View File
@@ -1,4 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(feature = "aead")]
pub mod aead;
#[cfg(feature = "stream_cipher")]
pub mod stream_cipher;
+2 -1
View File
@@ -2,12 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
use cipher::{Iv, StreamCipher};
pub use cipher::{IvSizeUser, KeyIvInit, KeySizeUser};
#[cfg(feature = "rand")]
use rand::{CryptoRng, RngCore};
// re-export this for ease of use
pub use cipher::Key as CipherKey;
pub use cipher::{IvSizeUser, KeyIvInit, KeySizeUser};
// SECURITY:
// TODO: note that this is not the most secure approach here
+1 -1
View File
@@ -21,7 +21,7 @@ thiserror = { workspace = true }
tracing = { workspace = true, features = ["log"] }
zeroize = { workspace = true }
nym-crypto = { path = "../crypto" }
nym-crypto = { path = "../crypto", features = ["aead"] }
nym-pemstore = { path = "../pemstore" }
nym-sphinx = { path = "../nymsphinx" }
nym-task = { path = "../task" }
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::iv::IV;
use crate::registration::handshake::shared_key::SharedKeys;
use crate::registration::handshake::LegacySharedKeys;
use nym_crypto::symmetric::stream_cipher;
use nym_sphinx::params::GatewayEncryptionAlgorithm;
use nym_sphinx::params::LegacyGatewayEncryptionAlgorithm;
use nym_sphinx::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
use thiserror::Error;
@@ -28,8 +28,8 @@ pub enum EncryptedAddressConversionError {
}
impl EncryptedAddressBytes {
pub fn new(address: &DestinationAddressBytes, key: &SharedKeys, iv: &IV) -> Self {
let ciphertext = stream_cipher::encrypt::<GatewayEncryptionAlgorithm>(
pub fn new(address: &DestinationAddressBytes, key: &LegacySharedKeys, iv: &IV) -> Self {
let ciphertext = stream_cipher::encrypt::<LegacyGatewayEncryptionAlgorithm>(
key.encryption_key(),
iv.inner(),
address.as_bytes_ref(),
@@ -40,7 +40,12 @@ impl EncryptedAddressBytes {
EncryptedAddressBytes(enc_address)
}
pub fn verify(&self, address: &DestinationAddressBytes, key: &SharedKeys, iv: &IV) -> bool {
pub fn verify(
&self,
address: &DestinationAddressBytes,
key: &LegacySharedKeys,
iv: &IV,
) -> bool {
self == &Self::new(address, key, iv)
}
+5 -5
View File
@@ -3,15 +3,15 @@
use nym_crypto::generic_array::{typenum::Unsigned, GenericArray};
use nym_crypto::symmetric::stream_cipher::{random_iv, IvSizeUser, IV as CryptoIV};
use nym_sphinx::params::GatewayEncryptionAlgorithm;
use nym_sphinx::params::LegacyGatewayEncryptionAlgorithm;
use rand::{CryptoRng, RngCore};
use thiserror::Error;
type NonceSize = <GatewayEncryptionAlgorithm as IvSizeUser>::IvSize;
type NonceSize = <LegacyGatewayEncryptionAlgorithm as IvSizeUser>::IvSize;
// I think 'IV' looks better than 'Iv', feel free to change that.
#[allow(clippy::upper_case_acronyms)]
pub struct IV(CryptoIV<GatewayEncryptionAlgorithm>);
pub struct IV(CryptoIV<LegacyGatewayEncryptionAlgorithm>);
#[derive(Error, Debug)]
// I think 'IV' looks better than 'Iv', feel free to change that.
@@ -29,7 +29,7 @@ pub enum IVConversionError {
impl IV {
pub fn new_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
IV(random_iv::<GatewayEncryptionAlgorithm, _>(rng))
IV(random_iv::<LegacyGatewayEncryptionAlgorithm, _>(rng))
}
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, IVConversionError> {
@@ -48,7 +48,7 @@ impl IV {
self.0.as_ref()
}
pub fn inner(&self) -> &CryptoIV<GatewayEncryptionAlgorithm> {
pub fn inner(&self) -> &CryptoIV<LegacyGatewayEncryptionAlgorithm> {
&self.0
}
+3 -1
View File
@@ -13,15 +13,17 @@ pub mod models;
pub mod registration;
pub mod types;
pub const CURRENT_PROTOCOL_VERSION: u8 = CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION;
pub const CURRENT_PROTOCOL_VERSION: u8 = AES_GCM_SIV_PROTOCOL_VERSION;
/// Defines the current version of the communication protocol between gateway and clients.
/// It has to be incremented for any breaking change.
// history:
// 1 - initial release
// 2 - changes to client credentials structure
// 3 - change to AES-GCM-SIV and non-zero IVs
pub const INITIAL_PROTOCOL_VERSION: u8 = 1;
pub const CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION: u8 = 2;
pub const AES_GCM_SIV_PROTOCOL_VERSION: u8 = 3;
pub type GatewayMac = HmacOutput<GatewayIntegrityHmacAlgorithm>;
@@ -1,8 +1,8 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::registration::handshake::shared_key::SharedKeys;
use crate::registration::handshake::state::State;
use crate::registration::handshake::LegacySharedKeys;
use crate::registration::handshake::{error::HandshakeError, WsItem};
use futures::future::BoxFuture;
use futures::task::{Context, Poll};
@@ -15,7 +15,7 @@ use std::pin::Pin;
use tungstenite::Message as WsMessage;
pub(crate) struct ClientHandshake<'a> {
handshake_future: BoxFuture<'a, Result<SharedKeys, HandshakeError>>,
handshake_future: BoxFuture<'a, Result<LegacySharedKeys, HandshakeError>>,
}
impl<'a> ClientHandshake<'a> {
@@ -121,7 +121,7 @@ impl<'a> ClientHandshake<'a> {
}
impl<'a> Future for ClientHandshake<'a> {
type Output = Result<SharedKeys, HandshakeError>;
type Output = Result<LegacySharedKeys, HandshakeError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.handshake_future).poll(cx)
@@ -1,8 +1,8 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::registration::handshake::shared_key::SharedKeys;
use crate::registration::handshake::state::State;
use crate::registration::handshake::LegacySharedKeys;
use crate::registration::handshake::{error::HandshakeError, WsItem};
use futures::future::BoxFuture;
use futures::task::{Context, Poll};
@@ -14,7 +14,7 @@ use std::pin::Pin;
use tungstenite::Message as WsMessage;
pub(crate) struct GatewayHandshake<'a> {
handshake_future: BoxFuture<'a, Result<SharedKeys, HandshakeError>>,
handshake_future: BoxFuture<'a, Result<LegacySharedKeys, HandshakeError>>,
}
impl<'a> GatewayHandshake<'a> {
@@ -106,7 +106,7 @@ impl<'a> GatewayHandshake<'a> {
}
impl<'a> Future for GatewayHandshake<'a> {
type Output = Result<SharedKeys, HandshakeError>;
type Output = Result<LegacySharedKeys, HandshakeError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.handshake_future).poll(cx)
@@ -3,25 +3,29 @@
use self::client::ClientHandshake;
use self::error::HandshakeError;
#[cfg(not(target_arch = "wasm32"))]
use self::gateway::GatewayHandshake;
pub use self::shared_key::{SharedKeySize, SharedKeys};
use futures::{Sink, Stream};
use nym_crypto::asymmetric::identity;
#[cfg(not(target_arch = "wasm32"))]
use nym_task::TaskClient;
use rand::{CryptoRng, RngCore};
use tungstenite::{Error as WsError, Message as WsMessage};
#[cfg(not(target_arch = "wasm32"))]
use self::gateway::GatewayHandshake;
#[cfg(not(target_arch = "wasm32"))]
use nym_task::TaskClient;
pub(crate) type WsItem = Result<WsMessage, WsError>;
mod client;
pub mod error;
#[cfg(not(target_arch = "wasm32"))]
mod gateway;
pub mod shared_key;
mod shared_key;
mod state;
pub use self::shared_key::legacy::{LegacySharedKeySize, LegacySharedKeys};
pub use self::shared_key::{SharedKeyConversionError, SharedSymmetricKey};
// Note: the handshake is built on top of WebSocket, but in principle it shouldn't be too difficult
// to remove that restriction, by just changing Sink<WsMessage> and Stream<Item = WsMessage> into
// AsyncWrite and AsyncRead and slightly adjusting the implementation. But right now
@@ -34,7 +38,7 @@ pub async fn client_handshake<'a, S>(
gateway_pubkey: identity::PublicKey,
expects_credential_usage: bool,
#[cfg(not(target_arch = "wasm32"))] shutdown: TaskClient,
) -> Result<SharedKeys, HandshakeError>
) -> Result<LegacySharedKeys, HandshakeError>
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
@@ -57,7 +61,7 @@ pub async fn gateway_handshake<'a, S>(
identity: &'a identity::KeyPair,
received_init_payload: Vec<u8>,
shutdown: TaskClient,
) -> Result<SharedKeys, HandshakeError>
) -> Result<LegacySharedKeys, HandshakeError>
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
@@ -1,6 +1,7 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::registration::handshake::shared_key::SharedKeyConversionError;
use crate::{GatewayMacSize, GatewayRequestsError};
use nym_crypto::generic_array::{
typenum::{Sum, Unsigned, U16},
@@ -9,43 +10,32 @@ use nym_crypto::generic_array::{
use nym_crypto::hmac::{compute_keyed_hmac, recompute_keyed_hmac_and_verify_tag};
use nym_crypto::symmetric::stream_cipher::{self, CipherKey, KeySizeUser, IV};
use nym_pemstore::traits::PemStorableKey;
use nym_sphinx::params::{GatewayEncryptionAlgorithm, GatewayIntegrityHmacAlgorithm};
use nym_sphinx::params::{GatewayIntegrityHmacAlgorithm, LegacyGatewayEncryptionAlgorithm};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use zeroize::{Zeroize, ZeroizeOnDrop};
// shared key is as long as the encryption key and the MAC key combined.
pub type SharedKeySize = Sum<EncryptionKeySize, MacKeySize>;
pub type LegacySharedKeySize = Sum<EncryptionKeySize, MacKeySize>;
// we're using 16 byte long key in sphinx, so let's use the same one here
type MacKeySize = U16;
type EncryptionKeySize = <GatewayEncryptionAlgorithm as KeySizeUser>::KeySize;
type EncryptionKeySize = <LegacyGatewayEncryptionAlgorithm as KeySizeUser>::KeySize;
/// Shared key used when computing MAC for messages exchanged between client and its gateway.
pub type MacKey = GenericArray<u8, MacKeySize>;
#[derive(Debug, PartialEq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
pub struct SharedKeys {
encryption_key: CipherKey<GatewayEncryptionAlgorithm>,
pub struct LegacySharedKeys {
encryption_key: CipherKey<LegacyGatewayEncryptionAlgorithm>,
mac_key: MacKey,
}
#[derive(Debug, Clone, Copy, Error)]
pub enum SharedKeyConversionError {
#[error("the string representation of the shared keys was malformed - {0}")]
DecodeError(#[from] bs58::decode::Error),
#[error(
"the received shared keys had invalid size. Got: {received}, but expected: {expected}"
)]
InvalidSharedKeysSize { received: usize, expected: usize },
}
impl SharedKeys {
impl LegacySharedKeys {
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SharedKeyConversionError> {
if bytes.len() != SharedKeySize::to_usize() {
if bytes.len() != LegacySharedKeySize::to_usize() {
return Err(SharedKeyConversionError::InvalidSharedKeysSize {
received: bytes.len(),
expected: SharedKeySize::to_usize(),
expected: LegacySharedKeySize::to_usize(),
});
}
@@ -53,7 +43,7 @@ impl SharedKeys {
GenericArray::clone_from_slice(&bytes[..EncryptionKeySize::to_usize()]);
let mac_key = GenericArray::clone_from_slice(&bytes[EncryptionKeySize::to_usize()..]);
Ok(SharedKeys {
Ok(LegacySharedKeys {
encryption_key,
mac_key,
})
@@ -65,17 +55,17 @@ impl SharedKeys {
pub fn encrypt_and_tag(
&self,
data: &[u8],
iv: Option<&IV<GatewayEncryptionAlgorithm>>,
iv: Option<&IV<LegacyGatewayEncryptionAlgorithm>>,
) -> Vec<u8> {
let encrypted_data = match iv {
Some(iv) => stream_cipher::encrypt::<GatewayEncryptionAlgorithm>(
Some(iv) => stream_cipher::encrypt::<LegacyGatewayEncryptionAlgorithm>(
self.encryption_key(),
iv,
data,
),
None => {
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
stream_cipher::encrypt::<GatewayEncryptionAlgorithm>(
let zero_iv = stream_cipher::zero_iv::<LegacyGatewayEncryptionAlgorithm>();
stream_cipher::encrypt::<LegacyGatewayEncryptionAlgorithm>(
self.encryption_key(),
&zero_iv,
data,
@@ -93,7 +83,7 @@ impl SharedKeys {
pub fn decrypt_tagged(
&self,
enc_data: &[u8],
iv: Option<&IV<GatewayEncryptionAlgorithm>>,
iv: Option<&IV<LegacyGatewayEncryptionAlgorithm>>,
) -> Result<Vec<u8>, GatewayRequestsError> {
let mac_size = GatewayMacSize::to_usize();
if enc_data.len() < mac_size {
@@ -115,9 +105,9 @@ impl SharedKeys {
// together with a mutable one
let message_bytes_mut = &mut enc_data.to_vec()[mac_size..];
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
let zero_iv = stream_cipher::zero_iv::<LegacyGatewayEncryptionAlgorithm>();
let iv = iv.unwrap_or(&zero_iv);
stream_cipher::decrypt_in_place::<GatewayEncryptionAlgorithm>(
stream_cipher::decrypt_in_place::<LegacyGatewayEncryptionAlgorithm>(
self.encryption_key(),
iv,
message_bytes_mut,
@@ -125,7 +115,7 @@ impl SharedKeys {
Ok(message_bytes_mut.to_vec())
}
pub fn encryption_key(&self) -> &CipherKey<GatewayEncryptionAlgorithm> {
pub fn encryption_key(&self) -> &CipherKey<LegacyGatewayEncryptionAlgorithm> {
&self.encryption_key
}
@@ -145,7 +135,7 @@ impl SharedKeys {
val: S,
) -> Result<Self, SharedKeyConversionError> {
let decoded = bs58::decode(val.into()).into_vec()?;
SharedKeys::try_from_bytes(&decoded)
LegacySharedKeys::try_from_bytes(&decoded)
}
pub fn to_base58_string(&self) -> String {
@@ -153,13 +143,13 @@ impl SharedKeys {
}
}
impl From<SharedKeys> for String {
fn from(keys: SharedKeys) -> Self {
impl From<LegacySharedKeys> for String {
fn from(keys: LegacySharedKeys) -> Self {
keys.to_base58_string()
}
}
impl PemStorableKey for SharedKeys {
impl PemStorableKey for LegacySharedKeys {
type Error = SharedKeyConversionError;
fn pem_type() -> &'static str {
@@ -0,0 +1,90 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::GatewayRequestsError;
use nym_crypto::generic_array::{typenum::Unsigned, GenericArray};
use nym_crypto::symmetric::aead::{self, AeadKey, KeySizeUser, Nonce};
use nym_pemstore::traits::PemStorableKey;
use nym_sphinx::params::GatewayEncryptionAlgorithm;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
pub mod legacy;
#[derive(Debug, PartialEq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
pub struct SharedSymmetricKey(AeadKey<GatewayEncryptionAlgorithm>);
type KeySize = <GatewayEncryptionAlgorithm as KeySizeUser>::KeySize;
#[derive(Debug, Clone, Copy, Error)]
pub enum SharedKeyConversionError {
#[error("the string representation of the shared key was malformed: {0}")]
DecodeError(#[from] bs58::decode::Error),
#[error(
"the received shared keys had invalid size. Got: {received}, but expected: {expected}"
)]
InvalidSharedKeysSize { received: usize, expected: usize },
}
impl SharedSymmetricKey {
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SharedKeyConversionError> {
if bytes.len() != KeySize::to_usize() {
return Err(SharedKeyConversionError::InvalidSharedKeysSize {
received: bytes.len(),
expected: KeySize::to_usize(),
});
}
Ok(SharedSymmetricKey(GenericArray::clone_from_slice(bytes)))
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.iter().copied().collect()
}
pub fn try_from_base58_string<S: Into<String>>(
val: S,
) -> Result<Self, SharedKeyConversionError> {
let bs58_str = Zeroizing::new(val.into());
let decoded = Zeroizing::new(bs58::decode(bs58_str).into_vec()?);
Self::try_from_bytes(&decoded)
}
pub fn to_base58_string(&self) -> String {
let bytes = Zeroizing::new(self.to_bytes());
bs58::encode(bytes).into_string()
}
pub fn encrypt(
&self,
plaintext: &[u8],
nonce: &Nonce<GatewayEncryptionAlgorithm>,
) -> Result<Vec<u8>, GatewayRequestsError> {
aead::encrypt::<GatewayEncryptionAlgorithm>(&self.0, &nonce, plaintext).map_err(Into::into)
}
pub fn decrypt(
&self,
ciphertext: &[u8],
nonce: &Nonce<GatewayEncryptionAlgorithm>,
) -> Result<Vec<u8>, GatewayRequestsError> {
aead::decrypt::<GatewayEncryptionAlgorithm>(&self.0, &nonce, ciphertext).map_err(Into::into)
}
}
impl PemStorableKey for SharedSymmetricKey {
type Error = SharedKeyConversionError;
fn pem_type() -> &'static str {
"AES-256-GCM-SIV GATEWAY SHARED KEY"
}
fn to_bytes(&self) -> Vec<u8> {
self.to_bytes()
}
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
Self::try_from_bytes(bytes)
}
}
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::registration::handshake::error::HandshakeError;
use crate::registration::handshake::shared_key::{SharedKeySize, SharedKeys};
use crate::registration::handshake::WsItem;
use crate::registration::handshake::{LegacySharedKeySize, LegacySharedKeys};
use crate::types;
use futures::{Sink, SinkExt, Stream, StreamExt};
use nym_crypto::{
@@ -12,7 +12,7 @@ use nym_crypto::{
hkdf,
symmetric::stream_cipher,
};
use nym_sphinx::params::{GatewayEncryptionAlgorithm, GatewaySharedKeyHkdfAlgorithm};
use nym_sphinx::params::{GatewaySharedKeyHkdfAlgorithm, LegacyGatewayEncryptionAlgorithm};
#[cfg(not(target_arch = "wasm32"))]
use nym_task::TaskClient;
use rand::{CryptoRng, RngCore};
@@ -41,7 +41,7 @@ pub(crate) struct State<'a, S> {
ephemeral_keypair: encryption::KeyPair,
/// The derived shared key using the ephemeral keys of both parties.
derived_shared_keys: Option<SharedKeys>,
derived_shared_keys: Option<LegacySharedKeys>,
/// The known or received public identity key of the remote.
/// Ideally it would always be known before the handshake was initiated.
@@ -128,12 +128,12 @@ impl<'a, S> State<'a, S> {
None,
&dh_result,
None,
SharedKeySize::to_usize(),
LegacySharedKeySize::to_usize(),
)
.expect("somehow too long okm was provided");
let derived_shared_key =
SharedKeys::try_from_bytes(&okm).expect("okm was expanded to incorrect length!");
LegacySharedKeys::try_from_bytes(&okm).expect("okm was expanded to incorrect length!");
self.derived_shared_keys = Some(derived_shared_key)
}
@@ -153,8 +153,8 @@ impl<'a, S> State<'a, S> {
.collect();
let signature = self.identity.private_key().sign(message);
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
stream_cipher::encrypt::<GatewayEncryptionAlgorithm>(
let zero_iv = stream_cipher::zero_iv::<LegacyGatewayEncryptionAlgorithm>();
stream_cipher::encrypt::<LegacyGatewayEncryptionAlgorithm>(
self.derived_shared_keys.as_ref().unwrap().encryption_key(),
&zero_iv,
&signature.to_bytes(),
@@ -178,8 +178,8 @@ impl<'a, S> State<'a, S> {
.expect("shared key was not derived!");
// first decrypt received data
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
let decrypted_signature = stream_cipher::decrypt::<GatewayEncryptionAlgorithm>(
let zero_iv = stream_cipher::zero_iv::<LegacyGatewayEncryptionAlgorithm>();
let decrypted_signature = stream_cipher::decrypt::<LegacyGatewayEncryptionAlgorithm>(
derived_shared_key.encryption_key(),
&zero_iv,
remote_material,
@@ -320,7 +320,7 @@ impl<'a, S> State<'a, S> {
/// Finish the handshake, yielding the derived shared key and implicitly dropping all borrowed
/// values.
pub(crate) fn finalize_handshake(self) -> SharedKeys {
pub(crate) fn finalize_handshake(self) -> LegacySharedKeys {
self.derived_shared_keys.unwrap()
}
}
+16 -12
View File
@@ -4,7 +4,7 @@
use crate::authentication::encrypted_address::EncryptedAddressBytes;
use crate::iv::{IVConversionError, IV};
use crate::models::CredentialSpendingRequest;
use crate::registration::handshake::SharedKeys;
use crate::registration::handshake::LegacySharedKeys;
use crate::{GatewayMacSize, CURRENT_PROTOCOL_VERSION, INITIAL_PROTOCOL_VERSION};
use nym_credentials::ecash::bandwidth::CredentialSpendingData;
use nym_credentials_interface::CompactEcashError;
@@ -14,11 +14,12 @@ use nym_crypto::symmetric::stream_cipher;
use nym_sphinx::addressing::nodes::NymNodeRoutingAddressError;
use nym_sphinx::forwarding::packet::{MixPacket, MixPacketFormattingError};
use nym_sphinx::params::packet_sizes::PacketSize;
use nym_sphinx::params::{GatewayEncryptionAlgorithm, GatewayIntegrityHmacAlgorithm};
use nym_sphinx::params::{GatewayIntegrityHmacAlgorithm, LegacyGatewayEncryptionAlgorithm};
use nym_sphinx::DestinationAddressBytes;
use serde::{Deserialize, Serialize};
use tracing::log::error;
use nym_crypto::symmetric::aead::AeadError;
use std::str::FromStr;
use std::string::FromUtf8Error;
use thiserror::Error;
@@ -154,6 +155,9 @@ pub enum GatewayRequestsError {
#[error("the provided [v1] credential has invalid number of parameters - {0}")]
InvalidNumberOfEmbededParameters(u32),
#[error("failed to either encrypt or decrypt provided message")]
AeadFailure(#[from] AeadError),
// variant to catch legacy errors
#[error("{0}")]
Other(String),
@@ -236,7 +240,7 @@ impl ClientControlRequest {
pub fn new_enc_ecash_credential(
credential: CredentialSpendingData,
shared_key: &SharedKeys,
shared_key: &LegacySharedKeys,
iv: IV,
) -> Self {
let cred = CredentialSpendingRequest::new(credential);
@@ -251,7 +255,7 @@ impl ClientControlRequest {
pub fn try_from_enc_ecash_credential(
enc_credential: Vec<u8>,
shared_key: &SharedKeys,
shared_key: &LegacySharedKeys,
iv: Vec<u8>,
) -> Result<CredentialSpendingRequest, GatewayRequestsError> {
let iv = IV::try_from_bytes(&iv)?;
@@ -388,7 +392,7 @@ pub enum BinaryRequest {
impl BinaryRequest {
pub fn try_from_encrypted_tagged_bytes(
raw_req: Vec<u8>,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
) -> Result<Self, GatewayRequestsError> {
let message_bytes = &shared_keys.decrypt_tagged(&raw_req, None)?;
@@ -398,7 +402,7 @@ impl BinaryRequest {
Ok(BinaryRequest::ForwardSphinx(mix_packet))
}
pub fn into_encrypted_tagged_bytes(self, shared_key: &SharedKeys) -> Vec<u8> {
pub fn into_encrypted_tagged_bytes(self, shared_key: &LegacySharedKeys) -> Vec<u8> {
match self {
BinaryRequest::ForwardSphinx(mix_packet) => {
let forwarding_data = match mix_packet.into_bytes() {
@@ -421,7 +425,7 @@ impl BinaryRequest {
BinaryRequest::ForwardSphinx(mix_packet)
}
pub fn into_ws_message(self, shared_key: &SharedKeys) -> Message {
pub fn into_ws_message(self, shared_key: &LegacySharedKeys) -> Message {
Message::Binary(self.into_encrypted_tagged_bytes(shared_key))
}
}
@@ -434,7 +438,7 @@ pub enum BinaryResponse {
impl BinaryResponse {
pub fn try_from_encrypted_tagged_bytes(
raw_req: Vec<u8>,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
) -> Result<Self, GatewayRequestsError> {
let mac_size = GatewayMacSize::to_usize();
if raw_req.len() < mac_size {
@@ -452,8 +456,8 @@ impl BinaryResponse {
return Err(GatewayRequestsError::InvalidMac);
}
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
let plaintext = stream_cipher::decrypt::<GatewayEncryptionAlgorithm>(
let zero_iv = stream_cipher::zero_iv::<LegacyGatewayEncryptionAlgorithm>();
let plaintext = stream_cipher::decrypt::<LegacyGatewayEncryptionAlgorithm>(
shared_keys.encryption_key(),
&zero_iv,
message_bytes,
@@ -462,7 +466,7 @@ impl BinaryResponse {
Ok(BinaryResponse::PushedMixMessage(plaintext))
}
pub fn into_encrypted_tagged_bytes(self, shared_key: &SharedKeys) -> Vec<u8> {
pub fn into_encrypted_tagged_bytes(self, shared_key: &LegacySharedKeys) -> Vec<u8> {
match self {
// TODO: it could be theoretically slightly more efficient if the data wasn't taken
// by reference because then it makes a copy for encryption rather than do it in place
@@ -474,7 +478,7 @@ impl BinaryResponse {
BinaryResponse::PushedMixMessage(msg)
}
pub fn into_ws_message(self, shared_key: &SharedKeys) -> Message {
pub fn into_ws_message(self, shared_key: &LegacySharedKeys) -> Message {
Message::Binary(self.into_encrypted_tagged_bytes(shared_key))
}
}
+3 -3
View File
@@ -11,7 +11,7 @@ use models::{
VerifiedTicket, WireguardPeer,
};
use nym_credentials_interface::ClientTicket;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use nym_sphinx::DestinationAddressBytes;
use shared_keys::SharedKeysManager;
use sqlx::ConnectOptions;
@@ -46,7 +46,7 @@ pub trait Storage: Send + Sync {
async fn insert_shared_keys(
&self,
client_address: DestinationAddressBytes,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
) -> Result<i64, StorageError>;
/// Tries to retrieve shared keys stored for the particular client.
@@ -330,7 +330,7 @@ impl Storage for PersistentStorage {
async fn insert_shared_keys(
&self,
client_address: DestinationAddressBytes,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
) -> Result<i64, StorageError> {
let client_id = self
.client_manager
+1 -1
View File
@@ -14,7 +14,7 @@ generic-array = { workspace = true, optional = true, features = ["serde"] }
thiserror = { workspace = true }
zeroize = { workspace = true }
nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] }
nym-crypto = { path = "../../crypto", features = ["stream_cipher", "rand"] }
nym-pemstore = { path = "../../pemstore" }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-params = { path = "../params" }
@@ -13,7 +13,7 @@ bs58 = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] }
nym-crypto = { path = "../../crypto", features = ["stream_cipher", "rand"] }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
+1 -1
View File
@@ -11,7 +11,7 @@ repository = { workspace = true }
thiserror = { workspace = true }
serde = { workspace = true, features = ["derive"] }
nym-crypto = { path = "../../crypto", features = ["hashing", "symmetric"] }
nym-crypto = { path = "../../crypto", features = ["hashing", "stream_cipher", "aes-gcm-siv"] }
nym-sphinx-types = { path = "../types" }
[features]
+10 -4
View File
@@ -4,6 +4,7 @@
use nym_crypto::aes::Aes128;
use nym_crypto::blake3;
use nym_crypto::ctr;
use nym_crypto::Aes256GcmSiv;
type Aes128Ctr = ctr::Ctr64BE<Aes128>;
@@ -48,7 +49,7 @@ pub type GatewaySharedKeyHkdfAlgorithm = 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
// TODO: if updated, the pem type defined in gateway\gateway-requests\src\registration\handshake\legacy_shared_key
// needs updating!
pub type GatewayIntegrityHmacAlgorithm = blake3::Hasher;
@@ -59,11 +60,16 @@ pub type GatewayIntegrityHmacAlgorithm = blake3::Hasher;
// - the pem type defined in nym\common\nymsphinx\acknowledgements\src\key needs updating!
pub type AckEncryptionAlgorithm = Aes128Ctr;
/// Legacy encryption algorithm used for end-to-end encryption of messages exchanged between clients
/// and their gateways.
// TODO: if updated, the pem type defined in gateway\gateway-requests\src\registration\handshake\legacy_shared_key
// needs updating!
pub type LegacyGatewayEncryptionAlgorithm = Aes128Ctr;
/// Encryption algorithm used for end-to-end encryption of messages exchanged between clients
/// and their gateways.
// TODO: if updated, the pem type defined in gateway\gateway-requests\src\registration\handshake\shared_key
// needs updating!
pub type GatewayEncryptionAlgorithm = Aes128Ctr;
// NOTE: if updated, the pem type defined in gateway\gateway-requests\src\registration\handshake\shared_key
pub type GatewayEncryptionAlgorithm = Aes256GcmSiv;
/// Encryption algorithm used for end-to-end encryption of messages exchanged between clients that are
/// encapsulated inside sphinx packets.
@@ -21,10 +21,11 @@ use nym_crypto::asymmetric::identity;
use nym_gateway_requests::authentication::encrypted_address::{
EncryptedAddressBytes, EncryptedAddressConversionError,
};
use nym_gateway_requests::registration::handshake::shared_key::SharedKeyConversionError;
use nym_gateway_requests::{
iv::{IVConversionError, IV},
registration::handshake::{error::HandshakeError, gateway_handshake, SharedKeys},
registration::handshake::{
error::HandshakeError, gateway_handshake, LegacySharedKeys, SharedKeyConversionError,
},
types::{ClientControlRequest, ServerResponse},
BinaryResponse, CURRENT_PROTOCOL_VERSION, INITIAL_PROTOCOL_VERSION,
};
@@ -177,7 +178,7 @@ where
async fn perform_registration_handshake(
&mut self,
init_msg: Vec<u8>,
) -> Result<SharedKeys, HandshakeError>
) -> Result<LegacySharedKeys, HandshakeError>
where
S: AsyncRead + AsyncWrite + Unpin + Send,
{
@@ -258,7 +259,7 @@ where
/// * `packets`: unwrapped packets that are to be pushed back to the client.
pub(crate) async fn push_packets_to_client(
&mut self,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
packets: Vec<Vec<u8>>,
) -> Result<(), WsError>
where
@@ -313,7 +314,7 @@ where
async fn push_stored_messages_to_client(
&mut self,
client_address: DestinationAddressBytes,
shared_keys: &SharedKeys,
shared_keys: &LegacySharedKeys,
) -> Result<(), InitialAuthenticationError>
where
S: AsyncRead + AsyncWrite + Unpin,
@@ -367,7 +368,7 @@ where
client_address: DestinationAddressBytes,
encrypted_address: EncryptedAddressBytes,
iv: IV,
) -> Result<Option<SharedKeys>, InitialAuthenticationError> {
) -> Result<Option<LegacySharedKeys>, InitialAuthenticationError> {
let shared_keys = self
.shared_state
.storage
@@ -378,7 +379,7 @@ where
// this should never fail as we only ever construct persisted shared keys ourselves when inserting
// data to the storage. The only way it could fail is if we somehow changed implementation without
// performing proper migration
let keys = SharedKeys::try_from_base58_string(
let keys = LegacySharedKeys::try_from_base58_string(
shared_keys.derived_aes128_ctr_blake3_hmac_keys_bs58,
)
.map_err(|source| {
@@ -451,7 +452,7 @@ where
client_address: DestinationAddressBytes,
encrypted_address: EncryptedAddressBytes,
iv: IV,
) -> Result<Option<SharedKeys>, InitialAuthenticationError>
) -> Result<Option<LegacySharedKeys>, InitialAuthenticationError>
where
S: AsyncRead + AsyncWrite + Unpin,
{
@@ -616,7 +617,7 @@ where
async fn register_client(
&mut self,
client_address: DestinationAddressBytes,
client_shared_keys: &SharedKeys,
client_shared_keys: &LegacySharedKeys,
) -> Result<i64, InitialAuthenticationError>
where
S: AsyncRead + AsyncWrite + Unpin,
@@ -3,7 +3,7 @@
use crate::config::Config;
use nym_credential_verification::BandwidthFlushingBehaviourConfig;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_gateway_requests::registration::handshake::LegacySharedKeys;
use nym_gateway_requests::ServerResponse;
use nym_gateway_storage::Storage;
use nym_sphinx::DestinationAddressBytes;
@@ -46,11 +46,15 @@ pub(crate) struct ClientDetails {
#[zeroize(skip)]
pub(crate) address: DestinationAddressBytes,
pub(crate) id: i64,
pub(crate) shared_keys: SharedKeys,
pub(crate) shared_keys: LegacySharedKeys,
}
impl ClientDetails {
pub(crate) fn new(id: i64, address: DestinationAddressBytes, shared_keys: SharedKeys) -> Self {
pub(crate) fn new(
id: i64,
address: DestinationAddressBytes,
shared_keys: LegacySharedKeys,
) -> Self {
ClientDetails {
address,
id,