diff --git a/Cargo.lock b/Cargo.lock index 07b67a5..5c516d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2077,7 +2077,7 @@ dependencies = [ [[package]] name = "tiny-encrypt" -version = "1.9.16" +version = "1.9.17" dependencies = [ "aes-gcm-stream", "base64 0.22.1", diff --git a/Cargo.toml b/Cargo.toml index f63a839..53a0472 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tiny-encrypt" -version = "1.9.16" +version = "1.9.17" edition = "2021" license = "MIT" description = "A simple and tiny file encrypt tool" diff --git a/src/cmd_config.rs b/src/cmd_config.rs index 53bf714..68aa798 100644 --- a/src/cmd_config.rs +++ b/src/cmd_config.rs @@ -63,7 +63,7 @@ pub struct CmdConfig { } pub fn config(cmd_config: CmdConfig) -> XResult<()> { - let config = TinyEncryptConfig::load_default()?; + let config = TinyEncryptConfig::load_default(&None)?; if cmd_config.json { let mut config = config; diff --git a/src/cmd_decrypt.rs b/src/cmd_decrypt.rs index 7b22a52..bef3bb1 100644 --- a/src/cmd_decrypt.rs +++ b/src/cmd_decrypt.rs @@ -95,6 +95,10 @@ pub struct CmdDecrypt { #[arg(long, short = 'A')] pub digest_algorithm: Option, + /// Config file or based64 encoded (starts with: base64:) + #[arg(long)] + pub config: Option, + /// Files need to be decrypted pub paths: Vec, } @@ -108,7 +112,7 @@ impl Drop for CmdDecrypt { pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> { if cmd_decrypt.split_print { util_msg::set_logger_std_out(false); } debugging!("Cmd decrypt: {:?}", cmd_decrypt); - let config = TinyEncryptConfig::load_default().ok(); + let config = TinyEncryptConfig::load_default(&cmd_decrypt.config).ok(); let start = Instant::now(); let mut succeed_count = 0; diff --git a/src/cmd_encrypt.rs b/src/cmd_encrypt.rs index 42a0c26..9d52205 100644 --- a/src/cmd_encrypt.rs +++ b/src/cmd_encrypt.rs @@ -77,12 +77,16 @@ pub struct CmdEncrypt { #[arg(long, short = 'A')] pub encryption_algorithm: Option, + /// Config file or based64 encoded (starts with: base64:) + #[arg(long)] + pub config: Option, + /// Files need to be decrypted pub paths: Vec, } pub fn encrypt(cmd_encrypt: CmdEncrypt) -> XResult<()> { - let config = TinyEncryptConfig::load_default()?; + let config = TinyEncryptConfig::load_default(&cmd_encrypt.config)?; debugging!("Found tiny encrypt config: {:?}", config); let mut envelops = config.find_envelops(&cmd_encrypt.profile, &cmd_encrypt.key_filter)?; debugging!("Found envelops: {:?}", envelops); diff --git a/src/cmd_execenv.rs b/src/cmd_execenv.rs index da295f6..095e8dd 100644 --- a/src/cmd_execenv.rs +++ b/src/cmd_execenv.rs @@ -29,6 +29,10 @@ pub struct CmdExecEnv { #[arg(long, short = 's')] pub slot: Option, + /// Config file or based64 encoded (starts with: base64:) + #[arg(long)] + pub config: Option, + /// Tiny encrypt file name pub file_name: String, @@ -45,7 +49,7 @@ impl Drop for CmdExecEnv { pub fn exec_env(cmd_exec_env: CmdExecEnv) -> XResult<()> { util_msg::set_logger_std_out(false); debugging!("Cmd exec env: {:?}", cmd_exec_env); - let config = TinyEncryptConfig::load_default().ok(); + let config = TinyEncryptConfig::load_default(&cmd_exec_env.config).ok(); if cmd_exec_env.command_arguments.is_empty() { return simple_error!("No commands assigned."); } diff --git a/src/cmd_info.rs b/src/cmd_info.rs index 80f32a0..0730fbb 100644 --- a/src/cmd_info.rs +++ b/src/cmd_info.rs @@ -23,12 +23,16 @@ pub struct CmdInfo { #[arg(long, short = 'M', default_value_t = false)] pub raw_meta: bool, + /// Config file or based64 encoded (starts with: base64:) + #[arg(long)] + pub config: Option, + /// File pub paths: Vec, } pub fn info(cmd_info: CmdInfo) -> XResult<()> { - let config = TinyEncryptConfig::load_default().ok(); + let config = TinyEncryptConfig::load_default(&cmd_info.config).ok(); for (i, path) in cmd_info.paths.iter().enumerate() { let path = config::resolve_path_namespace(&config, path, true); if i > 0 { println!("{}", "-".repeat(88)); } diff --git a/src/cmd_simple_encrypt_decrypt.rs b/src/cmd_simple_encrypt_decrypt.rs index 7873349..c287396 100644 --- a/src/cmd_simple_encrypt_decrypt.rs +++ b/src/cmd_simple_encrypt_decrypt.rs @@ -54,6 +54,10 @@ pub struct CmdSimpleEncrypt { #[arg(long, short = 'A')] pub password: Option, + /// Config file or based64 encoded (starts with: base64:) + #[arg(long)] + pub config: Option, + /// Direct output result value #[arg(long)] pub outputs_password: bool, @@ -93,6 +97,10 @@ pub struct CmdSimpleDecrypt { #[arg(long, short = 'A')] pub password: Option, + /// Config file or based64 encoded (starts with: base64:) + #[arg(long)] + pub config: Option, + /// Direct output result value #[arg(long)] pub outputs_password: bool, @@ -193,7 +201,7 @@ pub fn simple_decrypt(cmd_simple_decrypt: CmdSimpleDecrypt) -> XResult<()> { } pub fn inner_simple_encrypt(cmd_simple_encrypt: CmdSimpleEncrypt) -> XResult<()> { - let config = TinyEncryptConfig::load_default()?; + let config = TinyEncryptConfig::load_default(&cmd_simple_encrypt.config)?; debugging!("Found tiny encrypt config: {:?}", config); let mut envelops = config.find_envelops( @@ -248,7 +256,7 @@ pub fn inner_simple_encrypt(cmd_simple_encrypt: CmdSimpleEncrypt) -> XResult<()> #[cfg(feature = "decrypt")] pub fn inner_simple_decrypt(cmd_simple_decrypt: CmdSimpleDecrypt) -> XResult<()> { - let config = TinyEncryptConfig::load_default().ok(); + let config = TinyEncryptConfig::load_default(&cmd_simple_decrypt.config).ok(); let pin = cmd_simple_decrypt.pin.clone().or_else(util_env::get_pin); let slot = cmd_simple_decrypt.slot.clone(); diff --git a/src/config.rs b/src/config.rs index d0aafbc..d406358 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,12 +3,13 @@ use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; use std::{env, fs}; -use rust_util::util_env as rust_util_env; +use rust_util::{util_env as rust_util_env}; use rust_util::util_file::resolve_file_path; use rust_util::{debugging, opt_result, warning, XResult}; use serde::{Deserialize, Serialize}; use crate::consts::{ENV_TINY_ENC_CONFIG_FILE, TINY_ENC_CONFIG_FILE, TINY_ENC_CONFIG_FILE_2, TINY_ENC_CONFIG_FILE_3, TINY_ENC_FILE_EXT}; use crate::spec::TinyEncryptEnvelopType; +use crate::util::decode_base64; /// Config file sample: /// ~/.tinyencrypt/config-rs.json @@ -74,14 +75,20 @@ pub struct TinyEncryptConfigEnvelop { } impl TinyEncryptConfig { - pub fn load_default() -> XResult { - let resolved_file0 = rust_util_env::env_var(ENV_TINY_ENC_CONFIG_FILE); + pub fn load_default(config: &Option) -> XResult { + let resolved_file0 = config.clone().or_else(|| rust_util_env::env_var(ENV_TINY_ENC_CONFIG_FILE)); let resolved_file_1 = resolve_file_path(TINY_ENC_CONFIG_FILE); let resolved_file_2 = resolve_file_path(TINY_ENC_CONFIG_FILE_2); let resolved_file_3 = resolve_file_path(TINY_ENC_CONFIG_FILE_3); if let Some(resolved_file) = resolved_file0 { + if resolved_file.starts_with("base64:") { + let decoded_resolved_bytes_result = decode_base64(&resolved_file.chars().skip(7).collect::()); + let decoded_resolved_bytes = opt_result!(decoded_resolved_bytes_result, "Decode base64 failed: {}"); + let decoded_resolved_content = opt_result!(String::from_utf8(decoded_resolved_bytes), "Decode UTF-8 string failed: {}"); + return Self::load_content(&decoded_resolved_content, ""); + } debugging!("Found tiny encrypt config file: {}", &resolved_file); - return Self::load(&resolved_file) + return Self::load_file(&resolved_file) } let config_file = if fs::metadata(&resolved_file_1).is_ok() { debugging!("Load config from: {resolved_file_1}"); @@ -96,18 +103,22 @@ impl TinyEncryptConfig { warning!("Cannot find config file from:\n- {resolved_file_1}\n- {resolved_file_2}\n- {resolved_file_3}"); resolved_file_1 }; - Self::load(&config_file) + Self::load_file(&config_file) } - pub fn load(file: &str) -> XResult { + pub fn load_file(file: &str) -> XResult { let resolved_file = resolve_file_path(file); - let config_contents = opt_result!( + let config_content = opt_result!( fs::read_to_string(resolved_file), "Read config file: {}, failed: {}", file ); + Self::load_content(&config_content, file) + } + + pub fn load_content(config_content: &str, file: &str) -> XResult { let config: TinyEncryptConfig = opt_result!( - serde_json::from_str(&config_contents), + serde_json::from_str(&config_content), "Parse config file: {}, failed: {}", file );