feat: v0.3.3, optimize code
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -2144,7 +2144,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-encrypt"
|
name = "tiny-encrypt"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm-stream",
|
"aes-gcm-stream",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tiny-encrypt"
|
name = "tiny-encrypt"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "A simple and tiny file encrypt tool"
|
description = "A simple and tiny file encrypt tool"
|
||||||
@@ -11,9 +11,9 @@ description = "A simple and tiny file encrypt tool"
|
|||||||
aes-gcm-stream = "0.2"
|
aes-gcm-stream = "0.2"
|
||||||
base64 = "0.21"
|
base64 = "0.21"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
clap = { version = "4.1", features = ["derive"] }
|
clap = { version = "4.4", features = ["derive"] }
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
fs-set-times = "0.20.0"
|
fs-set-times = "0.20"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
openpgp-card = "0.3"
|
openpgp-card = "0.3"
|
||||||
openpgp-card-pcsc = "0.3"
|
openpgp-card-pcsc = "0.3"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{fs, io};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::{Instant, SystemTime};
|
use std::time::{Instant, SystemTime};
|
||||||
@@ -113,9 +113,10 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
|
|||||||
if cmd_decrypt.skip_decrypt_file {
|
if cmd_decrypt.skip_decrypt_file {
|
||||||
information!("Decrypt file is skipped.");
|
information!("Decrypt file is skipped.");
|
||||||
} else {
|
} else {
|
||||||
|
let compressed_desc = iff!(meta.compress, " [compressed]", "");
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
util_msg::print_lastline(
|
util_msg::print_lastline(
|
||||||
&format!("Decrypting file: {}{} ...", path_display, iff!(meta.compress, " [compressed]", ""))
|
&format!("Decrypting file: {}{} ...", path_display, compressed_desc)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut file_out = File::create(path_out)?;
|
let mut file_out = File::create(path_out)?;
|
||||||
@@ -125,18 +126,13 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
|
|||||||
|
|
||||||
update_out_file_time(enc_meta, path_out);
|
update_out_file_time(enc_meta, path_out);
|
||||||
let encrypt_duration = start.elapsed();
|
let encrypt_duration = start.elapsed();
|
||||||
debugging!("Inner decrypt file: {} elapsed: {} ms", path_display, encrypt_duration.as_millis());
|
debugging!("Inner decrypt file{}: {} elapsed: {} ms", compressed_desc, path_display, encrypt_duration.as_millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
util::zeroize(key);
|
util::zeroize(key);
|
||||||
util::zeroize(nonce);
|
util::zeroize(nonce);
|
||||||
drop(file_in);
|
drop(file_in);
|
||||||
if cmd_decrypt.remove_file {
|
if cmd_decrypt.remove_file { util::remove_file_with_msg(path); }
|
||||||
match fs::remove_file(path) {
|
|
||||||
Err(e) => warning!("Remove file: {} failed: {}", path_display, e),
|
|
||||||
Ok(_) => information!("Remove file: {} succeed", path_display),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(meta.file_length)
|
Ok(meta.file_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,13 +175,13 @@ fn decrypt_file(file_in: &mut File, file_out: &mut File, key: &[u8], nonce: &[u8
|
|||||||
|
|
||||||
fn update_out_file_time(enc_meta: Option<EncEncryptedMeta>, path_out: &str) {
|
fn update_out_file_time(enc_meta: Option<EncEncryptedMeta>, path_out: &str) {
|
||||||
if let Some(enc_meta) = &enc_meta {
|
if let Some(enc_meta) = &enc_meta {
|
||||||
let create_time = enc_meta.c_time.map(|t| SystemTime::from_millis(t));
|
let create_time = enc_meta.c_time.map(SystemTime::from_millis);
|
||||||
let modify_time = enc_meta.m_time.map(|t| SystemTime::from_millis(t));
|
let modify_time = enc_meta.m_time.map(SystemTime::from_millis);
|
||||||
if create_time.is_some() || modify_time.is_some() {
|
if create_time.is_some() || modify_time.is_some() {
|
||||||
let set_times_result = fs_set_times::set_times(
|
let set_times_result = fs_set_times::set_times(
|
||||||
path_out,
|
path_out,
|
||||||
create_time.map(|t| SystemTimeSpec::Absolute(t)),
|
create_time.map(SystemTimeSpec::Absolute),
|
||||||
modify_time.map(|t| SystemTimeSpec::Absolute(t)),
|
modify_time.map(SystemTimeSpec::Absolute),
|
||||||
);
|
);
|
||||||
match set_times_result {
|
match set_times_result {
|
||||||
Ok(_) => information!("Set file time succeed."),
|
Ok(_) => information!("Set file time succeed."),
|
||||||
@@ -199,7 +195,7 @@ fn parse_encrypted_comment(meta: &TinyEncryptMeta, key: &[u8], nonce: &[u8]) ->
|
|||||||
if let Some(encrypted_comment) = &meta.encrypted_comment {
|
if let Some(encrypted_comment) = &meta.encrypted_comment {
|
||||||
match util::decode_base64(encrypted_comment) {
|
match util::decode_base64(encrypted_comment) {
|
||||||
Err(e) => warning!("Decode encrypted comment failed: {}", e),
|
Err(e) => warning!("Decode encrypted comment failed: {}", e),
|
||||||
Ok(ec_bytes) => match try_aes_gcm_decrypt_with_salt(&key, &nonce, SALT_COMMENT, &ec_bytes) {
|
Ok(ec_bytes) => match try_aes_gcm_decrypt_with_salt(key, nonce, SALT_COMMENT, &ec_bytes) {
|
||||||
Err(e) => warning!("Decrypt encrypted comment failed: {}", e),
|
Err(e) => warning!("Decrypt encrypted comment failed: {}", e),
|
||||||
Ok(decrypted_comment_bytes) => match String::from_utf8(decrypted_comment_bytes.clone()) {
|
Ok(decrypted_comment_bytes) => match String::from_utf8(decrypted_comment_bytes.clone()) {
|
||||||
Err(_) => success!("Encrypted message hex: {}", hex::encode(&decrypted_comment_bytes)),
|
Err(_) => success!("Encrypted message hex: {}", hex::encode(&decrypted_comment_bytes)),
|
||||||
@@ -218,7 +214,7 @@ fn parse_encrypted_meta(meta: &TinyEncryptMeta, key: &[u8], nonce: &[u8]) -> XRe
|
|||||||
let enc_encrypted_meta_bytes = opt_result!(
|
let enc_encrypted_meta_bytes = opt_result!(
|
||||||
util::decode_base64(enc_encrypted_meta), "Decode enc-encrypted-meta failed: {}");
|
util::decode_base64(enc_encrypted_meta), "Decode enc-encrypted-meta failed: {}");
|
||||||
let enc_meta = opt_result!(
|
let enc_meta = opt_result!(
|
||||||
EncEncryptedMeta::unseal(&key, &nonce, &enc_encrypted_meta_bytes), "Unseal enc-encrypted-meta failed: {}");
|
EncEncryptedMeta::unseal(key, nonce, &enc_encrypted_meta_bytes), "Unseal enc-encrypted-meta failed: {}");
|
||||||
if let Some(filename) = &enc_meta.filename {
|
if let Some(filename) = &enc_meta.filename {
|
||||||
information!("Source filename: {}", filename);
|
information!("Source filename: {}", filename);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::time::Instant;
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
use flate2::Compression;
|
use flate2::Compression;
|
||||||
use rsa::Pkcs1v15Encrypt;
|
use rsa::Pkcs1v15Encrypt;
|
||||||
use rust_util::{debugging, failure, information, opt_result, simple_error, success, util_msg, warning, XResult};
|
use rust_util::{debugging, failure, iff, information, opt_result, simple_error, success, util_msg, XResult};
|
||||||
use rust_util::util_time::UnixEpochTime;
|
use rust_util::util_time::UnixEpochTime;
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
@@ -125,8 +125,8 @@ fn encrypt_single(path: &PathBuf, envelops: &[&TinyEncryptConfigEnvelop], cmd_en
|
|||||||
let file_metadata = opt_result!(fs::metadata(path), "Read file: {} meta failed: {}", path.display());
|
let file_metadata = opt_result!(fs::metadata(path), "Read file: {} meta failed: {}", path.display());
|
||||||
let enc_encrypted_meta = EncEncryptedMeta {
|
let enc_encrypted_meta = EncEncryptedMeta {
|
||||||
filename: Some(util::get_file_name(path)),
|
filename: Some(util::get_file_name(path)),
|
||||||
c_time: file_metadata.created().ok().map(|t| t.to_millis()).flatten(),
|
c_time: file_metadata.created().ok().and_then(|t| t.to_millis()),
|
||||||
m_time: file_metadata.modified().ok().map(|t| t.to_millis()).flatten(),
|
m_time: file_metadata.modified().ok().and_then(|t| t.to_millis()),
|
||||||
};
|
};
|
||||||
let enc_encrypted_meta_bytes = opt_result!(enc_encrypted_meta.seal(&key, &nonce), "Seal enc-encrypted-meta failed: {}");
|
let enc_encrypted_meta_bytes = opt_result!(enc_encrypted_meta.seal(&key, &nonce), "Seal enc-encrypted-meta failed: {}");
|
||||||
|
|
||||||
@@ -141,10 +141,35 @@ fn encrypt_single(path: &PathBuf, envelops: &[&TinyEncryptConfigEnvelop], cmd_en
|
|||||||
debugging!("Encrypted meta: {:?}", encrypt_meta);
|
debugging!("Encrypted meta: {:?}", encrypt_meta);
|
||||||
|
|
||||||
if cmd_encrypt.compatible_with_1_0 {
|
if cmd_encrypt.compatible_with_1_0 {
|
||||||
|
encrypt_meta = process_compatible_with_1_0(cmd_encrypt, encrypt_meta)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut file_out = File::create(&path_out)?;
|
||||||
|
let compress_meta = !cmd_encrypt.disable_compress_meta;
|
||||||
|
let _ = file::write_tiny_encrypt_meta(&mut file_out, &encrypt_meta, compress_meta)?;
|
||||||
|
|
||||||
|
let compress_desc = iff!(cmd_encrypt.compress, " [with compress]", "");
|
||||||
|
let start = Instant::now();
|
||||||
|
util_msg::print_lastline(
|
||||||
|
&format!("Encrypting file: {}{} ...", path_display, compress_desc)
|
||||||
|
);
|
||||||
|
encrypt_file(&mut file_in, &mut file_out, &key, &nonce, cmd_encrypt.compress, &cmd_encrypt.compress_level)?;
|
||||||
|
util_msg::clear_lastline();
|
||||||
|
let encrypt_duration = start.elapsed();
|
||||||
|
debugging!("Inner encrypt file{}: {} elapsed: {} ms", compress_desc, path_display, encrypt_duration.as_millis());
|
||||||
|
|
||||||
|
util::zeroize(key);
|
||||||
|
util::zeroize(nonce);
|
||||||
|
drop(file_in);
|
||||||
|
drop(file_out);
|
||||||
|
if cmd_encrypt.remove_file { util::remove_file_with_msg(path); }
|
||||||
|
Ok(file_metadata.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_compatible_with_1_0(cmd_encrypt: &CmdEncrypt, mut encrypt_meta: TinyEncryptMeta) -> XResult<TinyEncryptMeta> {
|
||||||
if !cmd_encrypt.disable_compress_meta {
|
if !cmd_encrypt.disable_compress_meta {
|
||||||
return simple_error!("Compatible with 1.0 mode must turns --disable-compress-meta on.");
|
return simple_error!("Compatible with 1.0 mode must turns --disable-compress-meta on.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(envelops) = encrypt_meta.envelops {
|
if let Some(envelops) = encrypt_meta.envelops {
|
||||||
let mut filter_envelops = vec![];
|
let mut filter_envelops = vec![];
|
||||||
for envelop in envelops {
|
for envelop in envelops {
|
||||||
@@ -163,33 +188,9 @@ fn encrypt_single(path: &PathBuf, envelops: &[&TinyEncryptConfigEnvelop], cmd_en
|
|||||||
encrypt_meta.version = TINY_ENCRYPT_VERSION_10.to_string();
|
encrypt_meta.version = TINY_ENCRYPT_VERSION_10.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(encrypt_meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut file_out = File::create(&path_out)?;
|
|
||||||
let compress_meta = !cmd_encrypt.disable_compress_meta;
|
|
||||||
let _ = file::write_tiny_encrypt_meta(&mut file_out, &encrypt_meta, compress_meta)?;
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
util_msg::print_lastline(&format!("Encrypting file: {} ...", path_display));
|
|
||||||
encrypt_file(&mut file_in, &mut file_out, &key, &nonce, cmd_encrypt.compress, &cmd_encrypt.compress_level)?;
|
|
||||||
util_msg::clear_lastline();
|
|
||||||
let encrypt_duration = start.elapsed();
|
|
||||||
debugging!("Encrypt file: {} elapsed: {} ms", path_display, encrypt_duration.as_millis());
|
|
||||||
|
|
||||||
util::zeroize(key);
|
|
||||||
util::zeroize(nonce);
|
|
||||||
drop(file_in);
|
|
||||||
drop(file_out);
|
|
||||||
if cmd_encrypt.remove_file {
|
|
||||||
match fs::remove_file(path) {
|
|
||||||
Err(e) => warning!("Remove file: {} failed: {}", path_display, e),
|
|
||||||
Ok(_) => information!("Remove file: {} succeed", path_display),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(file_metadata.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn encrypt_file(file_in: &mut File, file_out: &mut File, key: &[u8], nonce: &[u8], compress: bool, compress_level: &Option<u32>) -> XResult<usize> {
|
fn encrypt_file(file_in: &mut File, file_out: &mut File, key: &[u8], nonce: &[u8], compress: bool, compress_level: &Option<u32>) -> XResult<usize> {
|
||||||
let mut total_len = 0;
|
let mut total_len = 0;
|
||||||
let mut buffer = [0u8; 1024 * 8];
|
let mut buffer = [0u8; 1024 * 8];
|
||||||
|
|||||||
11
src/util.rs
11
src/util.rs
@@ -1,15 +1,22 @@
|
|||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use base64::engine::general_purpose;
|
use base64::engine::general_purpose;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
use rust_util::{simple_error, warning, XResult};
|
use rust_util::{information, simple_error, warning, XResult};
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
use crate::consts::TINY_ENC_FILE_EXT;
|
use crate::consts::TINY_ENC_FILE_EXT;
|
||||||
|
|
||||||
|
pub fn remove_file_with_msg(path: &PathBuf) {
|
||||||
|
match fs::remove_file(path) {
|
||||||
|
Err(e) => warning!("Remove file: {} failed: {}", path.display(), e),
|
||||||
|
Ok(_) => information!("Remove file: {} succeed", path.display()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_file_name(path: &Path) -> String {
|
pub fn get_file_name(path: &Path) -> String {
|
||||||
let path_display = format!("{}", path.display());
|
let path_display = format!("{}", path.display());
|
||||||
if path_display.contains('/') {
|
if path_display.contains('/') {
|
||||||
|
|||||||
Reference in New Issue
Block a user