feat: update dependencies, optimize

This commit is contained in:
2023-10-28 16:41:07 +08:00
parent 373b3bcefc
commit 89ed3c26ed
12 changed files with 99 additions and 65 deletions

8
Cargo.lock generated
View File

@@ -611,9 +611,9 @@ dependencies = [
[[package]]
name = "fiat-crypto"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d"
checksum = "a481586acf778f1b1455424c343f71124b048ffa5f4fc3f8f6ae9dc432dcb3c7"
[[package]]
name = "flagset"
@@ -1378,9 +1378,9 @@ dependencies = [
[[package]]
name = "rust_util"
version = "0.6.45"
version = "0.6.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45c3036388284b69995eb2864a943b0de55de76ad5b56fc2d3c60fecd7b9ad82"
checksum = "cffc8cab4e18f1320f13ac0c357b4bef1c120723885a187799440440e563f7a4"
dependencies = [
"lazy_static",
"libc",

View File

@@ -5,11 +5,7 @@ use std::time::{Instant, SystemTime};
use clap::Args;
use openpgp_card::crypto_data::Cryptogram;
use rust_util::{
debugging, failure, iff, information, opt_result,
println_ex, simple_error, success, util_msg,
warning, XResult,
};
use rust_util::{debugging, failure, iff, information, opt_result, println_ex, simple_error, success, util_msg, util_size, warning, XResult};
use rust_util::util_time::UnixEpochTime;
use x509_parser::prelude::FromDer;
use x509_parser::x509::SubjectPublicKeyInfo;
@@ -85,10 +81,10 @@ pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> {
succeed_count += 1;
total_len += len;
success!(
"Decrypt {} succeed, cost {} ms, file size {} byte(s)",
"Decrypt {} succeed, cost {} ms, file size {}",
path.to_str().unwrap_or("N/A"),
start_decrypt_single.elapsed().as_millis(),
len
util_size::get_display_size(len as i64)
);
}
Err(e) => {
@@ -99,9 +95,9 @@ pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> {
}
if (succeed_count + failed_count) > 1 {
success!(
"Decrypt succeed {} file(s) {} byte(s), failed {} file(s), total cost {} ms",
"Decrypt succeed {} file(s) {}, failed {} file(s), total cost {} ms",
succeed_count,
total_len,
util_size::get_display_size(total_len as i64),
failed_count,
start.elapsed().as_millis(),
);
@@ -120,7 +116,9 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
let mut file_in = opt_result!(File::open(path), "Open file: {} failed: {}", &path_display);
let (_, meta) = opt_result!(
util_enc_file::read_tiny_encrypt_meta_and_normalize(&mut file_in), "Read file: {}, failed: {}", &path_display);
debugging!("Found meta: {}", serde_json::to_string_pretty(&meta).unwrap());
util_msg::when_debug(|| {
debugging!("Found meta: {}", serde_json::to_string_pretty(&meta).unwrap());
});
let encryption_algorithm = meta.encryption_algorithm.as_deref()
.unwrap_or(consts::TINY_ENC_AES_GCM);
@@ -143,12 +141,12 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
let key_nonce = KeyNonce { k: &key.0, n: &nonce.0 };
// debugging!("Decrypt key: {}", hex::encode(&key.0));
debugging!("Decrypt nonce: {}", hex::encode(&nonce.0));
util_msg::when_debug(|| debugging!("Decrypt nonce: {}", hex::encode(&nonce.0)));
let enc_meta = parse_encrypted_meta(&meta, cryptor, &key_nonce)?;
parse_encrypted_comment(&meta, cryptor, &key_nonce)?;
// Decrypt to output
// Decrypt to output
if cmd_decrypt.direct_print {
if meta.file_length > 10 * 1024 {
warning!("File too large(more than 10K) cannot direct print on console.");
@@ -170,7 +168,7 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
return Ok(meta.file_length);
}
// Digest file
// Digest file
if cmd_decrypt.digest_file {
let mut digest_write = DigestWrite::from_algo(digest_algorithm)?;
let _ = decrypt_file(
@@ -186,7 +184,7 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
return Ok(0);
}
// Decrypt to file
// Decrypt to file
let compressed_desc = iff!(meta.compress, " [compressed]", "");
let start = Instant::now();
@@ -195,12 +193,12 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
&mut file_in, meta.file_length, &mut file_out, cryptor, &key_nonce, meta.compress,
)?;
drop(file_out);
util_file::update_out_file_time(enc_meta, path_out);
util_file::update_file_time(enc_meta, path_out);
let encrypt_duration = start.elapsed();
debugging!("Inner decrypt file{}: {} elapsed: {} ms", compressed_desc, path_display, encrypt_duration.as_millis());
if do_skip_file_out && cmd_decrypt.remove_file { util::remove_file_with_msg(path); }
if do_skip_file_out & &cmd_decrypt.remove_file { util::remove_file_with_msg(path); }
Ok(meta.file_length)
}
@@ -224,7 +222,7 @@ fn decrypt_file(file_in: &mut File, file_len: u64, file_out: &mut impl Write,
last_block
};
opt_result!(file_out.write_all(&last_block), "Write file failed: {}");
debugging!("Decrypt finished, total bytes: {}", total_len);
debugging!("Decrypt finished, total: {} byte(s)", total_len);
progress.finish();
break;
} else {
@@ -305,8 +303,7 @@ fn try_decrypt_key_ecdh(config: &Option<TinyEncryptConfig>,
ENC_CHACHA20_POLY1305_P384 => (Cryptor::ChaCha20Poly1305, AlgorithmId::EccP384),
_ => return simple_error!("Unsupported header enc: {}", &wrap_key.header.enc),
};
let e_pub_key = &wrap_key.header.e_pub_key;
let e_pub_key_bytes = opt_result!(util::decode_base64_url_no_pad(e_pub_key), "Invalid envelop: {}");
let e_pub_key_bytes = wrap_key.header.get_e_pub_key_bytes()?;
let (_, subject_public_key_info) = opt_result!(
SubjectPublicKeyInfo::from_der(&e_pub_key_bytes), "Invalid envelop: {}");
@@ -341,15 +338,14 @@ fn try_decrypt_key_ecdh_pgp_x25519(envelop: &TinyEncryptEnvelop, pin: &Option<St
ENC_CHACHA20_POLY1305_X25519 => Cryptor::ChaCha20Poly1305,
_ => return simple_error!("Unsupported header enc: {}", &wrap_key.header.enc),
};
let e_pub_key = &wrap_key.header.e_pub_key;
let epk_bytes = opt_result!(util::decode_base64_url_no_pad(e_pub_key), "Invalid envelop: {}");
let e_pub_key_bytes = wrap_key.header.get_e_pub_key_bytes()?;
let mut pgp = util_pgp::get_openpgp()?;
let mut trans = opt_result!(pgp.transaction(), "Connect PIV card failed: {}");
util_pgp::read_and_verify_openpgp_pin(&mut trans, pin)?;
let shared_secret = trans.decipher(Cryptogram::ECDH(&epk_bytes))?;
let shared_secret = trans.decipher(Cryptogram::ECDH(&e_pub_key_bytes))?;
let key = util::simple_kdf(shared_secret.as_slice());
let key_nonce = KeyNonce { k: &key, n: &wrap_key.nonce };

View File

@@ -7,7 +7,7 @@ use std::time::Instant;
use clap::Args;
use flate2::Compression;
use rsa::Pkcs1v15Encrypt;
use rust_util::{debugging, failure, iff, information, opt_result, simple_error, success, XResult};
use rust_util::{debugging, failure, iff, information, opt_result, simple_error, success, util_size, XResult};
use rust_util::util_time::UnixEpochTime;
use crate::{crypto_cryptor, crypto_simple, util, util_enc_file, util_env, util_p256, util_p384, util_x25519};
@@ -194,7 +194,7 @@ fn encrypt_file(file_in: &mut File, file_len: u64, file_out: &mut impl Write, cr
None => GzStreamEncoder::new_default(),
Some(compress_level) => {
if *compress_level > 9 {
return simple_error!("Compress level must in range [0, 9]");
return simple_error!("Compress level must be in range [0, 9]");
}
GzStreamEncoder::new(Compression::new(*compress_level))
}
@@ -221,10 +221,12 @@ fn encrypt_file(file_in: &mut File, file_len: u64, file_out: &mut impl Write, cr
};
opt_result!(file_out.write_all(&last_block_and_tag), "Write file failed: {}");
progress.finish();
debugging!("Encrypt finished, total bytes: {}", total_len);
debugging!("Encrypt finished, total bytes: {} byte(s)", total_len);
if compress {
information!("File is compressed: {} byte(s) -> {} byte(s), ratio: {}%",
total_len, write_len, util::ratio(write_len, total_len));
information!("File is compressed: {} -> {}, ratio: {}%",
util_size::get_display_size(total_len as i64),
util_size::get_display_size(write_len as i64),
util::ratio(write_len, total_len));
}
break;
} else {
@@ -309,11 +311,7 @@ fn encrypt_envelop_shared_secret(cryptor: Cryptor,
cryptor, &key_nonce, key)?;
let wrap_key = WrapKey {
header: WrapKeyHeader {
kid: None,
enc: enc_type.to_string(),
e_pub_key: util::encode_base64_url_no_pad(ephemeral_spki),
},
header: WrapKeyHeader::from(enc_type, ephemeral_spki),
nonce: nonce.0.clone(),
encrypted_data: encrypted_key,
};

View File

@@ -8,7 +8,6 @@ use rust_util::{
debugging, failure, iff, opt_result, simple_error, success,
util_msg, util_size, util_time, XResult,
};
use rust_util::util_msg::MessageType;
use rust_util::util_time::UnixEpochTime;
use simpledateformat::format_human2;
@@ -97,7 +96,7 @@ pub fn info_single(path: &PathBuf, cmd_info: &CmdInfo) -> XResult<()> {
header(&format!("Envelop #{}", i + 1)),
util_envelop::format_envelop(envelop, &config)
));
util_msg::when(MessageType::DEBUG, || {
util_msg::when_debug(|| {
if let Ok(wrap_key) = WrapKey::parse(&envelop.encrypted_key) {
debugging!("Wrap key: {}", serde_json::to_string(&wrap_key).expect("SHOULD NOT HAPPEN"));
}

View File

@@ -74,14 +74,16 @@ fn get_encryptor(crypto: Cryptor, key_nonce: &KeyNonce) -> XResult<Box<dyn Encry
match crypto {
Cryptor::Aes256Gcm => {
let mut key: [u8; 32] = opt_result!(key_nonce.k.try_into(), "Bad AES 256 key: {}");
let aes256_gcm_stream_encryptor = Aes256GcmStreamEncryptor::new(key, key_nonce.n);
let aes256_gcm_stream_encryptor = Aes256GcmStreamEncryptor::new(
key, key_nonce.n);
key.zeroize();
Ok(Box::new(Aes256GcmEncryptor {
aes256_gcm_stream_encryptor,
}))
}
Cryptor::ChaCha20Poly1305 => Ok(Box::new(ChaCha20Poly1305Encryptor {
chacha20_poly1305_stream_encryptor: ChaCha20Poly1305StreamEncryptor::new(key_nonce.k, key_nonce.n)?,
chacha20_poly1305_stream_encryptor: ChaCha20Poly1305StreamEncryptor::new(
key_nonce.k, key_nonce.n)?,
}))
}
}
@@ -90,14 +92,16 @@ fn get_decryptor(crypto: Cryptor, key_nonce: &KeyNonce) -> XResult<Box<dyn Decry
match crypto {
Cryptor::Aes256Gcm => {
let mut key: [u8; 32] = opt_result!(key_nonce.k.try_into(), "Bad AES 256 key: {}");
let aes256_gcm_stream_decryptor = Aes256GcmStreamDecryptor::new(key, key_nonce.n);
let aes256_gcm_stream_decryptor = Aes256GcmStreamDecryptor::new(
key, key_nonce.n);
key.zeroize();
Ok(Box::new(Aes256GcmDecryptor {
aes256_gcm_stream_decryptor,
}))
}
Cryptor::ChaCha20Poly1305 => Ok(Box::new(ChaCha20Poly1305Decryptor {
chacha20_poly1305_stream_decryptor: ChaCha20Poly1305StreamDecryptor::new(key_nonce.k, key_nonce.n)?,
chacha20_poly1305_stream_decryptor: ChaCha20Poly1305StreamDecryptor::new(
key_nonce.k, key_nonce.n)?,
}))
}
}

View File

@@ -96,7 +96,7 @@ pub fn make_key256_and_nonce() -> (SecVec, SecVec) {
pub fn simple_kdf(input: &[u8]) -> Vec<u8> {
let mut input = input.to_vec();
for _ in 0..8 {
let mut sha256 = DigestWrite::sha256().expect("SHOULD NOT HAPPEN");
let mut sha256 = DigestWrite::sha256();
sha256.write_all(&input).expect("SHOULD NOT HAPPEN");
input = sha256.digest();
}

View File

@@ -33,8 +33,8 @@ impl DigestWrite {
}
}
pub fn sha256() -> XResult<Self> {
Ok(Self { digest: Box::new(Sha256::new()) })
pub fn sha256() -> Self {
Self { digest: Box::new(Sha256::new()) }
}
pub fn digest(self) -> Vec<u8> {

View File

@@ -46,7 +46,7 @@ pub fn read_tiny_encrypt_meta(r: &mut impl Read) -> XResult<(u32, TinyEncryptMet
return simple_error!("Meta too large: {}", length);
}
debugging!("Encrypted meta len: {}", length);
debugging!("Encrypted meta length: {}", length);
let mut meta_buff = vec![0; length as usize];
opt_result!(r.read_exact(meta_buff.as_mut_slice()), "Read meta failed: {}");

View File

@@ -7,6 +7,7 @@ use crate::consts;
pub const TINY_ENCRYPT_ENV_DEFAULT_ALGORITHM: &str = "TINY_ENCRYPT_DEFAULT_ALGORITHM";
pub const TINY_ENCRYPT_ENV_DEFAULT_COMPRESS: &str = "TINY_ENCRYPT_DEFAULT_COMPRESS";
pub const TINY_ENCRYPT_ENV_NO_PROGRESS: &str = "TINY_ENCRYPT_NO_PROGRESS";
pub fn get_default_encryption_algorithm() -> Option<&'static str> {
let env_default_algorithm = env::var(TINY_ENCRYPT_ENV_DEFAULT_ALGORITHM).ok();
@@ -24,4 +25,8 @@ pub fn get_default_encryption_algorithm() -> Option<&'static str> {
pub fn get_default_compress() -> Option<bool> {
iff!(rust_util_env::is_env_off(TINY_ENCRYPT_ENV_DEFAULT_COMPRESS), Some(true), None)
}
pub fn get_no_progress() -> bool {
rust_util_env::is_env_on(TINY_ENCRYPT_ENV_NO_PROGRESS)
}

View File

@@ -6,13 +6,13 @@ use rust_util::util_time::UnixEpochTime;
use crate::spec::EncEncryptedMeta;
pub fn update_out_file_time(enc_meta: Option<EncEncryptedMeta>, path_out: &str) {
pub fn update_file_time(enc_meta: Option<EncEncryptedMeta>, path: &str) {
if let Some(enc_meta) = &enc_meta {
let create_time = enc_meta.c_time.map(SystemTime::from_millis);
let modify_time = enc_meta.m_time.map(SystemTime::from_millis);
if create_time.is_some() || modify_time.is_some() {
let set_times_result = fs_set_times::set_times(
path_out,
path,
create_time.map(SystemTimeSpec::Absolute),
modify_time.map(SystemTimeSpec::Absolute),
);

View File

@@ -1,28 +1,46 @@
use indicatif::{ProgressBar, ProgressStyle};
use rust_util::{debugging, util_msg};
use crate::util_env;
const PB_PROGRESS: &str = "#-";
const PB_TEMPLATE: &str = "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes} {bytes_per_sec} ({eta})";
pub struct Progress {
progress_bar: ProgressBar,
pub enum Progress {
NoProgress,
Progress(ProgressBar),
}
impl Progress {
pub fn new(total: u64) -> Self {
let progress_bar = ProgressBar::new(total);
progress_bar.set_style(ProgressStyle::default_bar()
.template(PB_TEMPLATE).expect("SHOULD NOT FAIL")
.progress_chars(PB_PROGRESS)
);
Self { progress_bar }
let no_progress = util_env::get_no_progress();
let is_atty = util_msg::is_atty();
if no_progress || !is_atty {
debugging!("No progress: [{}, {}]", no_progress, is_atty);
Self::NoProgress
} else {
let progress_bar = ProgressBar::new(total);
progress_bar.set_style(ProgressStyle::default_bar()
.template(PB_TEMPLATE).expect("SHOULD NOT FAIL")
.progress_chars(PB_PROGRESS)
);
Self::Progress(progress_bar)
}
}
pub fn position(&self, position: u64) {
self.progress_bar.set_position(position)
match self {
Progress::NoProgress => {}
Progress::Progress(progress_bar) => progress_bar.set_position(position),
}
}
pub fn finish(&self) {
self.progress_bar.finish_and_clear()
match self {
Progress::NoProgress => {}
Progress::Progress(progress_bar) => progress_bar.finish_and_clear(),
}
}
}

View File

@@ -1,7 +1,7 @@
use rust_util::{opt_result, simple_error, XResult};
use serde::{Deserialize, Serialize};
use crate::util::{decode_base64_url_no_pad, encode_base64_url_no_pad};
use crate::util;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
@@ -20,17 +20,31 @@ pub struct WrapKeyHeader {
pub e_pub_key: String,
}
impl WrapKeyHeader {
pub fn from(enc_type: &str, ephemeral_spki: &[u8]) -> Self {
WrapKeyHeader {
kid: None,
enc: enc_type.to_string(),
e_pub_key: util::encode_base64_url_no_pad(ephemeral_spki),
}
}
pub fn get_e_pub_key_bytes(self) -> XResult<Vec<u8>> {
Ok(opt_result!(util::decode_base64_url_no_pad(&self.e_pub_key), "Invalid envelop e_pub_key: {}"))
}
}
impl WrapKey {
pub fn encode(&self) -> XResult<String> {
let mut buf = String::with_capacity(512);
buf.push_str("WK:");
let header = serde_json::to_string(&self.header)?;
let header_str = encode_base64_url_no_pad(header.as_bytes());
let header_str = util::encode_base64_url_no_pad(header.as_bytes());
buf.push_str(&header_str);
buf.push('.');
buf.push_str(&encode_base64_url_no_pad(&self.nonce));
buf.push_str(&util::encode_base64_url_no_pad(&self.nonce));
buf.push('.');
buf.push_str(&encode_base64_url_no_pad(&self.encrypted_data));
buf.push_str(&util::encode_base64_url_no_pad(&self.encrypted_data));
Ok(buf)
}
@@ -43,13 +57,13 @@ impl WrapKey {
return simple_error!("Invalid wrap key.");
}
let header = wks[0].chars().skip(3).collect::<String>();
let header_bytes = opt_result!(decode_base64_url_no_pad(&header), "Invalid wrap key header: {}");
let header_bytes = opt_result!(util::decode_base64_url_no_pad(&header), "Invalid wrap key header: {}");
let nonce = wks[1];
let encrypted_data = wks[2];
let header_str = opt_result!(String::from_utf8(header_bytes), "Invalid wrap key header: {}");
let header: WrapKeyHeader = opt_result!(serde_json::from_str(&header_str), "Invalid wrap key header: {}");
let nonce = opt_result!(decode_base64_url_no_pad(nonce), "Invalid wrap key: {}");
let encrypted_data = opt_result!(decode_base64_url_no_pad(encrypted_data), "Invalid wrap key: {}");
let nonce = opt_result!(util::decode_base64_url_no_pad(nonce), "Invalid wrap key: {}");
let encrypted_data = opt_result!(util::decode_base64_url_no_pad(encrypted_data), "Invalid wrap key: {}");
Ok(WrapKey {
header,
nonce,