Added Parallelism, also cleaned up code a bit
This commit is contained in:
153
src/main.rs
153
src/main.rs
@@ -9,7 +9,9 @@ use std::{
|
|||||||
fs::File,
|
fs::File,
|
||||||
io,
|
io,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
// time::SystemTime,
|
sync::Arc, // time::SystemTime,
|
||||||
|
thread,
|
||||||
|
thread::{available_parallelism, JoinHandle},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -22,10 +24,10 @@ const BUFFER_LEN: usize = 50 * 1024 * 1024; // 50 MiB
|
|||||||
fn encrypt_file(
|
fn encrypt_file(
|
||||||
source_path: String,
|
source_path: String,
|
||||||
dest_path: String,
|
dest_path: String,
|
||||||
nonce: &[u8; 24],
|
nonce: [u8; 24],
|
||||||
key: &Vec<u8>,
|
key: &[u8],
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut cipher = XChaCha20::new(key[..32].as_ref().into(), nonce.into());
|
let mut cipher = XChaCha20::new(key[..32].as_ref().into(), &nonce.into());
|
||||||
|
|
||||||
let source_file_path = Path::new(&source_path);
|
let source_file_path = Path::new(&source_path);
|
||||||
|
|
||||||
@@ -48,10 +50,12 @@ fn encrypt_file(
|
|||||||
// Stack allocated buffer
|
// Stack allocated buffer
|
||||||
// let mut buffer = [0u8; BUFFER_LEN];
|
// let mut buffer = [0u8; BUFFER_LEN];
|
||||||
|
|
||||||
|
println!("Start encrypting File: {}", file_name.to_str().unwrap());
|
||||||
|
|
||||||
// Heap allocated buffer (Allows larger sized buffer, up to 50 % max ram)
|
// Heap allocated buffer (Allows larger sized buffer, up to 50 % max ram)
|
||||||
let mut buffer = vec![0u8; BUFFER_LEN].into_boxed_slice();
|
let mut buffer = vec![0u8; BUFFER_LEN].into_boxed_slice();
|
||||||
|
|
||||||
dest_file.write(nonce)?;
|
dest_file.write(&nonce)?;
|
||||||
|
|
||||||
let mut f_name_bytes = file_name.to_str().unwrap_or_default().as_bytes().to_owned();
|
let mut f_name_bytes = file_name.to_str().unwrap_or_default().as_bytes().to_owned();
|
||||||
|
|
||||||
@@ -83,29 +87,23 @@ fn encrypt_file(
|
|||||||
|
|
||||||
fs::remove_file(source_file_path)?;
|
fs::remove_file(source_file_path)?;
|
||||||
|
|
||||||
return Ok(());
|
println!("Finished encrypting File: {}", file_name.to_str().unwrap());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt_file(source_path: String, pwd: &String, config: &argon2::Config) -> io::Result<()> {
|
fn decrypt_file(source_path: &Path, pwd: &String, config: &argon2::Config) -> io::Result<()> {
|
||||||
let mut nonce = [0u8; 24];
|
let mut nonce = [0u8; 24];
|
||||||
|
|
||||||
let path_info = Path::new(&source_path);
|
if !source_path.try_exists()? {
|
||||||
|
|
||||||
if !path_info.try_exists()? {
|
|
||||||
return Err(io::Error::from(io::ErrorKind::NotFound));
|
return Err(io::Error::from(io::ErrorKind::NotFound));
|
||||||
}
|
}
|
||||||
|
|
||||||
//let path = &source_path[..&source_path.len() - 4];
|
|
||||||
|
|
||||||
// if Path::new(&path).exists() {
|
|
||||||
// fs::remove_file(&path)?;
|
|
||||||
// }
|
|
||||||
|
|
||||||
let mut source_file = File::open(&source_path)?;
|
let mut source_file = File::open(&source_path)?;
|
||||||
|
|
||||||
source_file.read(&mut nonce)?;
|
source_file.read(&mut nonce)?;
|
||||||
|
|
||||||
let key = argon2::hash_raw(pwd.as_bytes(), &nonce, &config).unwrap();
|
let key = argon2::hash_raw(pwd.as_bytes(), &nonce, config).unwrap();
|
||||||
|
|
||||||
let mut cipher = XChaCha20::new(key[..32].as_ref().into(), &nonce.into());
|
let mut cipher = XChaCha20::new(key[..32].as_ref().into(), &nonce.into());
|
||||||
|
|
||||||
@@ -116,14 +114,12 @@ fn decrypt_file(source_path: String, pwd: &String, config: &argon2::Config) -> i
|
|||||||
source_file.read(&mut file_name_size_buffer)?;
|
source_file.read(&mut file_name_size_buffer)?;
|
||||||
let file_name_size = u16::from_le_bytes(file_name_size_buffer);
|
let file_name_size = u16::from_le_bytes(file_name_size_buffer);
|
||||||
|
|
||||||
println!("File Name Size: {file_name_size}");
|
|
||||||
|
|
||||||
let mut file_name_bytes = vec![0u8; file_name_size.into()];
|
let mut file_name_bytes = vec![0u8; file_name_size.into()];
|
||||||
source_file.read_exact(&mut file_name_bytes)?;
|
source_file.read_exact(&mut file_name_bytes)?;
|
||||||
|
|
||||||
cipher.apply_keystream(&mut file_name_bytes);
|
cipher.apply_keystream(&mut file_name_bytes);
|
||||||
|
|
||||||
let private_dir_path = match path_info.parent() {
|
let private_dir_path = match source_path.parent() {
|
||||||
Some(p) => Ok(p),
|
Some(p) => Ok(p),
|
||||||
None => Err(io::Error::from(io::ErrorKind::AddrNotAvailable)),
|
None => Err(io::Error::from(io::ErrorKind::AddrNotAvailable)),
|
||||||
}?;
|
}?;
|
||||||
@@ -134,22 +130,18 @@ fn decrypt_file(source_path: String, pwd: &String, config: &argon2::Config) -> i
|
|||||||
}?;
|
}?;
|
||||||
|
|
||||||
let file_name = String::from_utf8(file_name_bytes).unwrap_or_default();
|
let file_name = String::from_utf8(file_name_bytes).unwrap_or_default();
|
||||||
let path = root_dir_path.join(&file_name); //to_str().unwrap_or_default().to_owned() + &file_name;
|
let path = root_dir_path.join(&file_name);
|
||||||
|
|
||||||
println!("File Name: {file_name}\n Path: {path:?}");
|
println!("Start decrypting File: {file_name}");
|
||||||
|
|
||||||
let mut dest_file = File::create(path)?;
|
let mut dest_file = File::create(path)?;
|
||||||
|
|
||||||
println!("Worked!");
|
// Heap allocated buffer (Allows larger sized buffer, up to 50 % max ram, technically more)
|
||||||
|
|
||||||
// Heap allocated buffer (Allows larger sized buffer, up to 50 % max ram)
|
|
||||||
let mut buffer = vec![0u8; BUFFER_LEN].into_boxed_slice();
|
let mut buffer = vec![0u8; BUFFER_LEN].into_boxed_slice();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let read_count = source_file.read(&mut buffer)?;
|
let read_count = source_file.read(&mut buffer)?;
|
||||||
|
|
||||||
println!("Read Bytes {read_count}");
|
|
||||||
|
|
||||||
if read_count == BUFFER_LEN {
|
if read_count == BUFFER_LEN {
|
||||||
cipher.apply_keystream(&mut buffer);
|
cipher.apply_keystream(&mut buffer);
|
||||||
dest_file.write(&buffer)?;
|
dest_file.write(&buffer)?;
|
||||||
@@ -160,43 +152,77 @@ fn decrypt_file(source_path: String, pwd: &String, config: &argon2::Config) -> i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Fully written");
|
println!("Finished decrypting File: {file_name}");
|
||||||
return Ok(());
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
let config = argon2::Config {
|
let config = Arc::new(argon2::Config {
|
||||||
variant: argon2::Variant::Argon2id,
|
variant: argon2::Variant::Argon2id,
|
||||||
hash_length: 32,
|
hash_length: 32,
|
||||||
lanes: 8,
|
lanes: 8,
|
||||||
mem_cost: 16 * 1024,
|
mem_cost: 16 * 1024,
|
||||||
time_cost: 8,
|
time_cost: 8,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
});
|
||||||
|
|
||||||
let exe = env::current_exe().unwrap();
|
let exe = env::current_exe().unwrap();
|
||||||
let cwd = env::current_dir().unwrap();
|
let cwd = env::current_dir().unwrap();
|
||||||
let private = cwd.join("private");
|
let private = cwd.join("private");
|
||||||
|
|
||||||
|
let mut max_threads: usize = available_parallelism().unwrap().into();
|
||||||
|
|
||||||
|
let percent = max_threads as f32 * 0.7;
|
||||||
|
max_threads = percent.floor() as usize;
|
||||||
|
|
||||||
|
if max_threads < 1 {
|
||||||
|
max_threads = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Parallelism: {max_threads}");
|
||||||
|
|
||||||
if private.exists() {
|
if private.exists() {
|
||||||
let paths = fs::read_dir(&private).unwrap();
|
let paths = fs::read_dir(&private).unwrap();
|
||||||
|
|
||||||
print!("Type password for encrypted files: ");
|
print!("Type password for encrypted files: ");
|
||||||
std::io::stdout().flush().unwrap();
|
std::io::stdout().flush().unwrap();
|
||||||
let pwd = read_password().unwrap();
|
let pwd = Arc::new(read_password().unwrap());
|
||||||
|
|
||||||
|
let config = Arc::new(config);
|
||||||
|
|
||||||
|
let mut handles: Vec<JoinHandle<()>> = Vec::with_capacity(max_threads);
|
||||||
|
|
||||||
|
let mut current_threads = 0;
|
||||||
|
|
||||||
for path_result in paths {
|
for path_result in paths {
|
||||||
let path = path_result.unwrap().path();
|
let path = path_result.unwrap().path();
|
||||||
|
let pwd = pwd.clone();
|
||||||
|
let config = config.clone();
|
||||||
|
|
||||||
if path.is_file() {
|
handles.push(thread::spawn(move || {
|
||||||
decrypt_file(String::from(path.to_str().unwrap()), &pwd, &config)?;
|
if path.is_file() {
|
||||||
fs::remove_file(String::from(path.to_str().unwrap()))?;
|
decrypt_file(path.as_path(), &pwd, &config).unwrap();
|
||||||
|
fs::remove_file(String::from(path.to_str().unwrap())).unwrap();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
current_threads += 1;
|
||||||
|
|
||||||
|
if current_threads >= max_threads {
|
||||||
|
while let Some(handle) = handles.pop() {
|
||||||
|
handle.join().unwrap();
|
||||||
|
current_threads -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if current_threads > 0 {
|
||||||
|
while let Some(handle) = handles.pop() {
|
||||||
|
handle.join().unwrap();
|
||||||
|
current_threads -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::remove_dir(private)?;
|
fs::remove_dir(private)?;
|
||||||
|
|
||||||
//fs::remove_dir_all(private).unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
let paths = fs::read_dir(&cwd).unwrap();
|
let paths = fs::read_dir(&cwd).unwrap();
|
||||||
|
|
||||||
@@ -222,26 +248,57 @@ fn main() -> io::Result<()> {
|
|||||||
|
|
||||||
print!("Type password to encrypt files: ");
|
print!("Type password to encrypt files: ");
|
||||||
std::io::stdout().flush().unwrap();
|
std::io::stdout().flush().unwrap();
|
||||||
let pwd = read_password().unwrap();
|
let pwd = Arc::new(read_password().unwrap());
|
||||||
|
|
||||||
let mut nonce = [0u8; 24];
|
let mut nonce = [0u8; 24];
|
||||||
OsRng.fill_bytes(&mut nonce);
|
OsRng.fill_bytes(&mut nonce);
|
||||||
|
|
||||||
let key = argon2::hash_raw(pwd.as_bytes(), &nonce, &config).unwrap();
|
// let key = Arc::new(argon2::hash_raw(pwd.as_bytes(), &nonce, &config).unwrap());
|
||||||
|
|
||||||
let paths = fs::read_dir(cwd).unwrap();
|
let paths = fs::read_dir(cwd).unwrap();
|
||||||
|
let exe = Arc::new(exe);
|
||||||
|
let private = Arc::new(private);
|
||||||
|
|
||||||
|
let mut handles: Vec<JoinHandle<()>> = Vec::with_capacity(max_threads);
|
||||||
|
let mut current_threads = 0;
|
||||||
|
|
||||||
for path_result in paths {
|
for path_result in paths {
|
||||||
let path = path_result.unwrap().path();
|
let pwd = pwd.clone();
|
||||||
|
let exe = exe.clone();
|
||||||
|
let private = private.clone();
|
||||||
|
let config = config.clone();
|
||||||
|
|
||||||
if path.is_file() && path != exe {
|
handles.push(thread::spawn(move || {
|
||||||
encrypt_file(
|
let mut nonce = [0u8; 24];
|
||||||
String::from(path.to_str().unwrap()),
|
OsRng.fill_bytes(&mut nonce);
|
||||||
String::from(private.to_str().unwrap()),
|
let key = argon2::hash_raw(pwd.as_bytes(), &nonce, &config).unwrap();
|
||||||
&nonce,
|
|
||||||
&key,
|
let path = path_result.unwrap().path();
|
||||||
)
|
|
||||||
.unwrap();
|
if path.is_file() && path.as_os_str() != exe.as_os_str() {
|
||||||
|
encrypt_file(
|
||||||
|
String::from(path.to_str().unwrap()),
|
||||||
|
String::from(private.to_str().unwrap()),
|
||||||
|
nonce,
|
||||||
|
&key,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
current_threads += 1;
|
||||||
|
|
||||||
|
if current_threads >= max_threads {
|
||||||
|
while let Some(handle) = handles.pop() {
|
||||||
|
handle.join().unwrap();
|
||||||
|
current_threads -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if current_threads > 0 {
|
||||||
|
while let Some(handle) = handles.pop() {
|
||||||
|
handle.join().unwrap();
|
||||||
|
current_threads -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user