Feature/mix ed25519 identity (#388)
* Introduced identity keypair to mixnode * Updated upgrade 0.9.0 mix upgrade instructions * Printing failed upgrade notice when it failed * Moved printing upgrade start notice to beginning of function
This commit is contained in:
committed by
GitHub
parent
c8bf454ccc
commit
2f7b3eec08
@@ -16,7 +16,7 @@ use crate::commands::override_config;
|
||||
use crate::config::persistence::pathfinder::MixNodePathfinder;
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::encryption;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use directory_client::DirectoryClient;
|
||||
use log::*;
|
||||
use nymsphinx::params::DEFAULT_NUM_MIX_HOPS;
|
||||
@@ -142,8 +142,18 @@ pub fn execute(matches: &ArgMatches) {
|
||||
config = config.with_layer(layer);
|
||||
debug!("Choosing layer {}", config.get_layer());
|
||||
|
||||
let identity_keys = identity::KeyPair::new();
|
||||
let sphinx_keys = encryption::KeyPair::new();
|
||||
let pathfinder = MixNodePathfinder::new_from_config(&config);
|
||||
pemstore::store_keypair(
|
||||
&identity_keys,
|
||||
&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
pathfinder.public_identity_key().to_owned(),
|
||||
),
|
||||
)
|
||||
.expect("Failed to save identity keys");
|
||||
|
||||
pemstore::store_keypair(
|
||||
&sphinx_keys,
|
||||
&pemstore::KeyPairPath::new(
|
||||
@@ -152,7 +162,8 @@ pub fn execute(matches: &ArgMatches) {
|
||||
),
|
||||
)
|
||||
.expect("Failed to save sphinx keys");
|
||||
println!("Saved mixnet sphinx keypair");
|
||||
|
||||
println!("Saved mixnet identity and sphinx keypairs");
|
||||
let config_save_location = config.get_config_file_save_location();
|
||||
config
|
||||
.save_to_file(None)
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::config::{persistence::pathfinder::MixNodePathfinder, Config};
|
||||
use crate::node::MixNode;
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::encryption;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
|
||||
pub fn command_args<'a, 'b>() -> App<'a, 'b> {
|
||||
App::new("run")
|
||||
@@ -95,6 +95,19 @@ fn special_addresses() -> Vec<&'static str> {
|
||||
vec!["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]
|
||||
}
|
||||
|
||||
fn load_identity_keys(pathfinder: &MixNodePathfinder) -> identity::KeyPair {
|
||||
let identity_keypair: identity::KeyPair = pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_identity_key().to_owned(),
|
||||
pathfinder.public_identity_key().to_owned(),
|
||||
))
|
||||
.expect("Failed to read stored identity key files");
|
||||
println!(
|
||||
"Public identity key: {}\n",
|
||||
identity_keypair.public_key().to_base58_string()
|
||||
);
|
||||
identity_keypair
|
||||
}
|
||||
|
||||
fn load_sphinx_keys(pathfinder: &MixNodePathfinder) -> encryption::KeyPair {
|
||||
let sphinx_keypair: encryption::KeyPair = pemstore::load_keypair(&pemstore::KeyPairPath::new(
|
||||
pathfinder.private_encryption_key().to_owned(),
|
||||
@@ -120,6 +133,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
config = override_config(config, matches);
|
||||
|
||||
let pathfinder = MixNodePathfinder::new_from_config(&config);
|
||||
let identity_keypair = load_identity_keys(&pathfinder);
|
||||
let sphinx_keypair = load_sphinx_keys(&pathfinder);
|
||||
|
||||
let listening_ip_string = config.get_listening_address().ip().to_string();
|
||||
@@ -145,5 +159,5 @@ pub fn execute(matches: &ArgMatches) {
|
||||
config.get_announce_address()
|
||||
);
|
||||
|
||||
MixNode::new(config, sphinx_keypair).run();
|
||||
MixNode::new(config, identity_keypair, sphinx_keypair).run();
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::config::{Config, MISSING_VALUE};
|
||||
use crate::config::{missing_string_value, Config};
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use config::NymConfig;
|
||||
use crypto::asymmetric::identity;
|
||||
use std::fmt::Display;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use version_checker::{parse_version, Version};
|
||||
|
||||
@@ -41,6 +43,22 @@ fn print_successful_upgrade<D1: Display, D2: Display>(from: D1, to: D2) {
|
||||
}
|
||||
|
||||
fn pre_090_upgrade(from: &str, config: Config) -> Config {
|
||||
// note: current is guaranteed to not have any `build` information suffix (nor pre-release
|
||||
// information), as this was asserted at the beginning of this command)
|
||||
//
|
||||
// upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate
|
||||
// step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0)
|
||||
// this way we don't need to have all the crazy paths on how to upgrade from any version to any
|
||||
// other version. We just upgrade one minor version at a time.
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
let to_version = if current.major == 0 && current.minor == 9 {
|
||||
current
|
||||
} else {
|
||||
Version::new(0, 9, 0)
|
||||
};
|
||||
|
||||
print_start_upgrade(&from, &to_version);
|
||||
|
||||
// this is not extracted to separate function as you only have to manually pass version
|
||||
// if upgrading from pre090 version
|
||||
let from = match from.strip_prefix("v") {
|
||||
@@ -57,31 +75,41 @@ fn pre_090_upgrade(from: &str, config: Config) -> Config {
|
||||
if from_version.major == 0 && from_version.minor < 8 {
|
||||
// technically this could be implemented, but is there any point in that?
|
||||
eprintln!("upgrading node from before v0.8.0 is not supported. Please run `init` with new binary instead");
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
if (from_version.major == 0 && from_version.minor >= 9) || from_version.major >= 1 {
|
||||
eprintln!("self reported version is higher than 0.9.0. Those releases should have already contained version numbers in config! Make sure you provided correct version");
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1)
|
||||
}
|
||||
|
||||
// note: current is guaranteed to not have any `build` information suffix (nor pre-release
|
||||
// information), as this was asserted at the beginning of this command)
|
||||
//
|
||||
// upgrade to current (if it's a 0.9.X) or try to upgrade to 0.9.0 as an intermediate
|
||||
// step in future upgrades (so, for example, we might go 0.8.0 -> 0.9.0 -> 0.10.0)
|
||||
// this way we don't need to have all the crazy paths on how to upgrade from any version to any
|
||||
// other version. We just upgrade one minor version at a time.
|
||||
let current = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
let to_version = if current.major == 0 && current.minor == 9 {
|
||||
current
|
||||
} else {
|
||||
Version::new(0, 9, 0)
|
||||
};
|
||||
if config.get_private_identity_key_file() != missing_string_value::<PathBuf>()
|
||||
|| config.get_public_identity_key_file() != missing_string_value::<PathBuf>()
|
||||
{
|
||||
eprintln!("existing config seems to have specified identity keys which were only introduced in 0.9.0! Can't perform upgrade.");
|
||||
print_failed_upgrade(&from_version, &to_version);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
print_start_upgrade(&from_version, &to_version);
|
||||
let mut upgraded_config = config.with_custom_version(to_version.to_string().as_ref());
|
||||
|
||||
println!("Generating new identity...");
|
||||
let identity_keys = identity::KeyPair::new();
|
||||
upgraded_config.set_default_identity_keypair_paths();
|
||||
|
||||
if let Err(err) = pemstore::store_keypair(
|
||||
&identity_keys,
|
||||
&pemstore::KeyPairPath::new(
|
||||
upgraded_config.get_private_identity_key_file(),
|
||||
upgraded_config.get_public_identity_key_file(),
|
||||
),
|
||||
) {
|
||||
eprintln!("Failed to save new identity key files! - {}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let upgraded_config = config.with_custom_version(to_version.to_string().as_ref());
|
||||
// TODO: THIS IS INCOMPLETE AS ONCE PRESENCE IS REMOVED IN 0.9.0 IT WILL ALSO NEED
|
||||
// TO BE PURGED FROM CONFIG
|
||||
|
||||
@@ -135,7 +163,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
});
|
||||
|
||||
// versions fields were added in 0.9.0
|
||||
if existing_config.get_version() == MISSING_VALUE {
|
||||
if existing_config.get_version() == missing_string_value::<String>() {
|
||||
let self_reported_version = matches.value_of("current version").unwrap_or_else(|| {
|
||||
eprintln!(
|
||||
"trying to upgrade from pre v0.9.0 without providing current system version!"
|
||||
|
||||
@@ -86,8 +86,8 @@ impl NymConfig for Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn missing_string_value() -> String {
|
||||
MISSING_VALUE.to_string()
|
||||
pub fn missing_string_value<T: From<String>>() -> T {
|
||||
MISSING_VALUE.to_string().into()
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -98,6 +98,20 @@ impl Config {
|
||||
// builder methods
|
||||
pub fn with_id<S: Into<String>>(mut self, id: S) -> Self {
|
||||
let id = id.into();
|
||||
if self
|
||||
.mixnode
|
||||
.private_identity_key_file
|
||||
.as_os_str()
|
||||
.is_empty()
|
||||
{
|
||||
self.mixnode.private_identity_key_file =
|
||||
self::MixNode::default_private_identity_key_file(&id);
|
||||
}
|
||||
if self.mixnode.public_identity_key_file.as_os_str().is_empty() {
|
||||
self.mixnode.public_identity_key_file =
|
||||
self::MixNode::default_public_identity_key_file(&id);
|
||||
}
|
||||
|
||||
if self.mixnode.private_sphinx_key_file.as_os_str().is_empty() {
|
||||
self.mixnode.private_sphinx_key_file =
|
||||
self::MixNode::default_private_sphinx_key_file(&id);
|
||||
@@ -106,6 +120,7 @@ impl Config {
|
||||
self.mixnode.public_sphinx_key_file =
|
||||
self::MixNode::default_public_sphinx_key_file(&id);
|
||||
}
|
||||
|
||||
self.mixnode.id = id;
|
||||
self
|
||||
}
|
||||
@@ -218,6 +233,14 @@ impl Config {
|
||||
self.mixnode.location.clone()
|
||||
}
|
||||
|
||||
pub fn get_private_identity_key_file(&self) -> PathBuf {
|
||||
self.mixnode.private_identity_key_file.clone()
|
||||
}
|
||||
|
||||
pub fn get_public_identity_key_file(&self) -> PathBuf {
|
||||
self.mixnode.public_identity_key_file.clone()
|
||||
}
|
||||
|
||||
pub fn get_private_sphinx_key_file(&self) -> PathBuf {
|
||||
self.mixnode.private_sphinx_key_file.clone()
|
||||
}
|
||||
@@ -277,6 +300,14 @@ impl Config {
|
||||
pub fn get_version(&self) -> &str {
|
||||
&self.mixnode.version
|
||||
}
|
||||
|
||||
// upgrade-specific
|
||||
pub(crate) fn set_default_identity_keypair_paths(&mut self) {
|
||||
self.mixnode.private_identity_key_file =
|
||||
self::MixNode::default_private_identity_key_file(&self.mixnode.id);
|
||||
self.mixnode.public_identity_key_file =
|
||||
self::MixNode::default_public_identity_key_file(&self.mixnode.id);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
@@ -309,6 +340,14 @@ pub struct MixNode {
|
||||
/// `listening_address`.
|
||||
announce_address: String,
|
||||
|
||||
/// Path to file containing private identity key.
|
||||
#[serde(default = "missing_string_value")]
|
||||
private_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing public identity key.
|
||||
#[serde(default = "missing_string_value")]
|
||||
public_identity_key_file: PathBuf,
|
||||
|
||||
/// Path to file containing private sphinx key.
|
||||
private_sphinx_key_file: PathBuf,
|
||||
|
||||
@@ -329,6 +368,14 @@ pub struct MixNode {
|
||||
}
|
||||
|
||||
impl MixNode {
|
||||
fn default_private_identity_key_file(id: &str) -> PathBuf {
|
||||
Config::default_data_directory(Some(id)).join("private_identity.pem")
|
||||
}
|
||||
|
||||
fn default_public_identity_key_file(id: &str) -> PathBuf {
|
||||
Config::default_data_directory(Some(id)).join("public_identity.pem")
|
||||
}
|
||||
|
||||
fn default_private_sphinx_key_file(id: &str) -> PathBuf {
|
||||
Config::default_data_directory(Some(id)).join("private_sphinx.pem")
|
||||
}
|
||||
@@ -353,6 +400,8 @@ impl Default for MixNode {
|
||||
.parse()
|
||||
.unwrap(),
|
||||
announce_address: format!("127.0.0.1:{}", DEFAULT_LISTENING_PORT),
|
||||
private_identity_key_file: Default::default(),
|
||||
public_identity_key_file: Default::default(),
|
||||
private_sphinx_key_file: Default::default(),
|
||||
public_sphinx_key_file: Default::default(),
|
||||
presence_directory_server: DEFAULT_DIRECTORY_SERVER.to_string(),
|
||||
|
||||
@@ -17,7 +17,8 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MixNodePathfinder {
|
||||
config_dir: PathBuf,
|
||||
identity_private_key: PathBuf,
|
||||
identity_public_key: PathBuf,
|
||||
private_sphinx_key: PathBuf,
|
||||
public_sphinx_key: PathBuf,
|
||||
}
|
||||
@@ -25,12 +26,21 @@ pub struct MixNodePathfinder {
|
||||
impl MixNodePathfinder {
|
||||
pub fn new_from_config(config: &Config) -> Self {
|
||||
MixNodePathfinder {
|
||||
config_dir: config.get_config_file_save_location(),
|
||||
identity_private_key: config.get_private_identity_key_file(),
|
||||
identity_public_key: config.get_public_identity_key_file(),
|
||||
private_sphinx_key: config.get_private_sphinx_key_file(),
|
||||
public_sphinx_key: config.get_public_sphinx_key_file(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn private_identity_key(&self) -> &Path {
|
||||
&self.identity_private_key
|
||||
}
|
||||
|
||||
pub fn public_identity_key(&self) -> &Path {
|
||||
&self.identity_public_key
|
||||
}
|
||||
|
||||
pub fn private_encryption_key(&self) -> &Path {
|
||||
&self.private_sphinx_key
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ layer = {{ mixnode.layer }}
|
||||
# Socket address to which this mixnode will bind to and will be listening for packets.
|
||||
listening_address = '{{ mixnode.listening_address }}'
|
||||
|
||||
# Path to file containing private identity key.
|
||||
private_identity_key_file = '{{ mixnode.private_identity_key_file }}'
|
||||
|
||||
# Path to file containing public identity key.
|
||||
public_identity_key_file = '{{ mixnode.public_identity_key_file }}'
|
||||
|
||||
# Path to file containing private identity key.
|
||||
private_sphinx_key_file = '{{ mixnode.private_sphinx_key_file }}'
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::config::Config;
|
||||
use crate::node::listener::connection_handler::packet_processing::PacketProcessor;
|
||||
use crate::node::listener::connection_handler::ConnectionHandler;
|
||||
use crate::node::listener::Listener;
|
||||
use crypto::asymmetric::encryption;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use directory_client::DirectoryClient;
|
||||
use log::*;
|
||||
use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
|
||||
@@ -30,13 +30,20 @@ mod presence;
|
||||
// the MixNode will live for whole duration of this program
|
||||
pub struct MixNode {
|
||||
config: Config,
|
||||
#[allow(dead_code)]
|
||||
identity_keypair: Arc<identity::KeyPair>,
|
||||
sphinx_keypair: Arc<encryption::KeyPair>,
|
||||
}
|
||||
|
||||
impl MixNode {
|
||||
pub fn new(config: Config, sphinx_keypair: encryption::KeyPair) -> Self {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
identity_keypair: identity::KeyPair,
|
||||
sphinx_keypair: encryption::KeyPair,
|
||||
) -> Self {
|
||||
MixNode {
|
||||
config,
|
||||
identity_keypair: Arc::new(identity_keypair),
|
||||
sphinx_keypair: Arc::new(sphinx_keypair),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user