feat: v1.7.4, add slient mod for exec-env

This commit is contained in:
2024-01-11 00:24:39 +08:00
parent 2bf0614854
commit 27c6bee4ea
5 changed files with 49 additions and 26 deletions

2
Cargo.lock generated
View File

@@ -1788,7 +1788,7 @@ dependencies = [
[[package]]
name = "tiny-encrypt"
version = "1.7.3"
version = "1.7.4"
dependencies = [
"aes-gcm-stream",
"base64",

View File

@@ -1,6 +1,6 @@
[package]
name = "tiny-encrypt"
version = "1.7.3"
version = "1.7.4"
edition = "2021"
license = "MIT"
description = "A simple and tiny file encrypt tool"

View File

@@ -176,9 +176,9 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
let digest_algorithm = cmd_decrypt.digest_algorithm.as_deref().unwrap_or("sha256");
if cmd_decrypt.digest_file { DigestWrite::from_algo(digest_algorithm)?; } // FAST CHECK
let selected_envelop = select_envelop(&meta, key_id, config)?;
let selected_envelop = select_envelop(&meta, key_id, config, false)?;
let key = SecVec(try_decrypt_key(config, selected_envelop, pin, slot)?);
let key = SecVec(try_decrypt_key(config, selected_envelop, pin, slot, false)?);
let nonce = SecVec(opt_result!(util::decode_base64(&meta.nonce), "Decode nonce failed: {}"));
let key_nonce = KeyNonce { k: key.as_ref(), n: nonce.as_ref() };
@@ -454,17 +454,18 @@ fn parse_encrypted_meta(meta: &TinyEncryptMeta, cryptor: Cryptor, key_nonce: &Ke
pub fn try_decrypt_key(config: &Option<TinyEncryptConfig>,
envelop: &TinyEncryptEnvelop,
pin: &Option<String>,
slot: &Option<String>) -> XResult<Vec<u8>> {
slot: &Option<String>,
silent: bool) -> XResult<Vec<u8>> {
match envelop.r#type {
TinyEncryptEnvelopType::PgpRsa => try_decrypt_key_pgp_rsa(envelop, pin),
TinyEncryptEnvelopType::PgpX25519 => try_decrypt_key_ecdh_pgp_x25519(envelop, pin),
TinyEncryptEnvelopType::Gpg => try_decrypt_key_gpg(envelop),
#[cfg(feature = "macos")]
TinyEncryptEnvelopType::StaticX25519 => try_decrypt_key_ecdh_static_x25519(config, envelop),
TinyEncryptEnvelopType::PivP256 | TinyEncryptEnvelopType::PivP384 => try_decrypt_piv_key_ecdh(config, envelop, pin, slot),
TinyEncryptEnvelopType::PivP256 | TinyEncryptEnvelopType::PivP384 => try_decrypt_piv_key_ecdh(config, envelop, pin, slot, silent),
#[cfg(feature = "secure-enclave")]
TinyEncryptEnvelopType::KeyP256 => try_decrypt_se_key_ecdh(config, envelop),
TinyEncryptEnvelopType::PivRsa => try_decrypt_piv_key_rsa(config, envelop, pin, slot),
TinyEncryptEnvelopType::PivRsa => try_decrypt_piv_key_rsa(config, envelop, pin, slot, silent),
#[cfg(feature = "macos")]
TinyEncryptEnvelopType::StaticKyber1024 => try_decrypt_key_ecdh_static_kyber1204(config, envelop),
unknown_type => simple_error!("Unknown or unsupported type: {}", unknown_type.get_name()),
@@ -474,7 +475,8 @@ pub fn try_decrypt_key(config: &Option<TinyEncryptConfig>,
fn try_decrypt_piv_key_ecdh(config: &Option<TinyEncryptConfig>,
envelop: &TinyEncryptEnvelop,
pin: &Option<String>,
slot: &Option<String>) -> XResult<Vec<u8>> {
slot: &Option<String>,
silent: bool) -> XResult<Vec<u8>> {
let wrap_key = WrapKey::parse(&envelop.encrypted_key)?;
let (cryptor, algo_id) = match wrap_key.header.enc.as_str() {
ENC_AES256_GCM_P256 => (Cryptor::Aes256Gcm, AlgorithmId::EccP256),
@@ -487,7 +489,7 @@ fn try_decrypt_piv_key_ecdh(config: &Option<TinyEncryptConfig>,
let (_, subject_public_key_info) = opt_result!(
SubjectPublicKeyInfo::from_der(&e_pub_key_bytes), "Invalid envelop: {}");
let slot = util_piv::read_piv_slot(config, &envelop.kid, slot)?;
let slot = util_piv::read_piv_slot(config, &envelop.kid, slot, silent)?;
let pin = util::read_pin(pin)?;
let epk_bytes = subject_public_key_info.subject_public_key.as_ref();
@@ -514,10 +516,11 @@ fn try_decrypt_piv_key_ecdh(config: &Option<TinyEncryptConfig>,
fn try_decrypt_piv_key_rsa(config: &Option<TinyEncryptConfig>,
envelop: &TinyEncryptEnvelop,
pin: &Option<String>,
slot: &Option<String>) -> XResult<Vec<u8>> {
slot: &Option<String>,
silent: bool) -> XResult<Vec<u8>> {
let encrypted_key_bytes = opt_result!(util::decode_base64(&envelop.encrypted_key), "Decode encrypt key failed: {}");
let slot = util_piv::read_piv_slot(config, &envelop.kid, slot)?;
let slot = util_piv::read_piv_slot(config, &envelop.kid, slot, silent)?;
let pin = util::read_pin(pin)?;
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
@@ -699,7 +702,7 @@ fn try_decrypt_key_pgp_rsa(envelop: &TinyEncryptEnvelop, pin: &Option<String>) -
Ok(key)
}
pub fn select_envelop<'a>(meta: &'a TinyEncryptMeta, key_id: &Option<String>, config: &Option<TinyEncryptConfig>) -> XResult<&'a TinyEncryptEnvelop> {
pub fn select_envelop<'a>(meta: &'a TinyEncryptMeta, key_id: &Option<String>, config: &Option<TinyEncryptConfig>, silent: bool) -> XResult<&'a TinyEncryptEnvelop> {
let envelops = match &meta.envelops {
None => return simple_error!("No envelops found"),
Some(envelops) => if envelops.is_empty() {
@@ -709,14 +712,22 @@ pub fn select_envelop<'a>(meta: &'a TinyEncryptMeta, key_id: &Option<String>, co
},
};
success!("Found {} envelops:", envelops.len());
if let Some(envelop) = match_envelop_by_key_id(envelops, key_id, config) {
if silent {
debugging!("Found {} envelops:", envelops.len());
} else {
success!("Found {} envelops:", envelops.len());
}
if let Some(envelop) = match_envelop_by_key_id(envelops, key_id, config, silent) {
return Ok(envelop);
}
if envelops.len() == 1 {
let selected_envelop = &envelops[0];
success!("Auto selected envelop: #{} {}", 1, util_envelop::format_envelop(selected_envelop, config));
if silent {
debugging!("Auto selected envelop: #{} {}", 1, util_envelop::format_envelop(selected_envelop, config));
} else {
success!("Auto selected envelop: #{} {}", 1, util_envelop::format_envelop(selected_envelop, config));
}
if !selected_envelop.r#type.auto_select() {
util::read_line("Press enter to continue: ");
}
@@ -726,7 +737,7 @@ pub fn select_envelop<'a>(meta: &'a TinyEncryptMeta, key_id: &Option<String>, co
// auto select
if let Some(auto_select_key_ids) = util_env::get_auto_select_key_ids() {
for auto_select_key_id in auto_select_key_ids {
if let Some(envelop) = match_envelop_by_key_id(envelops, &Some(auto_select_key_id), config) {
if let Some(envelop) = match_envelop_by_key_id(envelops, &Some(auto_select_key_id), config, silent) {
return Ok(envelop);
}
}
@@ -738,11 +749,15 @@ pub fn select_envelop<'a>(meta: &'a TinyEncryptMeta, key_id: &Option<String>, co
let envelop_number = util::read_number("Please select an envelop:", 1, envelops.len());
let selected_envelop = &envelops[envelop_number - 1];
success!("Selected envelop: #{} {}", envelop_number, selected_envelop.r#type.get_upper_name());
if silent {
debugging!("Selected envelop: #{} {}", envelop_number, selected_envelop.r#type.get_upper_name());
} else {
success!("Selected envelop: #{} {}", envelop_number, selected_envelop.r#type.get_upper_name());
}
Ok(selected_envelop)
}
fn match_envelop_by_key_id<'a>(envelops: &'a Vec<TinyEncryptEnvelop>, key_id: &Option<String>, config: &Option<TinyEncryptConfig>) -> Option<&'a TinyEncryptEnvelop> {
fn match_envelop_by_key_id<'a>(envelops: &'a Vec<TinyEncryptEnvelop>, key_id: &Option<String>, config: &Option<TinyEncryptConfig>, silent: bool) -> Option<&'a TinyEncryptEnvelop> {
if let Some(key_id) = key_id {
for envelop in envelops {
let is_sid_matched = config.as_ref().and_then(|config| {
@@ -752,7 +767,11 @@ fn match_envelop_by_key_id<'a>(envelops: &'a Vec<TinyEncryptEnvelop>, key_id: &O
}).unwrap_or(false);
if is_sid_matched || (&envelop.kid == key_id) {
information!("Matched envelop: {}", util_envelop::format_envelop(envelop, config));
if silent {
debugging!("Matched envelop: {}", util_envelop::format_envelop(envelop, config));
} else {
information!("Matched envelop: {}", util_envelop::format_envelop(envelop, config));
}
return Some(envelop);
}
}

View File

@@ -4,7 +4,7 @@ use std::process::Command;
use std::time::Instant;
use clap::Args;
use rust_util::{debugging, iff, information, opt_result, simple_error, util_cmd, util_msg, warning, XResult};
use rust_util::{debugging, iff, opt_result, simple_error, util_cmd, util_msg, warning, XResult};
use serde_json::Value;
use zeroize::Zeroize;
@@ -71,9 +71,9 @@ pub fn exec_env(cmd_exec_env: CmdExecEnv) -> XResult<()> {
.unwrap_or(consts::TINY_ENC_AES_GCM);
let cryptor = Cryptor::from(encryption_algorithm)?;
let selected_envelop = select_envelop(&meta, &key_id, &config)?;
let selected_envelop = select_envelop(&meta, &key_id, &config, true)?;
let key = SecVec(try_decrypt_key(&config, selected_envelop, &pin, &cmd_exec_env.slot)?);
let key = SecVec(try_decrypt_key(&config, selected_envelop, &pin, &cmd_exec_env.slot, true)?);
let nonce = SecVec(opt_result!(util::decode_base64(&meta.nonce), "Decode nonce failed: {}"));
let key_nonce = KeyNonce { k: key.as_ref(), n: nonce.as_ref() };
@@ -95,7 +95,7 @@ pub fn exec_env(cmd_exec_env: CmdExecEnv) -> XResult<()> {
-1
};
information!("Finished, cost: {}ms", start.elapsed().as_millis());
debugging!("Finished, cost: {}ms", start.elapsed().as_millis());
std::process::exit(exit_code);
}

View File

@@ -1,18 +1,22 @@
use std::io;
use std::io::Write;
use rust_util::{information, print_ex, simple_error, XResult};
use rust_util::{debugging, information, print_ex, simple_error, XResult};
use yubikey::piv::{RetiredSlotId, SlotId};
use crate::config::TinyEncryptConfig;
pub fn read_piv_slot(config: &Option<TinyEncryptConfig>, kid: &str, slot: &Option<String>) -> XResult<String> {
pub fn read_piv_slot(config: &Option<TinyEncryptConfig>, kid: &str, slot: &Option<String>, silent: bool) -> XResult<String> {
match slot {
Some(slot) => Ok(slot.to_string()),
None => {
if let Some(config) = config {
if let Some(first_arg) = config.find_first_arg_by_kid(kid) {
information!("Found kid: {}'s slot: {}", kid, first_arg);
if silent {
debugging!("Found kid: {}'s slot: {}", kid, first_arg);
} else {
information!("Found kid: {}'s slot: {}", kid, first_arg);
}
return Ok(first_arg.to_string());
}
}