Skip to content
Snippets Groups Projects

Resolve "cli: keys modify: ask salt and password on password prompt for security"

Files
8
@@ -31,8 +31,8 @@ use crate::*;
use std::io;
#[derive(Debug, Copy, Clone)]
/// Errors encountered by the wizard
pub enum WizardError {
/// Errors encountered by the user interaction
pub enum CLIError {
/// Canceled
Canceled,
@@ -40,35 +40,22 @@ pub enum WizardError {
BadInput,
}
impl From<std::io::Error> for WizardError {
impl From<std::io::Error> for CLIError {
fn from(_e: std::io::Error) -> Self {
WizardError::BadInput
CLIError::BadInput
}
}
/// Modify network keys command
pub fn modify_network_keys(
salt: String,
password: String,
mut key_pairs: DuniterKeyPairs,
) -> DuniterKeyPairs {
let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters();
key_pairs.network_keypair =
KeyPairEnum::Ed25519(generator.generate(ed25519::SaltedPassword::new(salt, password)));
key_pairs
pub fn modify_network_keys(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, CLIError> {
key_pairs.network_keypair = salt_password_prompt()?;
Ok(key_pairs)
}
/// Modify member keys command
pub fn modify_member_keys(
salt: String,
password: String,
mut key_pairs: DuniterKeyPairs,
) -> DuniterKeyPairs {
let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters();
key_pairs.member_keypair = Some(KeyPairEnum::Ed25519(
generator.generate(ed25519::SaltedPassword::new(salt, password)),
));
key_pairs
pub fn modify_member_keys(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, CLIError> {
key_pairs.member_keypair = Some(salt_password_prompt()?);
Ok(key_pairs)
}
/// Ask user for confirmation and Clear keys command
@@ -126,7 +113,7 @@ pub fn show_keys(key_pairs: DuniterKeyPairs) {
pub fn save_keypairs(
profile_path: PathBuf,
keypairs_file_path: &Option<PathBuf>,
key_pairs: DuniterKeyPairs,
key_pairs: &DuniterKeyPairs,
) -> Result<(), std::io::Error> {
let conf_keys_path: PathBuf = if let Some(keypairs_file_path) = keypairs_file_path {
keypairs_file_path.to_path_buf()
@@ -139,7 +126,7 @@ pub fn save_keypairs(
Ok(())
}
fn question_prompt<'a>(question: &str, answers: &[&'a str]) -> Result<&'a str, WizardError> {
fn question_prompt<'a>(question: &str, answers: &[&'a str]) -> Result<&'a str, CLIError> {
let mut buf = String::new();
println!("{} ({}):", question, answers.join("/"));
@@ -150,14 +137,14 @@ fn question_prompt<'a>(question: &str, answers: &[&'a str]) -> Result<&'a str, W
let answer = answers.iter().find(|x| **x == buf.trim());
match answer {
Some(&value) => Ok(value),
None => Err(WizardError::Canceled),
None => Err(CLIError::Canceled),
}
}
Err(_) => Err(WizardError::Canceled),
Err(_) => Err(CLIError::Canceled),
}
}
fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> {
fn salt_password_prompt() -> Result<KeyPairEnum, CLIError> {
let salt = rpassword::prompt_password_stdout("Salt: ")?;
if !salt.is_empty() {
let password = rpassword::prompt_password_stdout("Password: ")?;
@@ -168,15 +155,15 @@ fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> {
);
Ok(key_pairs)
} else {
Err(WizardError::BadInput)
Err(CLIError::BadInput)
}
} else {
Err(WizardError::BadInput)
Err(CLIError::BadInput)
}
}
/// The wizard key function
pub fn key_wizard(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, WizardError> {
pub fn key_wizard(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, CLIError> {
let mut answer = question_prompt("Modify your network keypair?", &["y", "n"])?;
if answer == "y" {
key_pairs.network_keypair = salt_password_prompt()?;
@@ -204,89 +191,6 @@ mod tests {
//static SALT_INIT: &'static str = "initsalt";
//static PASSWORD_INIT: &'static str = "initpassword";
static BASE58_SEED_TEST: &'static str = "ELjDWGPyCGMuhr7R7H2aip6UJA9qLRepmK77pcD41UqQ";
static BASE58_PUB_TEST: &'static str = "6sewkaNWyEMqkEa2PVRWrDb3hxWtjPdUSB1zXVCqhdWV";
static SALT_TEST: &'static str = "testsalt";
static PASSWORD_TEST: &'static str = "testpassword";
#[test]
fn test_modify_member_keys() {
let key_pairs = DuniterKeyPairs {
network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
seed: Seed32::from_base58(BASE58_SEED_INIT)
.expect("conf : keypairs file : fail to parse network_seed !"),
pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT)
.expect("conf : keypairs file : fail to parse network_pub !"),
}),
member_keypair: None,
};
let result_key_pairs =
modify_member_keys(SALT_TEST.to_owned(), PASSWORD_TEST.to_owned(), key_pairs);
// We expect network key not to change
assert_eq!(
result_key_pairs.network_keypair.public_key(),
PubKey::Ed25519(
ed25519::PublicKey::from_base58(BASE58_PUB_INIT)
.expect("Wrong data in BASE58_PUB_TEST")
)
);
assert_eq!(
result_key_pairs.network_keypair.seed().clone(),
Seed32::from_base58(BASE58_SEED_INIT).expect("Wrong data in BASE58_SEED_INIT"),
);
// We expect member key to update as intended
assert_eq!(
unwrap!(
result_key_pairs.member_keypair.clone(),
"conf: member_keypair must have a value"
)
.public_key(),
PubKey::Ed25519(unwrap!(
ed25519::PublicKey::from_base58(BASE58_PUB_TEST),
"Wrong data in BASE58_PUB_TEST"
))
);
assert_eq!(
result_key_pairs
.member_keypair
.clone()
.expect("conf: member_keypair must have a value")
.seed()
.clone(),
Seed32::from_base58(BASE58_SEED_TEST).expect("Wrong data in BASE58_SEED_TEST"),
);
}
#[test]
fn test_modify_network_keys() {
let key_pairs = DuniterKeyPairs {
network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
seed: Seed32::from_base58(BASE58_SEED_INIT)
.expect("conf : keypairs file : fail to parse network_seed !"),
pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT)
.expect("conf : keypairs file : fail to parse network_pub !"),
}),
member_keypair: None,
};
let result_key_pairs =
modify_network_keys(SALT_TEST.to_owned(), PASSWORD_TEST.to_owned(), key_pairs);
// We expect network key to update
assert_eq!(
result_key_pairs.network_keypair.public_key(),
PubKey::Ed25519(
ed25519::PublicKey::from_base58(BASE58_PUB_TEST)
.expect("Wrong data in BASE58_PUB_TEST")
)
);
assert_eq!(
result_key_pairs.network_keypair.seed().clone(),
Seed32::from_base58(BASE58_SEED_TEST).expect("Wrong data in BASE58_SEED_TEST")
);
// We expect member key not to change
assert_eq!(result_key_pairs.member_keypair, None);
}
#[test]
fn test_clear_network_keys() {
let key_pairs = DuniterKeyPairs {
Loading