allow nym-api to understand signatures on legacy host information
This commit is contained in:
Generated
+1
@@ -6247,6 +6247,7 @@ dependencies = [
|
||||
"nym-exit-policy",
|
||||
"nym-http-api-client",
|
||||
"nym-wireguard-types",
|
||||
"rand_chacha 0.2.2",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -36,6 +36,9 @@ nym-bin-common = { path = "../../common/bin-common", features = ["bin_info_schem
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
rand_chacha = "0.2"
|
||||
nym-crypto = { path = "../../common/crypto", features = ["rand"] }
|
||||
|
||||
|
||||
[features]
|
||||
default = ["client"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::api::v1::node::models::HostInformation;
|
||||
use crate::api::v1::node::models::{HostInformation, LegacyHostInformation};
|
||||
use crate::error::Error;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use schemars::JsonSchema;
|
||||
@@ -61,7 +61,16 @@ impl SignedHostInformation {
|
||||
return false;
|
||||
};
|
||||
|
||||
self.verify(&pub_key)
|
||||
if self.verify(&pub_key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// attempt to verify legacy signature
|
||||
SignedData {
|
||||
data: LegacyHostInformation::from(self.data.clone()),
|
||||
signature: self.signature.clone(),
|
||||
}
|
||||
.verify(&pub_key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,3 +93,85 @@ impl Display for ErrorResponse {
|
||||
self.message.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use rand_chacha::rand_core::SeedableRng;
|
||||
use std::net::IpAddr;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct LegacyHostInformation {
|
||||
pub ip_address: Vec<IpAddr>,
|
||||
pub hostname: Option<String>,
|
||||
pub keys: LegacyKeys,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct LegacyKeys {
|
||||
pub ed25519: String,
|
||||
pub x25519: String,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dummy_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 host_info = crate::api::v1::node::models::HostInformation {
|
||||
ip_address: vec!["1.1.1.1".parse().unwrap()],
|
||||
hostname: Some("foomp.com".to_string()),
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: ed22519.public_key().to_base58_string(),
|
||||
x25519_sphinx: x25519_sphinx.public_key().to_base58_string(),
|
||||
x25519_noise: "".to_string(),
|
||||
},
|
||||
};
|
||||
|
||||
let signed_info = SignedHostInformation::new(host_info, ed22519.private_key()).unwrap();
|
||||
assert!(signed_info.verify(ed22519.public_key()));
|
||||
assert!(signed_info.verify_host_information())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dummy_legacy_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 legacy_info = crate::api::v1::node::models::LegacyHostInformation {
|
||||
ip_address: vec!["1.1.1.1".parse().unwrap()],
|
||||
hostname: Some("foomp.com".to_string()),
|
||||
keys: crate::api::v1::node::models::LegacyHostKeys {
|
||||
ed25519: ed22519.public_key().to_base58_string(),
|
||||
x25519: x25519_sphinx.public_key().to_base58_string(),
|
||||
},
|
||||
};
|
||||
|
||||
let host_info = crate::api::v1::node::models::HostInformation {
|
||||
ip_address: legacy_info.ip_address.clone(),
|
||||
hostname: legacy_info.hostname.clone(),
|
||||
keys: crate::api::v1::node::models::HostKeys {
|
||||
ed25519_identity: legacy_info.keys.ed25519.clone(),
|
||||
x25519_sphinx: legacy_info.keys.x25519.clone(),
|
||||
x25519_noise: "".to_string(),
|
||||
},
|
||||
};
|
||||
|
||||
// signature on legacy data
|
||||
let signature = SignedData::new(legacy_info, ed22519.private_key())
|
||||
.unwrap()
|
||||
.signature;
|
||||
|
||||
// signed blob with the 'current' structure
|
||||
let current_struct = SignedData {
|
||||
data: host_info,
|
||||
signature,
|
||||
};
|
||||
|
||||
assert!(!current_struct.verify(ed22519.public_key()));
|
||||
assert!(current_struct.verify_host_information())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,23 @@ pub struct HostInformation {
|
||||
pub keys: HostKeys,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LegacyHostInformation {
|
||||
pub ip_address: Vec<IpAddr>,
|
||||
pub hostname: Option<String>,
|
||||
pub keys: LegacyHostKeys,
|
||||
}
|
||||
|
||||
impl From<HostInformation> for LegacyHostInformation {
|
||||
fn from(value: HostInformation) -> Self {
|
||||
LegacyHostInformation {
|
||||
ip_address: value.ip_address,
|
||||
hostname: value.hostname,
|
||||
keys: value.keys.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct HostKeys {
|
||||
@@ -49,6 +66,21 @@ pub struct HostKeys {
|
||||
pub x25519_noise: String,
|
||||
}
|
||||
|
||||
impl From<HostKeys> for LegacyHostKeys {
|
||||
fn from(value: HostKeys) -> Self {
|
||||
LegacyHostKeys {
|
||||
ed25519: value.ed25519_identity,
|
||||
x25519: value.x25519_sphinx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LegacyHostKeys {
|
||||
pub ed25519: String,
|
||||
pub x25519: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct HostSystem {
|
||||
|
||||
Reference in New Issue
Block a user