allow nym-api to understand signatures on legacy host information

This commit is contained in:
Jędrzej Stuczyński
2024-04-09 16:17:39 +01:00
parent 69c1a32392
commit 0ed43d2439
4 changed files with 129 additions and 2 deletions
Generated
+1
View File
@@ -6247,6 +6247,7 @@ dependencies = [
"nym-exit-policy",
"nym-http-api-client",
"nym-wireguard-types",
"rand_chacha 0.2.2",
"schemars",
"serde",
"serde_json",
+3
View File
@@ -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"]
+93 -2
View File
@@ -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 {