diff --git a/Cargo.lock b/Cargo.lock index 0720e76..c8cbc45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -508,7 +508,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.11.7" +version = "1.11.8" dependencies = [ "aes-gcm-stream", "authenticator 0.3.1", diff --git a/Cargo.toml b/Cargo.toml index 07f73a9..07db150 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.11.7" +version = "1.11.8" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_keypair_generate.rs b/src/cmd_keypair_generate.rs index 17ddb7c..716fb56 100644 --- a/src/cmd_keypair_generate.rs +++ b/src/cmd_keypair_generate.rs @@ -33,12 +33,6 @@ impl Command for CommandImpl { .takes_value(true) .help("Key chain name"), ) - .arg( - Arg::with_name("import-key-value") - .long("import-key-value") - .takes_value(true) - .help("Import key value"), - ) .arg(Arg::with_name("json").long("json").help("JSON output")) } @@ -46,26 +40,12 @@ impl Command for CommandImpl { let with_hmac_encrypt = sub_arg_matches.is_present("with-hmac-encrypt"); let key_type = sub_arg_matches.value_of("type").unwrap().to_lowercase(); let keychain_name = sub_arg_matches.value_of("keychain-name"); - let import_key_value = sub_arg_matches.value_of("import-key-value"); if let Some(keychain_name) = keychain_name { let keychain_key = KeychainKey::from_key_name_default(keychain_name); - if let Some(keychain_key_value_bytes) = keychain_key.get_password()? { - let keychain_key_value: KeychainKeyValue = - serde_json::from_slice(&keychain_key_value_bytes)?; - util_msg::set_logger_std_out(false); - information!("Keychain key URI: {}", keychain_key.to_key_uri()); - println!( - "{}", - serde_json::to_string_pretty(&keychain_key_value).unwrap() - ); + if let Some(_) = keychain_key.get_password()? { return simple_error!("Keychain key URI: {} exists", keychain_key.to_key_uri()); } - - if let Some(import_key_value) = import_key_value { - keychain_key.set_password(import_key_value.as_bytes())?; - return Ok(None); - } } let json_output = sub_arg_matches.is_present("json"); diff --git a/src/cmd_keypair_keychain_export.rs b/src/cmd_keypair_keychain_export.rs new file mode 100644 index 0000000..34bbcd7 --- /dev/null +++ b/src/cmd_keypair_keychain_export.rs @@ -0,0 +1,45 @@ +use crate::keychain::{KeychainKey, KeychainKeyValue}; +use clap::{App, Arg, ArgMatches, SubCommand}; +use rust_util::util_clap::{Command, CommandError}; +use rust_util::util_msg; + +pub struct CommandImpl; + +impl Command for CommandImpl { + fn name(&self) -> &str { + "keypair-keychain-export" + } + + fn subcommand<'a>(&self) -> App<'a, 'a> { + SubCommand::with_name(self.name()) + .about("Export software keypair from keychain") + .arg( + Arg::with_name("keychain-name") + .long("keychain-name") + .takes_value(true) + .help("Key chain name"), + ) + } + + fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { + let keychain_name = sub_arg_matches.value_of("keychain-name"); + + if let Some(keychain_name) = keychain_name { + let keychain_key = KeychainKey::from_key_name_default(keychain_name); + if let Some(keychain_key_value_bytes) = keychain_key.get_password()? { + let keychain_key_value: KeychainKeyValue = + serde_json::from_slice(&keychain_key_value_bytes)?; + util_msg::set_logger_std_out(false); + information!("Keychain key URI: {}", keychain_key.to_key_uri()); + println!( + "{}", + serde_json::to_string_pretty(&keychain_key_value).unwrap() + ); + } else { + return simple_error!("Keychain key URI: {} not found", keychain_key.to_key_uri()); + } + } + + Ok(None) + } +} diff --git a/src/cmd_keypair_keychain_import.rs b/src/cmd_keypair_keychain_import.rs new file mode 100644 index 0000000..a9076fa --- /dev/null +++ b/src/cmd_keypair_keychain_import.rs @@ -0,0 +1,46 @@ +use crate::keychain::KeychainKey; +use clap::{App, Arg, ArgMatches, SubCommand}; +use rust_util::util_clap::{Command, CommandError}; + +pub struct CommandImpl; + +impl Command for CommandImpl { + fn name(&self) -> &str { + "keypair-keychain-import" + } + + fn subcommand<'a>(&self) -> App<'a, 'a> { + SubCommand::with_name(self.name()) + .about("Import software keypair to keychain") + .arg( + Arg::with_name("keychain-name") + .long("keychain-name") + .takes_value(true) + .help("Key chain name"), + ) + .arg( + Arg::with_name("import-key-value") + .long("import-key-value") + .takes_value(true) + .help("Import key value"), + ) + } + + fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { + let keychain_name = sub_arg_matches.value_of("keychain-name"); + let import_key_value = sub_arg_matches.value_of("import-key-value"); + + if let Some(keychain_name) = keychain_name { + let keychain_key = KeychainKey::from_key_name_default(keychain_name); + if let Some(_) = keychain_key.get_password()? { + return simple_error!("Keychain key URI: {} exists", keychain_key.to_key_uri()); + } + + if let Some(import_key_value) = import_key_value { + keychain_key.set_password(import_key_value.as_bytes())?; + } + } + + Ok(None) + } +} diff --git a/src/main.rs b/src/main.rs index 1c34e62..e6e9a0f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,6 +53,8 @@ mod cmd_u2f_sign; mod cmd_file_verify; mod cmd_parseecdsasignature; mod cmd_keypair_generate; +mod cmd_keypair_keychain_import; +mod cmd_keypair_keychain_export; mod digest; mod ecdhutil; mod ecdsautil; @@ -144,6 +146,8 @@ fn inner_main() -> CommandError { Box::new(cmd_ec_verify::CommandImpl), Box::new(cmd_parseecdsasignature::CommandImpl), Box::new(cmd_keypair_generate::CommandImpl), + Box::new(cmd_keypair_keychain_import::CommandImpl), + Box::new(cmd_keypair_keychain_export::CommandImpl), ]; #[allow(clippy::vec_init_then_push)]