easydes 0.1.6

Encrypt with DES easily in Rust.
Documentation
extern crate clap;

use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command};
use easydes::easydes::*;
use std::fs::File;
use std::io::{Read, Write};

fn main() {
    let arg_matches: ArgMatches = Command::new("easydes")
        .version(VERSION)
        .about("Encrypt and decrypt with DES.")
        .arg(Arg::new("v").short('v').help("Enable verbose logging"))
        .arg(
            Arg::new("triple_des")
                .short('3')
                .long("triple_des")
                .help("Encrypt/Decrypt using Triple DES."),
        )
        .arg(
            Arg::new("key")
                .short('k')
                .long("key")
                .value_name("KEY")
                .help("Encryption/Decryption key")
                .required(true),
        )
        .arg(
            Arg::new("iv")
                .short('i')
                .long("iv")
                .value_name("IV")
                .help("Encryption/Decryption IV. Only used in CBC."),
        )
        .arg(
            Arg::new("if")
                .long("infile")
                .value_name("INPATH")
                .help("Specify the path to the input file.")
                .required(true),
        )
        .arg(
            Arg::new("of")
                .long("outfile")
                .value_name("OUTPATH")
                .help("Specify the path to the output file.")
                .default_missing_value("./output"),
        )
        .arg(
            Arg::new("mode")
                .short('m')
                .value_name("MODE")
                .help("Specify the mode. Default is ECB which doesn't require an IV.")
                .possible_values(["ECB", "CBC"])
                .default_value("ECB"),
        )
        .arg(
            Arg::new("encrypt")
                .short('e')
                .help("Encrypt")
                .action(ArgAction::SetTrue),
        )
        .arg(
            Arg::new("decrypt")
                .short('d')
                .help("Decrypt")
                .action(ArgAction::SetFalse),
        )
        .group(
            ArgGroup::new("direction")
                .arg("encrypt")
                .arg("decrypt")
                .required(true),
        )
        .get_matches();

    let des_mode: Mode = match arg_matches.value_of("mode") {
        Some("ECB") => easydes::easydes::Mode::ECB,
        Some("CBC") => easydes::easydes::Mode::CBC,
        Some(_) => panic!("No such mode"),
        None => easydes::easydes::Mode::CBC,
    };

    let enc_or_dec: Des = match arg_matches.get_one::<bool>("direction") {
        Some(true) => Des::Encrypt,
        Some(false) => Des::Decrypt,
        None => panic!("It was not specified if encryption or decryption should be used."),
    };

    if des_mode == Mode::CBC && !arg_matches.is_present("iv") {
        panic!("We need an IV in CBC mode!");
    }

    let mut input: Vec<u8> = Vec::new();

    if let Some(infile) = arg_matches.value_of("if") {
        let mut f = File::open(infile).unwrap();
        f.read_to_end(&mut input).unwrap();
    }

    let output = match des_mode {
        Mode::ECB => match arg_matches.is_present("triple_des") {
            true => {
                let key_hex_string: &str = arg_matches.value_of("key").unwrap();
                let mut key: [u8; 24] = [0 as u8; 24];
                hex::decode_to_slice(key_hex_string, &mut key).expect("Decoding key failed");

                triple_des_ecb(&key, &mut input.to_vec(), enc_or_dec)
            }
            false => {
                let key_hex_string: &str = arg_matches.value_of("key").unwrap();
                let mut key: [u8; 8] = [0 as u8; 8];
                hex::decode_to_slice(key_hex_string, &mut key).expect("Decoding key failed");

                des_ecb(&key, &mut input.to_vec(), enc_or_dec)
            }
        },
        Mode::CBC => match arg_matches.is_present("triple_des") {
            true => {
                let key_hex_string: &str = arg_matches.value_of("key").unwrap();
                let mut key: [u8; 24] = [0 as u8; 24];
                hex::decode_to_slice(key_hex_string, &mut key).expect("Decoding key failed");

                let mut iv: [u8; 8] = [0 as u8; 8];
                let iv_hex_string = arg_matches.value_of("iv").unwrap();
                hex::decode_to_slice(iv_hex_string, &mut iv).expect("Decoding IV failed");

                triple_des_cbc(&key, &iv, &mut input.to_vec(), enc_or_dec)
            }
            false => {
                let key_hex_string: &str = arg_matches.value_of("key").unwrap();
                let mut key: [u8; 8] = [0 as u8; 8];
                hex::decode_to_slice(key_hex_string, &mut key).expect("Decoding key failed");

                let mut iv: [u8; 8] = [0 as u8; 8];
                let iv_hex_string = arg_matches.value_of("iv").unwrap();
                hex::decode_to_slice(iv_hex_string, &mut iv).expect("Decoding IV failed");

                des_cbc(&key, &iv, &mut input.to_vec(), enc_or_dec)
            }
        },
    };

    let mut outfile =
        File::create(arg_matches.value_of("of").unwrap()).expect("Could not open output file.");
    outfile.write_all(&output).unwrap();
    //println!("{:#02x?}", output);
}