Commit 6e25530d authored by inso's avatar inso Committed by Éloïs

Wizard Key with structopts

Run cargo fmt
parent 43b0a3d5
......@@ -276,6 +276,7 @@ dependencies = [
"duniter-module 0.1.0-a0.1",
"dup-crypto 0.5.0",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -920,8 +921,69 @@ dependencies = [
]
[[package]]
<<<<<<< HEAD
name = "rust-crypto-wasm"
version = "0.3.1"
=======
name = "regex"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rpassword"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
"rprompt 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rprompt"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rust-crypto"
version = "0.2.36"
>>>>>>> 80f6f56... Wizard Key with structopts
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -1340,8 +1402,19 @@ dependencies = [
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
<<<<<<< HEAD
"checksum rust-crypto-wasm 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9dcf11edbc9a0effb4a99ddbe909dd26fb2e71459064879218c27b0add1cb6ec"
"checksum rustbreak 2.0.0-rc3 (registry+https://github.com/rust-lang/crates.io-index)" = "b1c185a2ede13fcb28feb6864ee9412a20f57bd83b4be18dc81fde4d6e786982"
=======
"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
"checksum regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c93d55961981ba9226a213b385216f83ab43bd6ac53ab16b2eeb47e337cf4e"
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
"checksum regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05b06a75f5217880fc5e905952a42750bf44787e56a6c6d6852ed0992f5e1d54"
"checksum rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b273c91bd242ca03ad6d71c143b6f17a48790e61f21a6c78568fa2b6774a24a4"
"checksum rprompt 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1601f32bc5858aae3cbfa1c645c96c4d820cc5c16be0194f089560c00b6eb625"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustbreak 2.0.0-rc2 (registry+https://github.com/rust-lang/crates.io-index)" = "676cb04876f4391d5d2f2c9029d10cfe5fe28ad625ad8460531bed1191477083"
>>>>>>> 80f6f56... Wizard Key with structopts
"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
......
......@@ -16,6 +16,7 @@ serde_json = "1.0.*"
dirs = "1.0.2"
dup-crypto = { path = "../crypto" }
dubp-documents= { path = "../documents" }
rpassword = "1.0.0"
duniter-module = { path = "../module" }
[features]
......
// Copyright (C) 2018 The Duniter Project Developers.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Defined the few global types used by all modules,
//! as well as the DuniterModule trait that all modules must implement.
#![cfg_attr(feature = "strict", deny(warnings))]
#![deny(
missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
unused_qualifications
)]
extern crate rpassword;
use std::io;
use *;
#[derive(Debug, Copy, Clone)]
/// Errors encountered by the wizard
pub enum WizardError {
/// Canceled
Canceled,
/// Bad input
BadInput,
}
impl From<std::io::Error> for WizardError {
fn from(_e: std::io::Error) -> Self {
WizardError::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(salt.as_bytes(), password.as_bytes()));
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(salt.as_bytes(), password.as_bytes()),
));
key_pairs
}
/// Clear keys command
pub fn clear_keys(network: bool, member: bool, mut key_pairs: DuniterKeyPairs) -> DuniterKeyPairs {
if network {
key_pairs.network_keypair = generate_random_keypair(KeysAlgo::Ed25519);
}
if member {
key_pairs.member_keypair = None;
}
key_pairs
}
/// Show keys command
pub fn show_keys(key_pairs: DuniterKeyPairs) {
println!("Network key : {}", key_pairs.network_keypair);
match key_pairs.member_keypair {
None => println!("No member key configured"),
Some(key) => println!("Member key : {}", key),
}
}
/// Save keys after a command run
pub fn save_keypairs(profile: &str, key_pairs: DuniterKeyPairs) {
let conf_keys_path = keypairs_filepath(profile);
write_keypairs_file(&conf_keys_path, &key_pairs).expect("could not write keypairs file");
}
fn question_prompt(question: &str, answers: Vec<String>) -> Result<String, WizardError> {
let mut buf = String::new();
println!("{} ({}) :", question, answers.join("/"));
let res = io::stdin().read_line(&mut buf);
match res {
Ok(_) => {
let answer = answers.into_iter().find(|x| x == buf.trim());
match answer {
Some(value) => Ok(value),
None => Err(WizardError::Canceled),
}
}
Err(_) => Err(WizardError::Canceled),
}
}
fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> {
let salt = rpassword::prompt_password_stdout("? Salt: ")?;
if !salt.is_empty() {
let password = rpassword::prompt_password_stdout("? Password: ")?;
if !password.is_empty() {
let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters();
let key_pairs = KeyPairEnum::Ed25519(generator.generate(
salt.into_bytes().as_slice(),
password.into_bytes().as_slice(),
));
Ok(key_pairs)
} else {
Err(WizardError::BadInput)
}
} else {
Err(WizardError::BadInput)
}
}
/// The wizard key function
pub fn key_wizard(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, WizardError> {
let mut answer = question_prompt(
"? Modify your network keypair?",
vec!["y".to_string(), "n".to_string()],
)?;
if answer == "y" {
key_pairs.network_keypair = salt_password_prompt()?;
}
answer = question_prompt(
"? Modify your member keypair?",
vec!["y".to_string(), "n".to_string(), "d".to_string()],
)?;
if answer == "y" {
key_pairs.member_keypair = Some(salt_password_prompt()?);
} else if answer == "d" {
println!("Deleting member keypair !");
key_pairs.member_keypair = None;
}
Ok(key_pairs)
}
......@@ -40,7 +40,12 @@ extern crate duniter_module;
extern crate dup_crypto;
extern crate rand;
extern crate serde;
pub mod keys;
use dubp_documents::CurrencyName;
use duniter_crypto::keys::*;
use duniter_documents::CurrencyName;
use duniter_module::{DuniterConf, ModuleName, RequiredKeys, RequiredKeysContent};
use dup_crypto::keys::*;
use rand::Rng;
......@@ -56,6 +61,9 @@ static USER_DATAS_FOLDER: &'static str = "durs-dev";
/// If no currency is specified by the user, is the currency will be chosen by default
pub static DEFAULT_CURRRENCY: &'static str = "g1";
/// Keypairs filename
pub static KEYPAIRS_FILENAME: &'static str = "keypairs.json";
#[derive(Debug, Clone)]
/// User request on global conf
pub enum ChangeGlobalConf {
......@@ -315,6 +323,14 @@ pub fn get_profile_path(profile: &str) -> PathBuf {
profile_path
}
/// Get keypairs file path
pub fn keypairs_filepath(profile: &str) -> PathBuf {
let profile_path = get_profile_path(profile);
let mut conf_keys_path = profile_path.clone();
conf_keys_path.push(KEYPAIRS_FILENAME);
conf_keys_path
}
/// Load configuration.
pub fn load_conf(profile: &str) -> (DuRsConf, DuniterKeyPairs) {
let mut profile_path = get_profile_path(profile);
......@@ -336,7 +352,7 @@ pub fn load_conf(profile: &str) -> (DuRsConf, DuniterKeyPairs) {
pub fn load_conf_at_path(profile: &str, profile_path: &PathBuf) -> (DuRsConf, DuniterKeyPairs) {
// Get KeyPairs
let mut keypairs_path = profile_path.clone();
keypairs_path.push("keypairs.json");
keypairs_path.push(KEYPAIRS_FILENAME);
let keypairs = if keypairs_path.as_path().exists() {
if let Ok(mut f) = File::open(keypairs_path.as_path()) {
let mut contents = String::new();
......
// Copyright (C) 2018 The Duniter Project Developers.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Durs-core cli : dbex subcommands.
extern crate structopt;
#[derive(StructOpt, Debug, Clone)]
#[structopt(
name = "keys",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
/// durs databases explorer
pub struct KeysOpt {
#[structopt(subcommand)]
/// KeysSubCommand
pub subcommand: KeysSubCommand,
}
#[derive(StructOpt, Debug, Clone)]
/// keys subcommands
pub enum KeysSubCommand {
/// modify durs keys
#[structopt(
name = "modify",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
Modify(ModifyOpt),
/// clear durs keys
#[structopt(
name = "clear",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
Clear(ClearOpt),
/// show durs keys
#[structopt(
name = "show",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
Show(ShowOpt),
#[structopt(
name = "wizard",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
/// wizard to help user generate durs keys
Wizard(WizardOpt),
}
#[derive(StructOpt, Debug, Clone)]
/// ModifyOpt
pub struct ModifyOpt {
#[structopt(subcommand)]
/// Modify sub commands
pub subcommand: ModifySubCommand,
}
#[derive(StructOpt, Debug, Clone)]
/// keys modify subcommands
pub enum ModifySubCommand {
#[structopt(
name = "member",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
/// Salt and password of member key
MemberSaltPassword(SaltPasswordOpt),
#[structopt(
name = "network",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
/// Salt and password of network key
NetworkSaltPassword(SaltPasswordOpt),
}
#[derive(StructOpt, Debug, Copy, Clone)]
/// ClearOpt
pub struct ClearOpt {
#[structopt(long = "member")]
/// True if we change member key
pub member: bool,
#[structopt(long = "network")]
/// True if we change network key
pub network: bool,
#[structopt(long = "all")]
/// True if we change member and network key
pub all: bool,
}
#[derive(StructOpt, Debug, Clone)]
/// SaltPasswordOpt
pub struct SaltPasswordOpt {
#[structopt(long = "salt", required = true)]
/// Salt of key generator
pub salt: String,
#[structopt(long = "password", required = true)]
/// Password of key generator
pub password: String,
}
#[derive(StructOpt, Debug, Copy, Clone)]
/// WizardOpt
pub struct WizardOpt {}
#[derive(StructOpt, Debug, Copy, Clone)]
/// ShowOpt
pub struct ShowOpt {}
......@@ -18,12 +18,15 @@
extern crate structopt;
pub mod dbex;
pub mod keys;
pub mod modules;
pub mod reset;
pub mod start;
pub mod sync;
use cli::keys::KeysOpt;
pub use dbex::*;
pub use keys::*;
use log::Level;
pub use modules::*;
pub use reset::*;
......@@ -82,6 +85,12 @@ pub enum CoreSubCommand {
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
DbExOpt(DbExOpt),
/// keys operations
#[structopt(
name = "keys",
raw(setting = "structopt::clap::AppSettings::ColoredHelp")
)]
KeysOpt(KeysOpt),
}
/// InvalidInput
......
......@@ -51,7 +51,7 @@ pub mod cli;
pub mod router;
use duniter_blockchain::{BlockchainModule, DBExQuery, DBExTxQuery, DBExWotQuery};
pub use duniter_conf::{ChangeGlobalConf, DuRsConf, DuniterKeyPairs};
pub use duniter_conf::{ChangeGlobalConf, DuRsConf, DuniterKeyPairs, KEYPAIRS_FILENAME};
use duniter_message::*;
use duniter_module::*;
use duniter_network::{NetworkModule, SyncEndpoint, SyncParams};
......@@ -59,7 +59,9 @@ use log::Level;
use simplelog::*;
//use std::error::Error;
//use std::fmt::{Debug, Formatter};
use cli::keys::*;
use cli::*;
use duniter_conf::keys;
use std::fs;
use std::fs::{File, OpenOptions};
use std::sync::mpsc;
......@@ -396,7 +398,7 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> {
conf_file_path.push("conf.json");
fs::remove_file(conf_file_path.as_path()).expect("Fail to remove conf file !");
let mut conf_keys_path = profile_path.clone();
conf_keys_path.push("keypairs.json");
conf_keys_path.push(KEYPAIRS_FILENAME);
fs::remove_file(conf_keys_path.as_path())
.expect("Fail to remove keypairs file !");
}
......@@ -406,6 +408,38 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> {
}
}
false
} else if let Some(matches) = cli_args.subcommand_matches("keys") {
let opts = KeysOpt::from_clap(matches);
match opts.subcommand {
KeysSubCommand::Wizard(_wizardopt) => {
let new_keypairs = key_wizard(keypairs).unwrap();
save_keypairs(profile.as_str(), new_keypairs);
}
KeysSubCommand::Modify(modifyopt) => match modifyopt.subcommand {
ModifySubCommand::NetworkSaltPassword(networkopt) => {
let new_keypairs =
modify_network_keys(networkopt.salt, networkopt.password, keypairs);
save_keypairs(profile.as_str(), new_keypairs);
}
ModifySubCommand::MemberSaltPassword(memberopt) => {
let new_keypairs =
modify_member_keys(memberopt.salt, memberopt.password, keypairs);
save_keypairs(profile.as_str(), new_keypairs);
}
},
KeysSubCommand::Clear(clearopt) => {
let new_keypairs = clear_keys(
clearopt.network || clearopt.all,
clearopt.member || clearopt.all,
keypairs,
);
save_keypairs(profile.as_str(), new_keypairs);
}
KeysSubCommand::Show(_showopt) => {
show_keys(keypairs);
}
}
false
} else if let Some(unknow_subcommand) = cli_args.subcommand_name() {
let mut module_subcommand = true;
if let Some(sup_apps_fn) = sup_apps_fn {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment