From c05cf1a7cffbf416edc0a744eb3c8efc06ba547d Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Wed, 25 Oct 2023 23:16:20 +0800 Subject: [PATCH] feat: v0.5.3, fix compress issue, supports env TINY_ENCRYPT_DEFAULT_ALGORITHM --- Cargo.lock | 22 +++++++++++----------- Cargo.toml | 2 +- README.md | 5 +++++ src/cmd_encrypt.rs | 25 ++++++++++--------------- src/consts.rs | 1 + src/crypto_cryptor.rs | 16 +++++++++++++++- src/main.rs | 1 + src/util.rs | 5 +++++ src/util_env.rs | 16 ++++++++++++++++ 9 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 src/util_env.rs diff --git a/Cargo.lock b/Cargo.lock index 91ce94a..4091f25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,9 +233,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytecount" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1a12477b7237a01c11a80a51278165f9ba0edd28fa6db00a65ab230320dc58c" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "byteorder" @@ -300,9 +300,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -322,9 +322,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -1729,7 +1729,7 @@ dependencies = [ [[package]] name = "tiny-encrypt" -version = "0.5.2" +version = "0.5.3" dependencies = [ "aes-gcm-stream", "base64", diff --git a/Cargo.toml b/Cargo.toml index 9caa5c3..abbe5c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tiny-encrypt" -version = "0.5.2" +version = "0.5.3" edition = "2021" license = "MIT" description = "A simple and tiny file encrypt tool" diff --git a/README.md b/README.md index 1f76936..49222c5 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,11 @@ Specification: [Tiny Encrypt Spec V1.1](https://github.com/OpenWebStandard/tiny- Repository address: https://git.hatter.ink/hatter/tiny-encrypt-rs mirror https://github.com/jht5945/tiny-encrypt-rs +Set default encryption algorithm: +```shell +export TINY_ENCRYPT_DEFAULT_ALGORITHM='AES' # or CHACHA20 +``` +
Encrypt config `~/.tinyencrypt/config-rs.json`: diff --git a/src/cmd_encrypt.rs b/src/cmd_encrypt.rs index cbe3488..83e3221 100644 --- a/src/cmd_encrypt.rs +++ b/src/cmd_encrypt.rs @@ -10,7 +10,7 @@ use rsa::Pkcs1v15Encrypt; use rust_util::{debugging, failure, iff, information, opt_result, simple_error, success, XResult}; use rust_util::util_time::UnixEpochTime; -use crate::{consts, crypto_simple, util, util_enc_file, util_p256, util_p384, util_x25519}; +use crate::{crypto_cryptor, crypto_simple, util, util_enc_file, util_p256, util_p384, util_x25519}; use crate::compress::GzStreamEncoder; use crate::config::{TinyEncryptConfig, TinyEncryptConfigEnvelop}; use crate::consts::{ @@ -119,14 +119,7 @@ fn encrypt_single(path: &PathBuf, envelops: &[&TinyEncryptConfigEnvelop], cmd_en return Ok(0); } - let encryption_algorithm = cmd_encrypt.encryption_algorithm.as_deref() - .unwrap_or(consts::TINY_ENC_AES_GCM) - .to_lowercase(); - let cryptor = match encryption_algorithm.as_str() { - "aes" | "aes/gcm" => Cryptor::Aes256Gcm, - "chacha20" | "chacha20/poly1305" => Cryptor::ChaCha20Poly1305, - _ => return simple_error!("Unknown encryption algorithm: {}, should be AES or CHACHA20", encryption_algorithm), - }; + let cryptor = crypto_cryptor::get_cryptor_by_encryption_algorithm(&cmd_encrypt.encryption_algorithm)?; information!("Using encryption algorithm: {}", cryptor.get_name()); util::require_file_exists(path)?; @@ -184,11 +177,13 @@ fn encrypt_single(path: &PathBuf, envelops: &[&TinyEncryptConfigEnvelop], cmd_en let _ = util_enc_file::write_tiny_encrypt_meta(&mut file_out, &encrypt_meta, compress_meta)?; let compress_desc = iff!(cmd_encrypt.compress, " [with compress]", ""); - let compress_level = iff!(cmd_encrypt.compress, &cmd_encrypt.compress_level, &None); + + let compress_level = iff!(cmd_encrypt.compress, + Some(cmd_encrypt.compress_level.unwrap_or_else(|| Compression::default().level())), None); let start = Instant::now(); encrypt_file( &mut file_in, file_metadata.len(), &mut file_out, cryptor, - &key.0, &nonce.0, compress_level, + &key.0, &nonce.0, &compress_level, )?; drop(file_out); let encrypt_duration = start.elapsed(); @@ -338,14 +333,14 @@ fn encrypt_envelop_shared_secret(cryptor: Cryptor, enc_type: &str, envelop: &TinyEncryptConfigEnvelop) -> XResult { let shared_key = util::simple_kdf(shared_secret); - let (_, nonce) = util::make_key256_and_nonce(); + let nonce = util::make_nonce(); let encrypted_key = crypto_simple::encrypt( cryptor, &shared_key, &nonce.0, key)?; let wrap_key = WrapKey { header: WrapKeyHeader { - kid: None, // Some(envelop.kid.clone()), + kid: None, enc: enc_type.to_string(), e_pub_key: util::encode_base64_url_no_pad(ephemeral_spki), }, @@ -357,7 +352,7 @@ fn encrypt_envelop_shared_secret(cryptor: Cryptor, Ok(TinyEncryptEnvelop { r#type: envelop.r#type, kid: envelop.kid.clone(), - desc: None, // envelop.desc.clone(), + desc: None, encrypted_key: encoded_wrap_key, }) } @@ -369,7 +364,7 @@ fn encrypt_envelop_pgp(key: &[u8], envelop: &TinyEncryptConfigEnvelop) -> XResul Ok(TinyEncryptEnvelop { r#type: envelop.r#type, kid: envelop.kid.clone(), - desc: None, // envelop.desc.clone(), + desc: None, encrypted_key: util::encode_base64(&encrypted_key), }) } diff --git a/src/consts.rs b/src/consts.rs index 105ecda..887ae44 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -10,6 +10,7 @@ pub const ENC_CHACHA20_POLY1305_X25519: &str = "chacha20-poly1305-x25519"; pub const TINY_ENC_FILE_EXT: &str = ".tinyenc"; pub const TINY_ENC_CONFIG_FILE: &str = "~/.tinyencrypt/config-rs.json"; +pub const TINY_ENCRYPT_ENV_DEFAULT_ALGORITHM: &str = "TINY_ENCRYPT_DEFAULT_ALGORITHM"; pub const TINY_ENC_AES_GCM: &str = "AES/GCM"; pub const TINY_ENC_CHACHA20_POLY1305: &str = "CHACHA20/POLY1305"; diff --git a/src/crypto_cryptor.rs b/src/crypto_cryptor.rs index 33ec568..d4aa54e 100644 --- a/src/crypto_cryptor.rs +++ b/src/crypto_cryptor.rs @@ -3,7 +3,7 @@ use chacha20_poly1305_stream::{ChaCha20Poly1305StreamDecryptor, ChaCha20Poly1305 use rust_util::{opt_result, simple_error, XResult}; use zeroize::Zeroize; -use crate::consts; +use crate::{consts, util_env}; #[derive(Debug, Copy, Clone)] pub enum Cryptor { @@ -152,6 +152,20 @@ impl Decryptor for ChaCha20Poly1305Decryptor { } } +#[allow(clippy::redundant_closure)] +pub fn get_cryptor_by_encryption_algorithm(encryption_algorithm: &Option) -> XResult { + let encryption_algorithm = encryption_algorithm.as_deref() + .or_else(|| util_env::get_default_encryption_algorithm()) + .unwrap_or(consts::TINY_ENC_AES_GCM) + .to_lowercase(); + let cryptor = match encryption_algorithm.as_str() { + "aes" | "aes/gcm" => Cryptor::Aes256Gcm, + "chacha20" | "chacha20/poly1305" => Cryptor::ChaCha20Poly1305, + _ => return simple_error!("Unknown encryption algorithm: {}, should be AES or CHACHA20", encryption_algorithm), + }; + Ok(cryptor) +} + #[test] fn test_cryptor() { let key = [0u8; 32]; diff --git a/src/main.rs b/src/main.rs index 5981822..9472054 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ use crate::cmd_version::CmdVersion; mod consts; mod util; +mod util_env; mod util_digest; mod util_progress; mod util_piv; diff --git a/src/util.rs b/src/util.rs index 580905c..2549c5a 100644 --- a/src/util.rs +++ b/src/util.rs @@ -76,6 +76,11 @@ pub fn require_file_not_exists(path: impl AsRef) -> XResult<()> { } } +pub fn make_nonce() -> SecVec { + let (_, nonce) = make_key256_and_nonce(); + nonce +} + pub fn make_key256_and_nonce() -> (SecVec, SecVec) { let key: [u8; 32] = random(); let nonce: [u8; 12] = random(); diff --git a/src/util_env.rs b/src/util_env.rs new file mode 100644 index 0000000..3f7b93e --- /dev/null +++ b/src/util_env.rs @@ -0,0 +1,16 @@ +use std::env; + +use crate::consts; + +pub fn get_default_encryption_algorithm() -> Option<&'static str> { + let env_default_algorithm = env::var(consts::TINY_ENCRYPT_ENV_DEFAULT_ALGORITHM).ok(); + if let Some(env_algorithm) = env_default_algorithm { + let lower_default_algorithm = env_algorithm.to_lowercase(); + match lower_default_algorithm.as_str() { + "aes" | "aes/gcm" => return Some(consts::TINY_ENC_AES_GCM), + "chacha20" | "chacha20/poly1305" => return Some(consts::TINY_ENC_CHACHA20_POLY1305), + _ => {} + } + } + None +} \ No newline at end of file