Rust AES

In cryptography AES is a titan of an algorithm, standing for Advanced Encryption Standard, it despite being made over 20 years ago is still the go to algorithm, used as a foundational piece in modern quantum resistant communications. In fact, it might be fair to say that AES-256 (A 256 bit key) is inherently quantum resistant, despite not being made for that purpose. I decided to make my own implementation of the algorithm following the FIPS 197 specification in Rust. Rather than using hardware AES instructions, by targeting compilation systems, and calling assembly directly I wanted to follow the pseudocode more directly. The project focused on idiomatic Rust, high performance, and keeping to the algorithm as described in the document. The program is a CLI tool that uses I/O from the file system (i.e. hard drive/ssd), processes it, and writes the encrypted or decrypted output. Since file I/O tends to be the main performance bottleneck, multithreading can only do so much. Despite this, I implemented a system that allows files to be prefetched and loaded while computation is being done on other files. This overlap between computation and I/O helps maximize performance within hardware limits, trying to optimize around the I/O bottleneck. It also involved structuring the code in a clean, modular way using idiomatic Rust features like iterators and staying within Rust ownership principles. Overall, this project focused on making a product simply from a simple document specification, and performance tuning.
 Here is a multithreaded file reader that allows prefetching of files, and calls the function for the computation and reading in files.

for i in 0..2 {
thread::scope(|s| {
  s.spawn(|| {
    for j in 0..((num_files + (1 - i)) / 2) {
      let curr_file = fs::read(&files[i + 2 * j]);
      let mut curr_file = curr_file.unwrap();
      /* Do decryption/encryption based on user input */
      match (args.reverse, use_iv) {
        (false, false) => data_encrypt(&mut curr_file, &expanded_key),
        (false, true) => data_encrypt_iv(&mut curr_file, &expanded_key, &iv),
        (true, false) => data_decrypt(&mut curr_file, &expanded_key),
        (true, true) => data_decrypt_iv(&mut curr_file, &expanded_key, &iv),
      };

      let _ = fs::write(
        files[i + 2 * j].to_owned() + enc_or_dec,
        &curr_file[0..curr_file.len()],
      );
    }
  });
});