feaat: v1.9.13, add temporary key for simple encrypt
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -2008,7 +2008,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tiny-encrypt"
|
||||
version = "1.9.12"
|
||||
version = "1.9.13"
|
||||
dependencies = [
|
||||
"aes-gcm-stream",
|
||||
"base64 0.22.1",
|
||||
@@ -2027,6 +2027,7 @@ dependencies = [
|
||||
"openpgp-card-pcsc",
|
||||
"p256",
|
||||
"p384",
|
||||
"percent-encoding",
|
||||
"pinentry",
|
||||
"pqcrypto-kyber",
|
||||
"pqcrypto-traits",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tiny-encrypt"
|
||||
version = "1.9.12"
|
||||
version = "1.9.13"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "A simple and tiny file encrypt tool"
|
||||
@@ -54,6 +54,7 @@ ctrlc = "3.4"
|
||||
swift-secure-enclave-tool-rs = "1.0"
|
||||
json5 = "0.4"
|
||||
external-command-rs = "0.1"
|
||||
percent-encoding = "2.3"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
@@ -7,6 +7,7 @@ use tabled::{Table, Tabled};
|
||||
use tabled::settings::Style;
|
||||
|
||||
use crate::config::TinyEncryptConfig;
|
||||
use crate::temporary_key::serialize_config_envelop;
|
||||
use crate::util_envelop;
|
||||
|
||||
#[derive(Tabled, Eq)]
|
||||
@@ -50,6 +51,9 @@ pub struct CmdConfig {
|
||||
/// JSON output
|
||||
#[arg(long)]
|
||||
pub json: bool,
|
||||
/// Temporary key output
|
||||
#[arg(long)]
|
||||
pub temporary_key: bool,
|
||||
/// Encryption profile (use default when --key-filter is assigned)
|
||||
#[arg(long, short = 'p')]
|
||||
pub profile: Option<String>,
|
||||
@@ -71,6 +75,14 @@ pub fn config(cmd_config: CmdConfig) -> XResult<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if cmd_config.temporary_key {
|
||||
for envelop in &config.envelops {
|
||||
let k = serialize_config_envelop(envelop);
|
||||
println!("{}", k);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if cmd_config.profile.is_some() || cmd_config.key_filter.is_some() {
|
||||
return config_key_filter(&cmd_config, &config);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use serde::Serialize;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
use crate::temporary_key::deserialize_config_envelop;
|
||||
use crate::util_simple_pbe::SimplePbkdfEncryptionV1;
|
||||
|
||||
// Reference: https://git.hatter.ink/hatter/tiny-encrypt-rs/issues/3
|
||||
@@ -25,6 +26,10 @@ pub struct CmdSimpleEncrypt {
|
||||
#[arg(long, short = 'k')]
|
||||
pub key_filter: Option<String>,
|
||||
|
||||
/// Temporary key
|
||||
#[arg(long)]
|
||||
pub temporary_key: Option<Vec<String>>,
|
||||
|
||||
/// Encrypt value from stdin
|
||||
#[arg(long)]
|
||||
pub value_stdin: bool,
|
||||
@@ -190,9 +195,26 @@ pub fn simple_decrypt(cmd_simple_decrypt: CmdSimpleDecrypt) -> XResult<()> {
|
||||
pub fn inner_simple_encrypt(cmd_simple_encrypt: CmdSimpleEncrypt) -> XResult<()> {
|
||||
let config = TinyEncryptConfig::load_default()?;
|
||||
debugging!("Found tiny encrypt config: {:?}", config);
|
||||
let envelops = config.find_envelops(&cmd_simple_encrypt.profile, &cmd_simple_encrypt.key_filter)?;
|
||||
if envelops.is_empty() { return simple_error!("Cannot find any valid envelops"); }
|
||||
|
||||
let mut envelops = config.find_envelops(
|
||||
&cmd_simple_encrypt.profile,
|
||||
&cmd_simple_encrypt.key_filter)?;
|
||||
debugging!("Found envelops: {:?}", envelops);
|
||||
|
||||
let mut temporary_envelops = vec![];
|
||||
if let Some(temporary_key) = &cmd_simple_encrypt.temporary_key {
|
||||
for t_key in temporary_key {
|
||||
let envelop = opt_result!(deserialize_config_envelop(t_key), "Parse temporary key: {} failed: {}", t_key);
|
||||
temporary_envelops.push(envelop);
|
||||
}
|
||||
// FIXME should check kid not exists
|
||||
for t_envelop in &mut temporary_envelops {
|
||||
envelops.push(t_envelop)
|
||||
}
|
||||
debugging!("Final envelops: {:?}", envelops);
|
||||
}
|
||||
if envelops.is_empty() { return simple_error!("Cannot find any valid envelops"); }
|
||||
|
||||
let envelop_tkids: Vec<_> = envelops.iter()
|
||||
.map(|e| format!("{}:{}", e.r#type.get_name(), e.kid))
|
||||
.collect();
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::path::PathBuf;
|
||||
use std::{env, fs};
|
||||
use rust_util::util_env as rust_util_env;
|
||||
use rust_util::util_file::resolve_file_path;
|
||||
use rust_util::{debugging, opt_result, simple_error, warning, XResult};
|
||||
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;
|
||||
@@ -257,7 +257,8 @@ impl TinyEncryptConfig {
|
||||
});
|
||||
}
|
||||
if key_ids.is_empty() {
|
||||
return simple_error!("Profile or key filter cannot find any valid envelopes");
|
||||
// return simple_error!("Profile or key filter cannot find any valid envelopes");
|
||||
return Ok(vec![]);
|
||||
}
|
||||
for key_id in &key_ids {
|
||||
for envelop in self.find_by_kid_or_type(key_id) {
|
||||
@@ -267,7 +268,8 @@ impl TinyEncryptConfig {
|
||||
|
||||
let mut envelops: Vec<_> = matched_envelops_map.values().copied().collect();
|
||||
if envelops.is_empty() {
|
||||
return simple_error!("Profile or key filter cannot find any valid envelopes");
|
||||
// return simple_error!("Profile or key filter cannot find any valid envelopes");
|
||||
return Ok(vec![]);
|
||||
}
|
||||
envelops.sort_by(|e1, e2| {
|
||||
if e1.r#type < e2.r#type {
|
||||
|
||||
@@ -77,4 +77,5 @@ mod cmd_execenv;
|
||||
mod util_keychainkey;
|
||||
mod util_simple_pbe;
|
||||
mod util_log;
|
||||
mod temporary_key;
|
||||
|
||||
|
||||
19
src/spec.rs
19
src/spec.rs
@@ -132,6 +132,25 @@ impl TinyEncryptEnvelopType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
"pgp-rsa" => Some(TinyEncryptEnvelopType::PgpRsa),
|
||||
"pgp-x25519" => Some(TinyEncryptEnvelopType::PgpX25519),
|
||||
"gpg" => Some(TinyEncryptEnvelopType::Gpg),
|
||||
"static-x25519" => Some(TinyEncryptEnvelopType::StaticX25519),
|
||||
"static-kyber1024" => Some(TinyEncryptEnvelopType::StaticKyber1024),
|
||||
"key-p256" => Some(TinyEncryptEnvelopType::KeyP256),
|
||||
"ext-p256" => Some(TinyEncryptEnvelopType::ExtP256),
|
||||
"ext-p384" => Some(TinyEncryptEnvelopType::ExtP384),
|
||||
"piv-p256" => Some(TinyEncryptEnvelopType::PivP256),
|
||||
"piv-p384" => Some(TinyEncryptEnvelopType::PivP384),
|
||||
"piv-rsa" => Some(TinyEncryptEnvelopType::PivRsa),
|
||||
"age" => Some(TinyEncryptEnvelopType::Age),
|
||||
"kms" => Some(TinyEncryptEnvelopType::Kms),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn auto_select(&self) -> bool {
|
||||
match self {
|
||||
TinyEncryptEnvelopType::StaticX25519
|
||||
|
||||
56
src/temporary_key.rs
Normal file
56
src/temporary_key.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
// syntax
|
||||
// tiny-encrypt-key:type:sid:key_id:public_part[?key=value]
|
||||
// e.g.
|
||||
// tiny-encrypt-key:ext-p256:ext-key-1:02536aef5742b4288f1b44b3cc96f1556c35e4fac4e8e117e1f7ae091e42d0835b:04536aef5742b4288f1b44b3cc96f1556c35e4fac4e8e117e1f7ae091e42d0835bf3f95d932c22a74a91859bd7fdd8829a02d38cf4ec598b1cf6e02fa09f707a6f
|
||||
|
||||
use crate::config::TinyEncryptConfigEnvelop;
|
||||
use crate::spec::TinyEncryptEnvelopType;
|
||||
use rust_util::{iff, opt_result, opt_value_result, simple_error, XResult};
|
||||
|
||||
const TINY_ENCRYPT_KEY_PREFIX: &str = "tiny-encrypt-key:";
|
||||
|
||||
pub fn serialize_config_envelop(config_envelop: &TinyEncryptConfigEnvelop) -> String {
|
||||
let mut s = String::new();
|
||||
s.push_str(TINY_ENCRYPT_KEY_PREFIX);
|
||||
s.push_str(config_envelop.r#type.get_name());
|
||||
s.push(':');
|
||||
s.push_str(&encode(config_envelop.sid.as_deref().unwrap_or("")));
|
||||
s.push(':');
|
||||
s.push_str(&encode(&config_envelop.kid));
|
||||
s.push(':');
|
||||
s.push_str(&encode(&config_envelop.public_part));
|
||||
s
|
||||
}
|
||||
|
||||
pub fn deserialize_config_envelop(k: &str) -> XResult<TinyEncryptConfigEnvelop> {
|
||||
if !k.starts_with(TINY_ENCRYPT_KEY_PREFIX) {
|
||||
return simple_error!("invalid temporary key");
|
||||
}
|
||||
let k_parts = k.split(":").collect::<Vec<_>>();
|
||||
if k_parts.len() != 5 {
|
||||
return simple_error!("invalid temporary key (parts)");
|
||||
}
|
||||
let envelop_type = opt_value_result!(
|
||||
TinyEncryptEnvelopType::from_name(k_parts[1]), "Unknown envelop type: {}", k_parts[1]);
|
||||
Ok(TinyEncryptConfigEnvelop {
|
||||
r#type: envelop_type,
|
||||
sid: iff!(k_parts[2].is_empty(), None, Some(decode(k_parts[2])?)),
|
||||
kid: decode(k_parts[3])?,
|
||||
desc: None,
|
||||
args: None,
|
||||
public_part: decode(k_parts[4])?,
|
||||
})
|
||||
}
|
||||
|
||||
fn encode(s: &str) -> String {
|
||||
percent_encoding::utf8_percent_encode(s, percent_encoding::NON_ALPHANUMERIC).to_string()
|
||||
}
|
||||
|
||||
fn decode(s: &str) -> XResult<String> {
|
||||
Ok(opt_result!(
|
||||
percent_encoding::percent_decode_str(s).decode_utf8(),
|
||||
"decode: {} failed: {}",
|
||||
s
|
||||
)
|
||||
.to_string())
|
||||
}
|
||||
Reference in New Issue
Block a user