backwards compatibility for mixnodes announced keys
This commit is contained in:
committed by
Georgio Nicolas
parent
a66852c0ae
commit
afbdc107bf
@@ -896,7 +896,7 @@ pub struct HostKeys {
|
||||
pub current_x25519_sphinx_key: SphinxKey,
|
||||
|
||||
#[serde(default)]
|
||||
pub x25519_noise: Option<VersionedNoiseKey>,
|
||||
pub x25519_versioned_noise: Option<VersionedNoiseKey>,
|
||||
}
|
||||
|
||||
impl From<nym_node_requests::api::v1::node::models::HostKeys> for HostKeys {
|
||||
@@ -904,8 +904,6 @@ impl From<nym_node_requests::api::v1::node::models::HostKeys> for HostKeys {
|
||||
HostKeys {
|
||||
ed25519: value.ed25519_identity,
|
||||
x25519: value.x25519_sphinx,
|
||||
current_x25519_sphinx_key: value.primary_x25519_sphinx_key.into(),
|
||||
pre_announced_x25519_sphinx_key: value.pre_announced_x25519_sphinx_key.map(Into::into),
|
||||
x25519_versioned_noise: value.x25519_versioned_noise,
|
||||
}
|
||||
}
|
||||
@@ -1093,7 +1091,11 @@ impl NymNodeDescription {
|
||||
|
||||
SemiSkimmedNode {
|
||||
basic: skimmed_node,
|
||||
x25519_noise_versioned_key: self.description.host_information.keys.x25519_noise,
|
||||
x25519_noise_versioned_key: self
|
||||
.description
|
||||
.host_information
|
||||
.keys
|
||||
.x25519_versioned_noise,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::Deref;
|
||||
use v1::node::models::LegacyHostInformationV3;
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
pub mod client;
|
||||
@@ -70,6 +71,15 @@ impl SignedHostInformation {
|
||||
|
||||
// TODO: @JS: to remove downgrade support in future release(s)
|
||||
|
||||
let legacy_v3 = SignedData {
|
||||
data: LegacyHostInformationV3::from(self.data.clone()),
|
||||
signature: self.signature.clone(),
|
||||
};
|
||||
|
||||
if legacy_v3.verify(&self.keys.ed25519_identity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// attempt to verify legacy signatures
|
||||
let legacy_v3 = SignedData {
|
||||
data: LegacyHostInformationV3::from(self.data.clone()),
|
||||
@@ -131,7 +141,7 @@ mod tests {
|
||||
let mut rng = rand_chacha::ChaCha20Rng::from_seed([0u8; 32]);
|
||||
let ed22519 = ed25519::KeyPair::new(&mut rng);
|
||||
let x25519_sphinx = x25519::KeyPair::new(&mut rng);
|
||||
let x25519_noise = VersionedNoiseKey {
|
||||
let x25519_versioned_noise = VersionedNoiseKey {
|
||||
version: NoiseVersion::V1,
|
||||
x25519_pubkey: *x25519::KeyPair::new(&mut rng).public_key(),
|
||||
};
|
||||
@@ -145,11 +155,6 @@ mod tests {
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: *ed22519.public_key(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
primary_x25519_sphinx_key: SphinxKey {
|
||||
rotation_id: current_rotation_id,
|
||||
public_key: *x25519_sphinx.public_key(),
|
||||
},
|
||||
pre_announced_x25519_sphinx_key: None,
|
||||
x25519_versioned_noise: None,
|
||||
},
|
||||
};
|
||||
@@ -164,7 +169,7 @@ mod tests {
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: *ed22519.public_key(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
x25519_noise: Some(x25519_noise),
|
||||
x25519_versioned_noise: Some(x25519_versioned_noise),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -314,6 +319,84 @@ mod tests {
|
||||
assert!(current_struct_noise.verify_host_information())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dummy_legacy_v3_signed_host_verification() {
|
||||
let mut rng = rand_chacha::ChaCha20Rng::from_seed([0u8; 32]);
|
||||
let ed22519 = ed25519::KeyPair::new(&mut rng);
|
||||
let x25519_sphinx = x25519::KeyPair::new(&mut rng);
|
||||
let x25519_noise = x25519::KeyPair::new(&mut rng);
|
||||
|
||||
let legacy_info_no_noise = crate::api::v1::node::models::LegacyHostInformationV3 {
|
||||
ip_address: vec!["1.1.1.1".parse().unwrap()],
|
||||
hostname: Some("foomp.com".to_string()),
|
||||
keys: crate::api::v1::node::models::LegacyHostKeysV3 {
|
||||
ed25519_identity: *ed22519.public_key(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
x25519_noise: None,
|
||||
},
|
||||
};
|
||||
|
||||
//technically this variant should never happen
|
||||
let legacy_info_noise = crate::api::v1::node::models::LegacyHostInformationV3 {
|
||||
ip_address: vec!["1.1.1.1".parse().unwrap()],
|
||||
hostname: Some("foomp.com".to_string()),
|
||||
keys: crate::api::v1::node::models::LegacyHostKeysV3 {
|
||||
ed25519_identity: *ed22519.public_key(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
x25519_noise: Some(*x25519_noise.public_key()),
|
||||
},
|
||||
};
|
||||
|
||||
let host_info_no_noise = crate::api::v1::node::models::HostInformation {
|
||||
ip_address: legacy_info_no_noise.ip_address.clone(),
|
||||
hostname: legacy_info_no_noise.hostname.clone(),
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: legacy_info_no_noise.keys.ed25519_identity,
|
||||
x25519_sphinx: legacy_info_no_noise.keys.x25519_sphinx,
|
||||
x25519_versioned_noise: None,
|
||||
},
|
||||
};
|
||||
|
||||
let host_info_noise = crate::api::v1::node::models::HostInformation {
|
||||
ip_address: legacy_info_noise.ip_address.clone(),
|
||||
hostname: legacy_info_noise.hostname.clone(),
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: legacy_info_noise.keys.ed25519_identity,
|
||||
x25519_sphinx: legacy_info_noise.keys.x25519_sphinx,
|
||||
x25519_versioned_noise: Some(VersionedNoiseKey {
|
||||
version: NoiseVersion::V1,
|
||||
x25519_pubkey: legacy_info_noise.keys.x25519_noise.unwrap(),
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
// signature on legacy data
|
||||
let signature_no_noise = SignedData::new(legacy_info_no_noise, ed22519.private_key())
|
||||
.unwrap()
|
||||
.signature;
|
||||
|
||||
let signature_noise = SignedData::new(legacy_info_noise, ed22519.private_key())
|
||||
.unwrap()
|
||||
.signature;
|
||||
|
||||
// signed blob with the 'current' structure
|
||||
let current_struct_no_noise = SignedData {
|
||||
data: host_info_no_noise,
|
||||
signature: signature_no_noise,
|
||||
};
|
||||
|
||||
let current_struct_noise = SignedData {
|
||||
data: host_info_noise,
|
||||
signature: signature_noise,
|
||||
};
|
||||
|
||||
assert!(!current_struct_no_noise.verify(ed22519.public_key()));
|
||||
assert!(current_struct_no_noise.verify_host_information());
|
||||
|
||||
assert!(!current_struct_noise.verify(ed22519.public_key()));
|
||||
assert!(current_struct_noise.verify_host_information())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dummy_legacy_v2_signed_host_verification() {
|
||||
let mut rng = rand_chacha::ChaCha20Rng::from_seed([0u8; 32]);
|
||||
@@ -347,12 +430,7 @@ mod tests {
|
||||
hostname: legacy_info_no_noise.hostname.clone(),
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: legacy_info_no_noise.keys.ed25519_identity.parse().unwrap(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
primary_x25519_sphinx_key: SphinxKey {
|
||||
rotation_id: u32::MAX,
|
||||
public_key: *x25519_sphinx.public_key(),
|
||||
},
|
||||
pre_announced_x25519_sphinx_key: None,
|
||||
x25519_sphinx: legacy_info_no_noise.keys.x25519_sphinx.parse().unwrap(),
|
||||
x25519_versioned_noise: None,
|
||||
},
|
||||
};
|
||||
@@ -364,7 +442,7 @@ mod tests {
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: legacy_info_noise.keys.ed25519_identity.parse().unwrap(),
|
||||
x25519_sphinx: legacy_info_noise.keys.x25519_sphinx.parse().unwrap(),
|
||||
x25519_noise: Some(VersionedNoiseKey {
|
||||
x25519_versioned_noise: Some(VersionedNoiseKey {
|
||||
version: NoiseVersion::V1,
|
||||
x25519_pubkey: legacy_info_noise.keys.x25519_noise.parse().unwrap(),
|
||||
}),
|
||||
@@ -411,7 +489,7 @@ mod tests {
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: *ed22519.public_key(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
x25519_noise: None,
|
||||
x25519_versioned_noise: None,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -421,7 +499,7 @@ mod tests {
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: *ed22519.public_key(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
x25519_noise: Some(VersionedNoiseKey {
|
||||
x25519_versioned_noise: Some(VersionedNoiseKey {
|
||||
version: NoiseVersion::V1,
|
||||
x25519_pubkey: *x25519_noise.public_key(),
|
||||
}),
|
||||
@@ -462,12 +540,7 @@ mod tests {
|
||||
hostname: legacy_info.hostname.clone(),
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: legacy_info.keys.ed25519.parse().unwrap(),
|
||||
x25519_sphinx: *x25519_sphinx.public_key(),
|
||||
primary_x25519_sphinx_key: SphinxKey {
|
||||
rotation_id: u32::MAX,
|
||||
public_key: *x25519_sphinx.public_key(),
|
||||
},
|
||||
pre_announced_x25519_sphinx_key: None,
|
||||
x25519_sphinx: legacy_info.keys.x25519.parse().unwrap(),
|
||||
x25519_versioned_noise: None,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
use celes::Country;
|
||||
use nym_crypto::asymmetric::ed25519::{self, serde_helpers::bs58_ed25519_pubkey};
|
||||
use nym_crypto::asymmetric::x25519::{self, serde_helpers::bs58_x25519_pubkey};
|
||||
use nym_crypto::asymmetric::x25519::{
|
||||
self, serde_helpers::bs58_x25519_pubkey, serde_helpers::option_bs58_x25519_pubkey,
|
||||
};
|
||||
use nym_noise_keys::VersionedNoiseKey;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -144,7 +146,22 @@ pub struct HostKeys {
|
||||
|
||||
/// Base58-encoded x25519 public key of this node used for the noise protocol.
|
||||
#[serde(default)]
|
||||
pub x25519_noise: Option<VersionedNoiseKey>,
|
||||
pub x25519_versioned_noise: Option<VersionedNoiseKey>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LegacyHostKeysV3 {
|
||||
#[serde(alias = "ed25519")]
|
||||
#[serde(with = "bs58_ed25519_pubkey")]
|
||||
pub ed25519_identity: ed25519::PublicKey,
|
||||
|
||||
#[serde(alias = "x25519")]
|
||||
#[serde(with = "bs58_x25519_pubkey")]
|
||||
pub x25519_sphinx: x25519::PublicKey,
|
||||
|
||||
#[serde(default)]
|
||||
#[serde(with = "option_bs58_x25519_pubkey")]
|
||||
pub x25519_noise: Option<x25519::PublicKey>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -164,7 +181,7 @@ impl From<HostKeys> for LegacyHostKeysV3 {
|
||||
fn from(value: HostKeys) -> Self {
|
||||
LegacyHostKeysV3 {
|
||||
ed25519_identity: value.ed25519_identity,
|
||||
x25519_sphinx: value.primary_x25519_sphinx_key.public_key,
|
||||
x25519_sphinx: value.x25519_sphinx,
|
||||
x25519_noise: value.x25519_versioned_noise.map(|k| k.x25519_pubkey),
|
||||
}
|
||||
}
|
||||
@@ -177,7 +194,7 @@ impl From<LegacyHostKeysV3> for LegacyHostKeysV2 {
|
||||
x25519_sphinx: value.x25519_sphinx.to_base58_string(),
|
||||
x25519_noise: value
|
||||
.x25519_noise
|
||||
.map(|k| k.x25519_pubkey.to_base58_string())
|
||||
.map(|k| k.to_base58_string())
|
||||
.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,13 @@ pub mod system_info;
|
||||
pub(crate) fn sign_host_details(
|
||||
config: &Config,
|
||||
x22519_sphinx: &x25519::PublicKey,
|
||||
x25519_noise: &VersionedNoiseKey,
|
||||
x25519_versioned_noise: &VersionedNoiseKey,
|
||||
ed22519_identity: &ed25519::KeyPair,
|
||||
) -> Result<SignedHostInformation, NymNodeError> {
|
||||
let x25519_noise = if config.mixnet.debug.unsafe_disable_noise {
|
||||
let x25519_versioned_noise = if config.mixnet.debug.unsafe_disable_noise {
|
||||
None
|
||||
} else {
|
||||
Some(*x25519_noise)
|
||||
Some(*x25519_versioned_noise)
|
||||
};
|
||||
|
||||
let host_info = api_requests::v1::node::models::HostInformation {
|
||||
@@ -29,7 +29,7 @@ pub(crate) fn sign_host_details(
|
||||
keys: api_requests::v1::node::models::HostKeys {
|
||||
ed25519_identity: *ed22519_identity.public_key(),
|
||||
x25519_sphinx: *x22519_sphinx,
|
||||
x25519_noise,
|
||||
x25519_versioned_noise,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user