From bcff3002e9cd0966eb7fc257a056f0abf70d2657 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 25 May 2022 18:55:18 +0200 Subject: [PATCH 1/6] Improve inspection and generation of node keys --- bin/utils/subkey/src/lib.rs | 6 +-- client/cli/src/commands/generate_node_key.rs | 34 ++++++++++---- client/cli/src/commands/inspect_node_key.rs | 49 +++++++++++++++----- 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/bin/utils/subkey/src/lib.rs b/bin/utils/subkey/src/lib.rs index 3731d9f3ec75c..893cc2a85f751 100644 --- a/bin/utils/subkey/src/lib.rs +++ b/bin/utils/subkey/src/lib.rs @@ -30,8 +30,8 @@ use sc_cli::{ version )] pub enum Subkey { - /// Generate a random node libp2p key, save it to file or print it to stdout - /// and print its peer ID to stderr. + /// Generate a random node key, write it to a file or stdout and write the corresponding + /// peer-id to stderr GenerateNodeKey(GenerateNodeKeyCmd), /// Generate a random account @@ -40,7 +40,7 @@ pub enum Subkey { /// Gets a public key and a SS58 address from the provided Secret URI Inspect(InspectKeyCmd), - /// Print the peer ID corresponding to the node key in the given file + /// Load a node key from a file or stdin and print the corresponding peer-id InspectNodeKey(InspectNodeKeyCmd), /// Sign a message, with a given (secret) key. diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index 8c634dca9acf2..2eeca5b6590f8 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -20,14 +20,20 @@ use crate::Error; use clap::Parser; use libp2p::identity::{ed25519 as libp2p_ed25519, PublicKey}; -use std::{fs, path::PathBuf}; +use sp_core::hexdisplay::AsBytesRef; +use std::{ + borrow::Cow, + fs, + io::{self, Write}, + path::PathBuf, +}; /// The `generate-node-key` command #[derive(Debug, Parser)] #[clap( name = "generate-node-key", - about = "Generate a random node libp2p key, save it to \ - file or print it to stdout and print its peer ID to stderr" + about = "Generate a random node key, write it to a file or stdout + and write the corresponding peer-id to stderr" )] pub struct GenerateNodeKeyCmd { /// Name of file to save secret key to. @@ -35,22 +41,34 @@ pub struct GenerateNodeKeyCmd { /// If not given, the secret key is printed to stdout. #[clap(long)] file: Option, + + /// The output is in raw binary format. + /// + /// If not given, the output is written as an hex encoded string. + #[clap(long)] + bin: bool, } impl GenerateNodeKeyCmd { /// Run the command pub fn run(&self) -> Result<(), Error> { let keypair = libp2p_ed25519::Keypair::generate(); + let secret = keypair.secret(); - let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); - let secret_hex = hex::encode(secret.as_ref()); + + let file_data = if self.bin { + Cow::Borrowed(secret.as_ref()) + } else { + Cow::Owned(hex::encode(secret.as_ref()).into_bytes()) + }; match &self.file { - Some(file) => fs::write(file, secret_hex)?, - None => print!("{}", secret_hex), + Some(file) => fs::write(file, file_data)?, + None => io::stdout().write_all(file_data.as_bytes_ref())?, } - eprintln!("{}", peer_id); + let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); + eprintln!("Peer-ID: {}", peer_id); Ok(()) } diff --git a/client/cli/src/commands/inspect_node_key.rs b/client/cli/src/commands/inspect_node_key.rs index 4c0798cc0635c..38cfd6bcebf07 100644 --- a/client/cli/src/commands/inspect_node_key.rs +++ b/client/cli/src/commands/inspect_node_key.rs @@ -17,39 +17,64 @@ //! Implementation of the `inspect-node-key` subcommand -use crate::{Error, NetworkSchemeFlag}; +use crate::Error; use clap::Parser; use libp2p::identity::{ed25519, PublicKey}; -use std::{fs, path::PathBuf}; +use std::{ + fs, + io::{self, Read}, + path::PathBuf, +}; /// The `inspect-node-key` command #[derive(Debug, Parser)] #[clap( name = "inspect-node-key", - about = "Print the peer ID corresponding to the node key in the given file." + about = "Load a node key from a file or stdin and print the corresponding peer-id." )] pub struct InspectNodeKeyCmd { /// Name of file to read the secret key from. + /// + /// If not given, the secret key is read from stdin (up to EOF). #[clap(long)] - file: PathBuf, + file: Option, - #[allow(missing_docs)] - #[clap(flatten)] - pub network_scheme: NetworkSchemeFlag, + /// The input is in raw binary format. + /// + /// If not given, the input is read as an hex encoded string. + #[clap(long)] + bin: bool, } impl InspectNodeKeyCmd { /// runs the command pub fn run(&self) -> Result<(), Error> { - let mut file_content = - hex::decode(fs::read(&self.file)?).map_err(|_| "failed to decode secret as hex")?; + let mut file_data = match &self.file { + Some(file) => fs::read(&file)?, + None => { + let mut buf = Vec::with_capacity(64); + io::stdin().lock().read_to_end(&mut buf)?; + buf + }, + }; + + if !self.bin { + // With hex input, give to the user a bit of tolerance about whitespaces + let is_not_ascii_whitespace = |c: &u8| !c.is_ascii_whitespace(); + let beg = file_data.iter().position(is_not_ascii_whitespace).unwrap_or_default(); + let end = + file_data.iter().rposition(is_not_ascii_whitespace).unwrap_or(file_data.len()) + 1; + file_data = + hex::decode(&file_data[beg..end]).map_err(|_| "failed to decode secret as hex")?; + } + let secret = - ed25519::SecretKey::from_bytes(&mut file_content).map_err(|_| "Bad node key file")?; + ed25519::SecretKey::from_bytes(&mut file_data).map_err(|_| "Bad node key file")?; let keypair = ed25519::Keypair::from(secret); - let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); - println!("{}", peer_id); + let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); + println!("Peer-ID: {}", peer_id); Ok(()) } From 760d416d06cb367a633d220f27784b9a6cb74c22 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 25 May 2022 19:41:55 +0200 Subject: [PATCH 2/6] Lock stdout before write --- client/cli/src/commands/generate_node_key.rs | 6 +++--- client/cli/src/commands/key.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index 2eeca5b6590f8..ec1bf40e74e91 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -32,8 +32,8 @@ use std::{ #[derive(Debug, Parser)] #[clap( name = "generate-node-key", - about = "Generate a random node key, write it to a file or stdout - and write the corresponding peer-id to stderr" + about = "Generate a random node key, write it to a file or stdout \ + and write the corresponding peer-id to stderr" )] pub struct GenerateNodeKeyCmd { /// Name of file to save secret key to. @@ -64,7 +64,7 @@ impl GenerateNodeKeyCmd { match &self.file { Some(file) => fs::write(file, file_data)?, - None => io::stdout().write_all(file_data.as_bytes_ref())?, + None => io::stdout().lock().write_all(file_data.as_bytes_ref())?, } let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); diff --git a/client/cli/src/commands/key.rs b/client/cli/src/commands/key.rs index e0f3524196e2c..59cca554bfa37 100644 --- a/client/cli/src/commands/key.rs +++ b/client/cli/src/commands/key.rs @@ -26,8 +26,8 @@ use crate::{Error, SubstrateCli}; /// Key utilities for the cli. #[derive(Debug, clap::Subcommand)] pub enum KeySubcommand { - /// Generate a random node libp2p key, save it to file or print it to stdout - /// and print its peer ID to stderr. + /// Generate a random node key, write it to a file or stdout and write the + /// corresponding peer-id to stderr GenerateNodeKey(GenerateNodeKeyCmd), /// Generate a random account @@ -36,7 +36,7 @@ pub enum KeySubcommand { /// Gets a public key and a SS58 address from the provided Secret URI Inspect(InspectKeyCmd), - /// Print the peer ID corresponding to the node key in the given file + /// Load a node key from a file or stdin and print the corresponding peer-id InspectNodeKey(InspectNodeKeyCmd), /// Insert a key to the keystore of a node. From ac37b8640ac9797a1a4a0e34626b0723a5c84386 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 25 May 2022 19:45:09 +0200 Subject: [PATCH 3/6] Fix typo --- bin/utils/subkey/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/utils/subkey/src/lib.rs b/bin/utils/subkey/src/lib.rs index 893cc2a85f751..6773ba822340f 100644 --- a/bin/utils/subkey/src/lib.rs +++ b/bin/utils/subkey/src/lib.rs @@ -30,8 +30,8 @@ use sc_cli::{ version )] pub enum Subkey { - /// Generate a random node key, write it to a file or stdout and write the corresponding - /// peer-id to stderr + /// Generate a random node key, write it to a file or stdout and write the + /// corresponding peer-id to stderr GenerateNodeKey(GenerateNodeKeyCmd), /// Generate a random account From 77641df8f4851c0f7e05d3575e62957a628b7ab8 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 25 May 2022 20:16:41 +0200 Subject: [PATCH 4/6] Fix offset --- client/cli/src/commands/inspect_node_key.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/cli/src/commands/inspect_node_key.rs b/client/cli/src/commands/inspect_node_key.rs index 38cfd6bcebf07..14bd822a5f21b 100644 --- a/client/cli/src/commands/inspect_node_key.rs +++ b/client/cli/src/commands/inspect_node_key.rs @@ -62,8 +62,11 @@ impl InspectNodeKeyCmd { // With hex input, give to the user a bit of tolerance about whitespaces let is_not_ascii_whitespace = |c: &u8| !c.is_ascii_whitespace(); let beg = file_data.iter().position(is_not_ascii_whitespace).unwrap_or_default(); - let end = - file_data.iter().rposition(is_not_ascii_whitespace).unwrap_or(file_data.len()) + 1; + let end = file_data + .iter() + .rposition(is_not_ascii_whitespace) + .map(|off| off + 1) + .unwrap_or_default(); file_data = hex::decode(&file_data[beg..end]).map_err(|_| "failed to decode secret as hex")?; } From 771ec59ab6f22595bf63adba13187baa11dfe341 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Fri, 27 May 2022 15:32:02 +0200 Subject: [PATCH 5/6] Remove useless code --- client/cli/src/commands/generate_node_key.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index ec1bf40e74e91..d8be7d2759be3 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -20,9 +20,7 @@ use crate::Error; use clap::Parser; use libp2p::identity::{ed25519 as libp2p_ed25519, PublicKey}; -use sp_core::hexdisplay::AsBytesRef; use std::{ - borrow::Cow, fs, io::{self, Write}, path::PathBuf, @@ -57,14 +55,14 @@ impl GenerateNodeKeyCmd { let secret = keypair.secret(); let file_data = if self.bin { - Cow::Borrowed(secret.as_ref()) + secret.as_ref().to_owned() } else { - Cow::Owned(hex::encode(secret.as_ref()).into_bytes()) + hex::encode(secret.as_ref()).into_bytes() }; match &self.file { Some(file) => fs::write(file, file_data)?, - None => io::stdout().lock().write_all(file_data.as_bytes_ref())?, + None => io::stdout().lock().write_all(&file_data)?, } let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); From 3035165cc15f704cafa2bd7b2046d61bc621a9fa Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Fri, 27 May 2022 19:52:51 +0200 Subject: [PATCH 6/6] Set inspect-node-key 'network' option as obsolete --- client/cli/src/commands/generate_node_key.rs | 3 +-- client/cli/src/commands/inspect_node_key.rs | 19 ++++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/client/cli/src/commands/generate_node_key.rs b/client/cli/src/commands/generate_node_key.rs index d8be7d2759be3..6b2f12531458c 100644 --- a/client/cli/src/commands/generate_node_key.rs +++ b/client/cli/src/commands/generate_node_key.rs @@ -65,8 +65,7 @@ impl GenerateNodeKeyCmd { None => io::stdout().lock().write_all(&file_data)?, } - let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); - eprintln!("Peer-ID: {}", peer_id); + eprintln!("{}", PublicKey::Ed25519(keypair.public()).to_peer_id()); Ok(()) } diff --git a/client/cli/src/commands/inspect_node_key.rs b/client/cli/src/commands/inspect_node_key.rs index 14bd822a5f21b..e1617c1d085df 100644 --- a/client/cli/src/commands/inspect_node_key.rs +++ b/client/cli/src/commands/inspect_node_key.rs @@ -44,6 +44,11 @@ pub struct InspectNodeKeyCmd { /// If not given, the input is read as an hex encoded string. #[clap(long)] bin: bool, + + /// This argument is deprecated and has no effect for this command. + #[deprecated(note = "Network identifier is not used for node-key inspection")] + #[clap(short = 'n', long = "network", value_name = "NETWORK", ignore_case = true)] + pub network_scheme: Option, } impl InspectNodeKeyCmd { @@ -60,15 +65,8 @@ impl InspectNodeKeyCmd { if !self.bin { // With hex input, give to the user a bit of tolerance about whitespaces - let is_not_ascii_whitespace = |c: &u8| !c.is_ascii_whitespace(); - let beg = file_data.iter().position(is_not_ascii_whitespace).unwrap_or_default(); - let end = file_data - .iter() - .rposition(is_not_ascii_whitespace) - .map(|off| off + 1) - .unwrap_or_default(); - file_data = - hex::decode(&file_data[beg..end]).map_err(|_| "failed to decode secret as hex")?; + let keyhex = String::from_utf8_lossy(&file_data); + file_data = hex::decode(keyhex.trim()).map_err(|_| "failed to decode secret as hex")?; } let secret = @@ -76,8 +74,7 @@ impl InspectNodeKeyCmd { let keypair = ed25519::Keypair::from(secret); - let peer_id = PublicKey::Ed25519(keypair.public()).to_peer_id(); - println!("Peer-ID: {}", peer_id); + println!("{}", PublicKey::Ed25519(keypair.public()).to_peer_id()); Ok(()) }