Day 3 - Rust File Encryptor/Decryptor

Rust's encryption basics with our file encryptor/decryptor. Learn file I/O, XOR encryption, and CLI usage in a concise project.


Introduction

Today, we're diving into the world of security with Rust by creating a simple file encryptor/decryptor. We'll use a basic XOR cipher for encryption, but remember, this is for educational purposes; never use this for actual secure data due to its simplicity.

Prerequisites

  • Basic understanding of Rust
  • Familiarity with file I/O operations
  • Concept of encryption (even if basic)

Project Structure

Let's set up our project first:

mkdir rust-file-encryptor
cd rust-file-encryptor
cargo init --bin

Now, let’s define our folder structure:

rust-file-encryptor/
│
├── src/
│   ├── main.rs
│   ├── cli.rs
│   ├── encryption.rs
│   └── io.rs
│
├── Cargo.toml
└── README.md

Step 1: Setting up Cargo.toml

[package]
name = "file_encryptor"
version = "0.1.0"
edition = "2018"
 
[dependencies]
structopt = "0.3"

Step 2: cli.rs - Handling Command Line Arguments

use structopt::StructOpt;
 
#[derive(StructOpt)]
struct Cli {
    #[structopt(parse(from_os_str))]
    input: std::path::PathBuf,
    #[structopt(short, long)]
    decrypt: bool,
}
 
pub fn parse_args() -> Cli {
    Cli::from_args()
}

Step 3: encryption.rs - Encryption Logic

pub fn encrypt_decrypt(data: &mut [u8], key: u8) {
    data.iter_mut().for_each(|byte| *byte ^= key);
}
 
pub fn get_key() -> u8 {
    42 // A simple key for demonstration
}

Step 4: io.rs - File Operations

use std::fs;
use std::io::{Read, Write};
 
pub fn read_file(path: &std::path::Path) -> Result<Vec<u8>, std::io::Error> {
    let mut file = fs::File::open(path)?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer)?;
    Ok(buffer)
}
 
pub fn write_file(path: &std::path::Path, data: &[u8]) -> Result<(), std::io::Error> {
    let mut file = fs::File::create(path)?;
    file.write_all(data)?;
    Ok(())
}

Step 5: main.rs - Tying It All Together

mod cli;
mod encryption;
mod io;
 
use std::path::Path;
 
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args = cli::parse_args();
    let key = encryption::get_key();
    let mut data = io::read_file(&args.input)?;
 
    if args.decrypt {
        encryption::encrypt_decrypt(&mut data, key);
        let output_path = args.input.with_extension("decrypted");
        io::write_file(&output_path, &data)?;
        println!("Decrypted file saved to: {:?}", output_path);
    } else {
        encryption::encrypt_decrypt(&mut data, key);
        let output_path = args.input.with_extension("encrypted");
        io::write_file(&output_path, &data)?;
        println!("Encrypted file saved to: {:?}", output_path);
    }
 
    Ok(())
}

Step 6: Usage

To run your encryptor:

cargo run -- --input /path/to/file.txt
cargo run -- --input /path/to/file.txt --decrypt

Explanation

  • CLI Parsing: We use structopt to handle command-line arguments, allowing users to specify files for encryption or decryption.
  • Encryption Logic: We've used a simple XOR operation for demonstrating encryption. XOR with the same key twice will decrypt the data, making this method symmetric.
  • File I/O: The io module handles reading from and writing to files, ensuring we deal with file operations gracefully.
  • Main: Our main function reads the file, applies encryption or decryption based on the user's choice, and then writes the result back to a new file.

Conclusion

This project not only introduces you to basic encryption concepts in Rust but also teaches you about file handling, command-line interfaces, and modular programming. Remember, this is a stepping stone towards understanding more complex encryption algorithms like AES or RSA in future projects.

Feel free to extend this project by:

  • Implementing more secure encryption methods.
  • Adding error handling for common issues like file not found or permission denied.
  • Creating a GUI interface using something like egui for a visual component to the encryptor/decryptor.

This step-by-step guide should have you encrypting and decrypting files with Rust in no time!